C언어 - 기초 문법에 대해 알고 들어가자
반복문
For 문은 초기식, 조건식 그리고 증가 또는 감소식을 ()안에 기호 ;로 분리하여 사용한다. 3개의 식은 반복을 시작하여 반복을 중단할 때까지의 상황을 판단하기 위해 사용한다. for문에서 사용하는 증감식은 경우에 따라서 증가 또는 감소를 사용한다.
While 문과 do while 문은 거의 비슷하지만 조건을 언제 판단하느냐에 차이가 있다. While 문은 먼저 조건을 판단하여 반복을 결정하고, do while 문은 일단 1번은 반복하고 나서 조건을 판단하여 반복을 결정한다. 따라서 while 문은 조건이 거짓이라면 반복이 이루어지지 않지만 do while 문은 조건이 거짓이라도 1번은 반복을 처리한다. Do while 문에서는 while의 조건식 다음에 ; 이 반드시 사용되어야 하지만 while 문에서는 사용하지 않는다.
처리의 흐름을 조절
Break 문은 어떤 처리의 순서나 흐름을 중단시키는데 사용하며, 반복문에서 사용되어 조건을 만족할 경우에 반복을 중단시키는 곳에서도 사용할 수 있다.
Continue 문은 break 문과 같이 주로 반복문 안에서 사용된다. 그러나 break 문은 반복을 중단시키기 위해 사용하지만 continue 문은 반복을 중단시키지 않고 다음 반복이 이루어지도록 한다.
Goto 문은 break 문과 continue 문과는 달리 프로그램의 실행 순서를 특정한 곳으로 이동한다. 이때 이동할 곳을 지정하기 위해 label 을 사용한다. 즉, goto 문은 실행의 순서를 바꾸는데 사용하므로 goto 문을 너무 자주 사용하면 프로그램을 해석하거나 이해하기가 어려워지는 단점이 있으므로 가능하다면 다른 방법을 이용하는 것이 좋다.
사용자가 정의하는 함수
함수 원형의 선언이란 프로그램 내에서 사용자 정의 함수를 사용하겠다는 것을 컴파일러에 미리 알려주는 역할을 한다. 이때 함수의 데이터 형, 함수이름, 함수에서 사용할 인자들을 표시해준다.
함수 정의 부분은 함수가 처리해야할 기능들을 구체적으로 작성하는 부분이다. 데이터 형 함수 이름, 인자의 사용형식은 함수 원형의 방법과 동일하다. 단, 함수의 결과 값이 있는 경우에는 return 문과 함께 변수 또는 연산식을 사용하며, 결과값이 없는 void 형 함수는 return 문을 생각한다. 함수의 데이터 형은 return 문 다음에 나타난 결과 값의 데이터 형을 의미한다.
매크로 상수는 프로그램 작성단계에서 결정할 수 없는 상수를 정의하는 경우에 사용되며, 매크로의 이름은 일반적인 변수와 구별하기 위해 대문자를 사용한다. 그리고 매크로 상수로 정의된 값은 변수로 사용할 수 없으며 프로그램 내에서 저장된 값의 변경이 불가능하다.
재귀 호출이라 함은 호출된 함수가 실행 중에 자기 자신을 다시 호출하는 것으로 반복적인 호출이 일어난다. 따라서 재귀 호출에서는 무한 반복이 이루어지므로 이를 해결하기 위해 적절한 조건을 주어 함수를 벗어나도록 해 주어야 한다.
기억 클래스
변수에 대한 또 다른 속성인 기억 클래스는 메모리, 즉 기억공간에 데이터를 저장하는 방법을 지시하는 것으로서 프로그램 내에서의 변수에 대한 사용 범위와 변수의 수명을 결정한다. C언어에는 네 가지의 기억 클래스가 있다.
기억 클래스 수명 기억 공간
Auto 일시적 스택
Static 지속적 데이터
Extern 지속적 데이터
register 일시적 CPU 내의 register
지역과 전역은 각각 ‘local’ 과 ‘global’ 의 뜻으로 프로그램 내에서 변수가 사용될 수 있는 범위를 말한다. 따라서 지역 변수는 그 변수의 사용 범위가 어떤 한 함수 안에서만 사용할 수 있도록 제한되는 것이고, 전역 변수는 범위의 제한 없이 프로그램의 모든 함수에서 접근이 가능한 변수이다. 지역 변수와 전역 변수는 변수의 선언 위치에 따라 결정된다. 즉, 함수 또는 복합문 안에서 변수를 선언하면 그 변수는 지역 변수가 되고, 함수 밖에서 변수를 선언하면 전역변수가 된다. 지역 변수의 사용범위는 그 변수가 선언된 함수 내부로 제한되며 함수가 다를 경우에는 같은 이름의 변수를 다시 선언할 수도 있다.
함수의 안에서 선언하는 지역 변수들은 모두 자동 변수에 해당한다. 자동 변수는 함수가 호출되어 실행될 때만 기억 공간이 확보되고 함수의 실행이 종료됨과 동시에 자동으로 소멸되는 변수이다. 자동변수를 선언하기 위해서 auto라는 기억 클래스 지정자를 사용하지만 생략이 가능하다. 자동 변수는 함수가 실행될 때 스택이라는 기억 영역에 일시적으로 공간을 확보하므로 변수를 선언할 때 초기화를 하지 않고 사용할 경우에는 예상하지 못한 오류가 발생한다. 따라서 셈을 누적하기 위해 자동 변수를 선언할 경우에는 반드시 초기화를 해 주어야 한다. 반면 전역 변수의 경우에는 초기화를 해주지 않아도 0으로 초기화된다.
정적이라는 단어는 동적이라는 단어와 반대되는 의미이다. 정적 변수를 선언할 경우에는 static 지정자를 사용하며, 자동 변수와는 달리 프로그램이 종료될 때까지 변수의 수명이 지속된다. 정적 변수는 전역 변수와 같이 초기화를 하지 않아도 0으로 초기화되며 한번 초기화된 정적 변수는 더 이상 초기화되지 않는다. 정적 변수가 함수 내부에서 선언될 경우를 내부 정적 변수라 하고, 함수 밖에서 선언될 경우는 외부 정적 변수라 한다. 내부 정적 변수는 지역 변수로 사용되며, 외부 정적 변수는 전역 변수로 사용되지만 그 범위는 해당 프로그램 파일 내부로 제한되므로 외부 프로그램 파일의 함수에서는 사용할 수 없다. 내부 정적 변수는 함수의 내부에서 선언되고 지역 변수로 사용되지만 자동 변수와는 달리 변수의 수명이 프로그램이 종료할 때까지 지속되므로 자동 변수와는 차이가 있다.
앞에서 정적 변수는 함수 밖에서 선언될 경우 해당 프로그램 파일 내에서만 전역 변수의 역할을 한다고 하였다. 그러나 하나의 프로젝트 프로그램이 여러 개의 모듈 프로그램 파일로 나누어져 있더라도 어떤 모듈의 함수에서도 전역 변수로서 사용하고자 한다면 extern 지정자를 사용합니다. 즉, extern 지정자는 파일 외부에서 선언된 전역 변수를 해당 프로그램 파일 내부에서 전역 변수로 사용할 경우에 지정한다. 비교적 규모가 있는 프로그램들은 처음부터 하나의 프로그램 파일로 만들어지지 않고 기능별로 구분되는 여러 개의 프로그램 모듈로 나누어져 개발된다. 그러나 최종적으로 완성된 프로그램을 만들기 위해서는 여러 개의 모듈들을 각각 컴파일을 한 후에 하나의 통합된 프로그램으로 합쳐야하는데 이 과정을 분할 컴파일이라 한다.
레지스터 변수는 자동 변수와 기능이 동일하지만 메인 메모리인 주기억장치가 아니라 중앙처리장치인 CPU의 레지스터를 사용한다는 점에서 차이가 있다. 레지스터 변수는 주기억장치보다 처리 속도가 상대적으로 빠른 레지스터를 사용하므로 네 가지 기억 클래스 중에서 가장 빠른 처리를 하지만 CPU 레지스터는 개수에 제한이 있으므로 2, 3개 정도만 사용할 수 있다. 레지스터 변수는 크기에도 제한이 있기 때문에 char 형, int 형으로만 사용한다.
배열
배열과 변수는 데이터를 기억시킬 수 있는 공간이라는 점에서 공통점이 있지만 배열은 변수와 달리 번호가 붙은 동일한 데이터 형의 연속된 기억 공간이다.
배열의 첨자가 한 개인 배열을 1차원 배열이라 하는데 1차원 배열을 선언하는 방법에는 다음과 같은 방법이 있다.
1차원 배열 선언 방법 프로그램
배열 크기만 선언 Int korea[4];
배열의 초기화 Int korea[4]={15, 17, 27, 32};
배열 초기화에서 배열 크기 생략 Int korea[]={15, 17, 27, 32};
배열에 저장할 배열 요소들은 동일한 배열 이름을 갖지만 숫자, 즉 배열 첨자에 의해 구별한다. 배열 첨자는 korea[0.2] 나 china[2.6] 과 같이 실수형을 사용할 수 없으며 오직 정수형만을 사용한다.
키보드를 통해 배열 요소를 입력하는 경우에는 표준 입력 함수인 scanf를 사용할 수 있으며 반복문의 제어 변수를 이용하여 각 요소의 값을 구분하여 입력한다.
C언어는 문자에 대한 데이터 형인 char 형은 있으나 두 개 이상의 문자가 연속되는 문자열에 대한 데이터 형은 따로 정의되어 있지 않다. 따라서 문자열을 다루기 위해서는 다른 방법을 사용하는데 문자형 배열을 이용하거나 포인터를 이용할 수 있다.
문자열을 키보드로 입력하거나 출력할 때 표준 입출력 함수인 scanf 와 printf를 사용한다. 숫자를 대상으로 하는 배열의 입출력은 배열 요소별로 첨자를 구분하여 입출력을 하지만 문자열은 첨자를 구분하지 않고 한 번에 입력하고 출력하는 방법을 사용하므로 문자열에 대한 입출력에서 첨자를 사용할 필요가 없다.
2차원 배열은 1차원 배열과는 달리 두 개의 첨자를 사용하는 배열로서 대표적인 예로 행렬을 들 수 있다. 2차원 배열에서 첫 번째 첨자는 행을, 두 번째 첨자는 열을 나타낸다. 2차원배열을 선언하고 초기값을 지정하는 경우에도 첫 번째 첨자의 크기는 생략할 수 있다.
함수 호출에 사용된 변수를 인수, 함수 원형이나 정의에 사용된 변수를 인자라 부른다. 인수가 인자에 전달될 때 변수 자체가 전달되는 것이 아니라 변수에 저장된 값만 전달되므로 함수 정의부분에서 인자가 변하더라도 인수는 영향을 받지 않는다. 함수에서 이와 같은 값의 전달 방법을 값에 의한 호출이라 한다. C언어에서 함수 호출 방법은 두 가지 방법, 즉 값에 의한 호출과 참조에 의한 호출을 사용한다. 배열 역시 변수와 마찬가지로 함수의 인수나, 인자로 사용할 수 있으며 함수의 결과값, 즉 반환값으로도 사용할 수 있다. 함수의 인수로 배열을 사용할 경우에는 배열의 이름만 사용하고 함수의 인자로 배열을 사용할 경우에는 배열을 표시하되 배열의 크기는 생략한다.
포인터
포인터는 메모리상의 어떤 주소를 가리키고, 메모리상의 주소에는 데이터가 저장되므로 결국 포인터는 메모리에 저장된 데이터의 위치를 가리킨다고 할 수 있다.
일반 변수와는 달리 포인터 변수에는 오직 주소만을 저장할 수 있다. 포인터 변수도 값을 기억하는 변수이므로 사용하기 전에 선언해야 하며, 변수와 같이 저장된 값을 다른 주소로 변경시킬 수 있다. 포인터 변수를 선언할 경우에는 일반 변수의 선언과 같이 데이터 형과 변수 이름을 사용하는데 일반 변수와 구별하기 위해서 변수 앞에 간접 연산자 *를 사용한다.
포인터 변수 선언 의미
Char *p; 포인터 변수 p를 선언(변수이름은 *p가 아니라 p임)
포인터 변수 p의 데이터 형이 char 형이 아니라 p가 가리키게 될 주소에 저장된 데이터 형이 char 형이라는 의미
Int *pt; 포인터 변수 pt를 선언
포인터 변수 pt의 데이터 형이 int 형이 아니라 pt가 가리키게 될 주소에 저장된 데이터의 형이 int 형이라는 의미
포인터 변수의 앞에 사용된 간접 연산자 *는 포인터 변수에 저장된 주소가 가리키는 곳의 데이터를 나타낸다. 따라서 포인터가 가리키는 곳의 데이터를 수정한다면 변수에 저장되었던 데이터가 변경된다.
배열 요소들은 메모리 상에 연속된 기억 공간에 저장된다. 배열의 이름은 그 배열의 첫번째 요소가 저장되어 있는 주소를 가리키므로 주소를 가리킨다는 점에서는 배열과 포인터는 유사하다.
C언어에는 문자를 저장하는 char 형은 있지만 문자열을 저장하는 데이터 형은 따로 없으므로 배열 또는 포인터를 이용하여 문자열을 초기화할 수 있다.
[방법 1] char str1[]=”copy”; 또는 char str1[9]=”copy”;
[방법 2] char *str2=”copy”;
배열에 하나의 문자열을 저장하는 경우에는 [방법 1]의 앞부분과 같이 배열의 크기를 생략할 수 있으며, 뒷부분과 같이 배열의 크기를 지정하는 경우에는 문자의 길이보다 하나 더 크게 지정해 주어야 한다. 그러나 포인터 변수에 저장할 경우에는 크기를 지정할 필요가 없다. 포인터 변수는 문자열 자체를 보관하는 것이 아니라 그 문자열이 저장된 첫 번째 주소를 보관하기 때문이다.
포인터 변수에는 주소가 저장되고 주소는 4 byte로 표현된 숫자이므로 포인터 변수나 주소에 대한 연산이 가능하다. 그러나 주소는 양의 정수로 표현하므로 실수 연산은 사용할 수 없다. Int 형의 배열 a에 대해 a+1은 Visual C++의 경우 주소 a에 4를 더한 것과 같으며, Turbo C++의 경우는 2를 더한 것과 같다.
&a[0], (a+0) 그리고 (pt+0)는 동일한 수식이며
&a[n], (a+n) 그리고 (pt+n)의 주소는 모두 같다.
A[0], *(a+0), *(pt+0) 또는 pt[0]은 동일한 수식이며
A[n], *(a+n), *(pt+n) 또는 pt[n]은 모두 같은 값이다.
함수를 호출할 때 인자의 전달 방식에는 두 가지 방법이 있다. 하나는 값에 의한 호출이고 다른 하나는 참조에 의한 호출이다.
포인터 배열이란 여러 개의 포인터 변수를 배열로 사용하는 것이다. 포인터 배열은 문자형 포인터 배열을 사용할 때 유용하게 사용된다.
여러 개의 문자열을 문자형 배열에 저장할 때는 2차원 배열을 사용해야하며, 2차원 배열의 두 번째 첨자의 크기는 저장할 문자열의 길이를 감안하여 충분한 크기로 정해 주어야 하므로 기억의 공간의 낭비가 생기지만 포인터 배열을 이용할 경우에는 필요한 공간만을 사용하게 된다.
일반적으로 포인터는 어떤 변수의 주소를 가리키지만 함수의 주소에 대해서도 포인터 할 수 있다. C 언어에서 문자열 상수, 배열의 이름, 함수의 이름은 모두 포인터 상수이다. C 언어에서 함수의 이름은 그 함수가 시작되는 주소를 나타내는 포인터 상수이므로 함수 포인터를 사용하여 함수를 인자로 전달할 수 있다. 함수 포인터 는 다음과 같은 방법으로 선언한다.
데이터 형 *함수포인터(함수 인자들)
함수 포인터는 프로그램에서 자주 사용하게 될 몇 개의 함수들을 배열에 저장하여 사용하거나 하나의 함수 포인터에 대해 조건에 따라 여러 함수들 중에서 하나의 함수를 포인터로 이용하고자 할 때 사용한다.
함수를 선언할 때 함수의 앞부분에는 그 함수의 결과 값이 어떤 데이터 형인가를 명시해주어야하는데 함수의 결과 값으로 포인터를 사용하는 경우도 있다.
구조체
구조체는 서로 다른 데이터 형을 갖는 변수들을 대표 이름으로 묶어 놓는 것이라고 할수 있다.
새로운 구조체를 정의할 때 키워드 struct를 사용하고, struct 다음에는 그 구조체를 대표하는 이름을 표시해 주어야 한다. 이를 구조체 태그라 하고, 구조체를 구성하는 항목들은 멤버라고 부른다. 구조체 멤버의 이름은 구조체 태그와 다른 이름을 사용해야한다. 구조체 정의에 의해 새로운 데이터 형이 만들어지는 것이므로 구조체 태그가 곧 구조체 형이다.
문자형 포인터에는 문자열을 직접 대입할 수 있지만 문자형 배열에서는 배열 이름이 포인터 상수이므로 초기화를 제외하고는 문자열을 직접 배열에 대입할 수 없으므로 문자열을 복사하는 함수 strcpy를 사용하거나 입력함수 scanf를이용하여 대입하는 방법을 사용한다.
구조체 변수와의 차이점은 단지 첨자가 사용된다는 것이다. 저장된 내용을 출력하는 경우에도 구조체 변수와 마찬가지로 도트 연산자 . 를 이용하고, 첨자를 사용한다.
구조체 변수나 구조체 배열에 대해 멤버의 데이터를 출력할 경우 도트 연산자 ‘.’ 을 사용하지만 구조체 포인터에 대해서는 간접 연산자 ‘->’을 사용한다.
함수의 인자로 구조체 변수를 사용하는 것은 일반 변수를 함수의 인자로 사용하는 것과 차이가 없다. 함수를 정의할 때 인자의 데이터 형을 사용하는 것과 마찬가지로 구조체 형을 함수 인자의 데이터 형으로 사용한다.
함수의 인자로 구조체 포인터를 이용하는 방법은 구조체 변수를 이용하는 방법과 달리 주소에 의한 전달 방법을 사용하므로 호출된 함수에서의 변화는 구조체에 직접적인 영향을 준다. 인자로 포인터를 사용할 때는 구조체 변수에 대해 주소 연산자를 사용하거나 포인터 변수를 사용할 수 있다.
함수의 인자로 구조체 배열을 사용할 때는 구조체 형 포인터로 선언한다. 함수 호출에서 인수는 배열 이름을 그대로 사용하는데 이는 배열 이름이 포인터 상수이기 때문이다. 따라서 구조체 배열 첫 번째 요소의 주소가 함수의 인자인 구조체 포인터에 전달된다.
구조체 정의 부분만 따로 user.h라는 이름의 텍스트 파일로 저장하되 메모장 프로그램을 이용하여 저장할 수 있다. 구조체가 user.h라는 파일 이름으로 저장되었다면 #include 문장을 이용하여 구조체를 불러들여 사용할 수 있다.
구조체는 모든 데이터 형을 포함할 수 있기 때문에 구조체의 멤버로 또 다른 구조체를 사용할 수 있으며, 이를 구조체 안의 구조체, 즉 중첩된 구조체라 한다. 중첩된 구조체에서도 초기화를 사용할 수 있으며, 중첩된 구조체 변수에 데이터를 저장하는 경우에는 연산자 ‘.’을 여러 번 사용하게 된다. 구조체에 대해 배열 혹은 포인터 변수를 사용할 수 있듯이 중첩된 구조체에서도 같은 방법으로 사용한다.
자기 참조 구조체란 멤버의 데이터 형으로 자신의 구조체 형을 사용한다는 의미이다. 구조체 자체를 멤버로 사용할 수는 없지만 구조체의 데이터 형과 같은 포인터를 멤버로 가지는 것은 가능하다. 이렇게 함으로써 결국 포인터 멤버는 자기 자신을 가리키게 된다. 자기 참조 구조체는 자료 구조에서 연결 리스트나 트리를 구현하는데 있어서 필요한 구조체이다.
공용체
공용체는 멤버들을 구성하고 멤버에 데이터를 저장하거나 불러오는 방법은 구조체와 동일하지만 기억공간을 사용하는 것에 차이가 있다. 공용체를 선언할 때는 키워드 struct 대신에 union을 사용한다. 구조체 멤버들은 각 멤버의 크기로 구분된 기억공간을 사용하지만 공용체의 기억공간은 멤버의 데이터 크기 중에서 가장 큰 데이터 형의 크기로 정해진다. 따라서 char name[10]은 10개의 byte 크기이고 int id는 4byte 크기이므로 10개 byte 공간을 공동으로 사용한다. 공용체는 기억공간을 공동으로 사용하기 때문에 하나의 멤버값이 바뀌면 나머지 멤버들의 값도 동시에 바뀌게 되므로 모든 멤버가 동시에 기억공간을 공유하여 사용할 수 없고, 한번에 단 하나의 멤버만 기억공간을 사용할 수 있다. 그러므로 공용체 변수의 초기화도 어떤 멤버에 대해서든 하나의 데이터만 초기화로 사용할 수 있다.
열거형, enum
열거형은 구조체나 공용체와 같이 사용자가 정의하는 또 다른 형태의 데이터 형으로서 상수들의 집합을 정수형으로 대신하여 표현한다. 열거형 변수를 선언하는 형식은 다음과 같다.
Enum tag_name { 상수 list }
열거형은 키워드 enum을 사용하며 tag_name은 상수들의 집합을 대표하는 이름이다.
비트 필드
비트 필드는 구조체의 멤버들을 byte 단위가 아니라 bit 단위로 처리할 수 있는 구조체를 말한다.
파일처리
컴퓨터에서 파일로 저장하거나 파일을 읽을 때 다음과 같이 공통적인 절차에 따라 진행한다.
처리 단계 파일 입력(불러오기) 파일 출력(저장하기)
단계 1 파일 열기(open) 파일 열기(open)
단계 2 데이터 읽기(read) 데이터 쓰기(write)
단계 3 파일 닫기(close) 파일 닫기(close)
텍스트 방식의 파일 다루기
파일 열기는 함수 fopen을 사용한다. 함수 fopen 은 정상적으로 처리되었을 경우 파일에 대한 포인터를 반환하고, 오류가 발생된 경우에는 NULL 값을 반환한다. 함수 fopen은 헤더파일 <stdio.h>에 정의되어 있다.
fopen 함수원형 FILE *fopen(char *filename, char *filemode)
함수인자 *filename 처리하고자 하는 파일 이름
*filemode 파일 접근 방식을 결정하는 모드(mode)
반환값 파일 열기에 성공하면 유효한 파일 포인터를, 실패할 경우에는 NULL을 반환
함수 fopen의 첫 번째 인자인 filename은 대상 파일의 이름이며, 두 번째 인자인 filemode는 파일 접근 방식을 결정하는 모드이다. 파일 모드는 크게 두가지, 파일 입력모드와 파일 출력모드가 있다.
구분 Mode 의미 역할
파일입력 R Read(읽기) 파일을 읽기 전용으로 open. 파일을 open할 수 없다면 NULL을 반환
파일출력 W Write(쓰기) 파일을 생성하고 쓰기 전용으로 open. 같은 이름의 파일이 있다면 내용을 삭제하고 새로운 내용으로 파일을 생성
s Append(추가) 추가 쓰기 모드로 open. 같은 이름의 파일이 있다면 마지막 부분에 내용을 추가하고, 파일이 없다면 새로 만듦
파일 모드는 읽기, 쓰기, 추가의 세 가지 모드 외에 추가적으로 이러한 모드를 혼합하여 사용하는 혼합 모드들이 있다. 함수 fopen은 파일 열기에 성공하면 유효한 파일 포인터를, 실패할 경우에는 NULL을 반환한다. 실패할 경우, 즉 NULL을 반환할 경우에는 파일과 관련된 어떠한 작업도 처리할 수 없으므로 이 경우에는 대부분 다음과 같이 프로그램을 종료하는 함수 exit을 사용한다. 함수 exit은 헤더파일 <stdlib.h>를 필요로 한다.
파일과 그 파일을 처리하려는 원시 프로그램이 동일한 폴더에 존재한다면 파일 이름만 정확히 기술하면 되지만, 파일이 동일한 폴더에 존재하지 않는다면 파일의 경로를 모두 기술해 주어야 한다.
문자열에서 \의 사용은 \n 또는 \t와 같이 제어문자를 의미하므로, 경로를 나타내기 위해서 \를 사용할 경우에는 두 번 연속으로 사용해아 한다.
파일 처리를 위해 파일을 open할 때 오류가 발생하지 않았다면 파일 쓰기나 파일 읽기 작업을 할 수 있는대 이때 파일 입출력과 관련된 라이브러리 함수를 사용한다.
파일 쓰기나 파일 읽기 처리가 모두 끝났다면 프로그램을 종료하기 전에 열려진 파일을 모두 닫아 주어야 한다. 파일이 닫혀지지 않는 상태에서는 그 파일을 다시 열 수 없다.
fclose 함수원형 Int fclose(FILE *fp)
함수인자 fp 함수 fopen을 사용하면 얻는 유효한 파일 포인터
반환값 파일 닫기에 성공하면 0을, 실패하면 E0F를 반환
파일 입출력 함수
텍스트 방식의 파일에 대한 파일 쓰기와 파일 읽기에는 다음과 같은 라이브러리 함수들을 사용한다. 이 함수들은 모두 헤더파일 <stdio.h>를 필요로 하므로 별도의 헤더파일을 불러올 필요는 없다.
문자 단위의 파일처리
파일 출력, 즉 프로그램에서 만들어진 데이터를 파일에 저장하기 위해서는 함수 fopen의 인자로 출력할 파일의 이름과 파일 출력 모드인 ‘w’를 사용한다.
FILE *pt;
Pt=fopen(“출력할 파일 이름”, “w”);
문자를 파일에 출력하는 함수로 fputc와 putc가 있는데 사용방법은 동일하며 같은 기능을 한다.
파일 입력, 즉 파일에 저장된 데이터를 프로그램을 통해 읽기위해 함수 fopen의 인자로 읽을 파일의 이름과 파일 입력 모드인 “r”을 사용한다.
FILE *pt;
Pt=fopen(“읽을 파일 이름”, “r”);
파일에 저장된 데이터를 문자 단위로 읽는 함수 fgetc는 다음과 같이 함수 인자로 파일 포인터를 사용한다. 또 다른 함수로 getc가 있으며 사용방법과 기능은 동일하다.
fgetc 함수원형 Int fgetc(FILE *fp);
함수인자 fp 함수 fopen을 사용하여 얻은 유효한 파일 포인터
반환값 파일로부터 읽은 문자를 반환, 오류가 발생한 경우 E0F를 반환
getc 함수원형 Int fgetc(FILE *fp);
함수인자 fp 함수 fopen을 사용하여 얻은 유효한 파일 포인터
반환값 읽은 문자를 정수형으로 변환하여 반환, 오류가 있는 경우에는 E0F를 반환
파일의 끝에 도달했는지를 확인하는 함수로는 feof가 있다.파일의 끝에 도달했다면 0이 아닌 정수값을 반환하고, 그렇지 않은 경우에는 0값을 반환한다.
feof 함수원형 Int feof(FILE *fp);
함수인자 fp 함수 fopen을 사용하여 얻은 유효한 파일 포인터
반환값 파일의 끝에 도달했다면 0이 아닌 정수값을 반환하고, 그렇지 않은 경우에는 0값을 반환
문자열 단위의 파일처리
문자열을 파일로 출력하는 함수로는 fputs을 사용한다. 함수 fputs는 인자로 사용된 문자열을 해당 파일로 출력한다
fputs 함수원형 Int fputs(char *str, FILE *fp);
함수인자 str 출력하고자 하는 문자열 상수 또는 변수
fp 함수 fopen을 사용하여 얻은 유효한 파일 포인터
반환값 성공적으로 이루어져싿면 0이 아닌 정수값을 반환, 그렇지 않으면 E0F를 반환
입출력 형식을 지정하는 파일 처리
형식을 지정한다는 의미는 화면 출력 함수인 printf에서 변수의 데이터 형에 맞게 형식 지정자인 %d, %f 또는 %s 등을 사용하여 출력할 데이터의 형식을 지정한다는 것이다. 파일 출력함수의 하나인 fprintf는 함수의 첫 번째 인자로 파일 포인터가 사용되는 것을 제외하고는 그 사용법이 화면 출력함수인 printf와 동일하다. 함수 fprintf는 데이터를 파일에 저장할 때 주어진 형식에 맞추어 출력한다.
fprintf 함수원형 Int *fprintf(FILE *fp, char *format, 변수 list);
함수인자 fp 함수 fopen을 사용하여 얻은 유효한 파일 포인터
format 형식 제어 문자열
변수 list 출력하고자 하는 변수들의 list
반환값 출력될 내용의 byte 크기를 반환, 오류가 발생한 경우는 E0F를 반환
파일에 저장된 데이터를 주어진 형식에 맞게 읽는 함수인 fscanf는 세 개의 인자를 필요로 한다. 함수의 첫번째 인자로 파일 포인터가 사용된다는 것 외에 입력함수인 scanf 와 사용방법이 동일하다.
fscanf 함수원형 Int *fscanf(FILE *fp, char *format, 변수 list);
함수인자 fp 함수 fopen을 사용하여 얻은 유효한 파일 포인터
format 형식 제어 문자열
변수 list 출력하고자 하는 변수들의 list
반환값 정상적으로 읽은 필드의 개수를 반환, 오류가 발생한 경우는 E0F를 반환