70.2 서식을 지정하여 파일에서 문자열 읽기

이제 앞에서 생성한 hello.txt 파일의 내용을 읽어보겠습니다. 파일을 읽을 때도 fopen 함수로 파일을 열어서 파일 포인터를 얻은 뒤 fscanf 함수로 서식을 지정하여 파일의 내용을 읽습니다(stdio.h 헤더 파일에 선언되어 있습니다).

  • fscanf(파일포인터, 서식, 변수의주소1, 변수의주소2, …);
    • int fscanf(FILE * const _Stream, char const * const _Format, ...);
    • 성공하면 읽어온 값의 개수를 반환, 실패하면 EOF(-1)를 반환

다음 내용을 소스 코드 편집 창에 입력한 뒤 Ctrl+F5 키를 눌러서 실행해보세요.

file_read_format.c

#define _CRT_SECURE_NO_WARNINGS    // fopen 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>     // fopen, fscanf, fclose 함수가 선언된 헤더 파일

int main()
{
    char s1[10];
    int num1;

    FILE *fp = fopen("hello.txt", "r");    // hello.txt 파일을 읽기 모드(r)로 열기.
                                           // 파일 포인터를 반환

    fscanf(fp, "%s %d", s1, &num1);   // 서식을 지정하여 파일에서 문자열 읽기

    printf("%s %d\n", s1, num1);      // Hello 100: 파일에서 읽은 값을 출력

    fclose(fp);    // 파일 포인터 닫기

    return 0;
}

실행 결과

Hello 100

먼저 fopen 함수를 사용하여 hello.txt 파일을 읽기 모드(r)로 엽니다.

FILE *fp = fopen("hello.txt", "r");    // hello.txt 파일을 읽기 모드(r)로 열기.
                                       // 파일 포인터를 반환

fscanf 함수는 파일 포인터를 넣는다는 점 말고는 scanf 함수와 사용법이 같습니다. 즉, 파일에서 문자열을 읽은 뒤 서식에 맞추어서 값을 변수에 저장합니다. 여기서는 서식을 "%s %d"로 지정했으므로 "Hello" 부분은 문자 배열 s1에 저장되고, 100 부분은 정수형 변수 num1에 저장됩니다.

fscanf(fp, "%s %d", s1, &num1);    // 서식을 지정하여 파일에서 문자열 읽기

printfs1num1의 값을 출력해보면 "Hello"와 100이 나옵니다.

printf("%s %d\n", s1, num1);       // Hello 100: 파일에서 읽은 값을 출력

마찬가지로 파일 읽기 작업이 끝났다면 fclose 함수로 파일 포인터를 닫아줍니다.

fclose(fp);   // 파일 포인터 닫기

서식을 지정하여 파일에서 문자열을 읽는 과정을 그림으로 나타내면 다음과 같습니다.

그림 70‑2 서식을 지정하여 파일에서 문자열 읽기

fprintf 함수는 stdout 매크로를 활용해서 화면에 문자열을 출력했는데 fscanf도 비슷한 사용 방법이 있지 않을까요? fscanf 함수는 stdin 매크로를 활용하면 사용자가 입력한 값을 변수에 저장할 수 있습니다.

char s1[10];
int num1;
fscanf(stdin, "%s %d", s1, &num1);    // 서식을 지정하여 표준 입력(stdin)에서 문자열 읽기

즉, fscanf(stdin, ...);scanf 함수와 동작이 같습니다.

참고 | 파일 스트림

fprintf, fscanf 등의 함수의 매개변수에서 파일 포인터 부분을 보면 FILE* const _Stream와 같이 스트림(stream)이라고 되어 있습니다. 보통 파일 포인터를 파일 스트림이라고도 하는데 스트림은 물 등의 액체가 흐르는 것을 뜻합니다. 파이프 속에 물이 계속 흘러다니는 것처럼 파일 스트림도 파일의 데이터를 연속적으로 처리한다고 해서 스트림입니다.

즉, 파일에서 데이터를 처리할 때마다 매번 파일을 여는 것이 아니라 파일 스트림을 한 번 생성해서 계속 데이터를 쓰거나 가져오는 방식이죠. 여기서 fopen으로 파일을 읽기 전용으로 열면 입력 스트림, 쓰기 전용으로 열면 출력 스트림, 읽기/쓰기로 열면 입출력 스트림입니다. 파일 모드에 따라 단방향, 양방향이 되죠. 마찬가지로 stdin은 입력 스트림, stdout, stderr는 출력 스트림입니다.