C 프로그래밍 기초
chapter 10. 표준입출력 및 파일입출력
10.1 문자와 문자열의 입출력 표준 입출력은 주로 키보드로부터 입력받고 화면에 출력하기 위한 함수들을 제공 파일 입출력은 파일로부터의 입출력을 위한 함수들을 제공 이들 함수들을 사용하기 위해서는 <stdio.h>라는 헤더 파일을 포함
10.1 문자와 문자열의 입출력 putchar() 함수 ch 문자를 화면에 출력하는 함수 ch가 int형이지만 문자로 변환되어 출력 만약, 출력시 에러가 발생하면 EOF가 리턴 EOF는 stdio.h에 정의된 매크로로서 주로 -1의 값을 나타내며, 파일의 끝을 나타내는 의미로 사용 int putchar(int ch);
10.1 문자와 문자열의 입출력 getchar() 함수 키보드에서 입력된 한 문자가 리턴된다. 이 입력은 엔터키가 눌려질 때까지 계속 저장되었다가 엔터키가 눌려지는 순간에 입력된다. int getchar(void);
10.1 문자와 문자열의 입출력 a b c d \n 예) 입력 버퍼에 저장 -> 출력 #include <stdio.h> void main(void) { char ch; do { ch = getchar(); // 문자 입력 putchar(ch); // 문자 출력 } while(ch != '\n'); } 입력 abcd☜ 버퍼에 저장 -> 출력 abcd a b c d \n
예제 10-1[p289] 한 줄의 문자들을 입력하여 모든 소문자를 대문자로 바꾸어 출력하는 프로그램이다. C에서는 소문자를 대문자로 바꾸는 함수 toupper()와 대문자를 소문자로 바꾸는 tolower() 함수가 제공된다. 이 함수를 사용할 때는 ctype.h 헤더파일이 필요하다. #include <stdio.h> #include <ctype.h> void main(void) { char ch; char upper_ch; while((ch = getchar()) != '\n') { upper_ch = toupper(ch); putchar(upper_ch); } }
10.1 문자와 문자열의 입출력 getc(), getchar(), getch(), getche() 함수 getc(), getchar() 함수는 선행 파일 <stdio.h>가 필요 getc() => fp 파일로부터 한 문자를 읽어 리턴한다. getchar() => 한 줄의 스트림을 읽을 때 사용된다. getch(), getche() 함수는 선행 파일 <conio.h>가 필요, 대화형에 사용하기 위해 제공되는 함수로 getchar()와 다른 점은 키를 누르는 순간에 입력이 된다는 점과 엔터키를 눌렀을 때 입력되는 문자는 ‘\r’이 된다는 점이 다르다. 어떤 컴파일러는 이 함수를 제공하지 않으므로 주의해야 한다. int getc(FILE *fp) int getchar(void); int getch(void); int getche(void);
char *gets(char *str); 10.1 문자와 문자열의 입출력 gets() 함수, puts() 함수 gets()는 엔터키가 눌러질 때까지의 문자열이 str에 입력 만약 입력에 에러가 있으면 널(NULL) 포인터가 리턴 puts()는 str에 있는 문자열을 출력하는 함수로서 에러가 발생하면 EOF가 리턴 gets()와 scanf(), puts()와 printf()의 비교 (5장 참조) char *gets(char *str); int puts(char *str);
10.2 printf() 함수와 scanf()함수 출력된 문자들의 수를 리턴한다. 만약 에러가 발생하면 음수를 리턴한다. control-string은 두 가지 항목을 가지고 있다. 하나는 출력할 문자들이고, 다른 하나는 형식 지정자이다. 모든 형식 지정자는 %로 시작하며, printf() 함수에 사용되는 형식 지정자는 표 10-1(p291)과 같다. int printf(char *control-string, ...);
10.2 printf() 함수와 scanf()함수 지정자 의 미 %c 문자 %d 부호가 있는 정수로서 10진수 %i %e 과학 계산용 표기(소문자 ‘e’) %E 과학 계산용 표기(대문자 ‘E’) %f 실수로서 10진수 %g %e와 %f 중 더 짧은 표현을 사용한다. %G %E와 %f 중 더 짧은 표현을 사용한다. %o 부호가 없는 정수로서 8진수 %s 문자열 %u 부호가 없는 정수로서 10진수 %x 부호가 없는 정수로서 16진수(소문자) %X 부호가 없는 정수로서 16진수(대문자) %p 포인터를 출력한다. %n 관련된 인자는 그때까지 출력된 문자들의 수를 저장할 정수형 변수의 포인터가 되어야 한다. %% % 부호를 출력한다.
10.2.1.1 정수의 출력 예) #include <stdio.h> void main(void) { int i; { int i; i = 3815; printf("%d %o %x %X %u\n", i, i, i, i, i); printf("%ld, %sd", 43215, (short)42); } /* %d와 %i는 같으며, %u는 부호 없는 수, %o는 8진수 정수, %x와 %X는 16진수 정수를 출력, %x와 %X의 차이는 출력되는 16진수 A에서 F의 문자의 사용을 소문자로 할 것인가 아니면 대문자를 쓸 것인가를 나타낸다. 이들 지정자들에 h와 l을 부가하여 short와 long형을 출력 가능하다. */
10.2.1.1 정수의 출력 예) #include <stdio.h> void main(void) { { int i = 3521; printf("%9d\n", i); printf("%5d\n", i); printf("%5d%-8dxyz", i, i); printf("%08d\n", 3241); printf("%.8d\n", 3241); }
10.2.1.2 실수의 출력 일반 표기와 과학 계산용 표기의 두 가지 방식 존재 일반 표기는 %f를 사용하고, 과학 계산용 표기는 %e와 %E가 사용된다. 이들 지정자에 l과 L을 사용하여 double과 long double형을 출력할 수 있다. 예) #include <stdio.h> void main(void) { float f; f = 314.1573568; printf("%f\n", f); printf("%e %E\n", f, f); }
%[-] [필드 너비] [.] [소수점 이하 자릿수] 지정자 10.2.1.2 실수의 출력 %[-] [필드 너비] [.] [소수점 이하 자릿수] 지정자 예) #include <stdio.h> void main(void) { float f; f = 314.1573568; printf("%15f\n", f); printf("%15.3f%15.3E\n", f, f); printf("%-15.3f%-15.3E\n", f, f); printf("%8.3f%8.3E\n", f, f); } 예제 실행결과
10.2.3 기타 %p는 주소를 출력하기 위한 것으로 16진수로 출력된다. %s는 문자열 출력을 위한 것으로 아래와 같은 경우 문자열이 짤린다. %.10s는 10칸을 잡아 출력하라는 의미 예) #include <stdio.h> void main(void) { printf("%s\n", "Not all of this will be printed"); printf("%.10s\n", "Not all of this will be printed"); }
예제 10-2 (p296) rand() 함수는 난수(random number)를 만들어 주는 함수이며, 이것을 위해서 stdlib.h 파일이 필요하다. #include <stdio.h> #include <stdlib.h> void main(void) { int i; for(i = 0 ; i < 20 ; i++) printf("%10d%10d%10d\n", rand(), rand(), rand() ); }
int scanf(char *control-string, ... ); scanf() 함수는 읽어들인 필드들의 수를 반환하고, 에러가 발생하면 EOF가 리턴된다. 구체적인 사항들은 아래와 같다. 입력 데이터는 공백 문자, 탭, 또는 뉴라인 문자에 의하여 분리된다. ▪%x와 %o는 부호 없는 16진수와 8진수를 읽기 위한 지정자이며, %d, %x, %o에 h를 붙여 short 형을, l을 붙여 long형의 입력을 위해 사용된다. ▪%e, %f, %g는 실수의 입력을 위해 사용되면 l을 붙여 double형을, L을 붙여 long double을 위해 사용된다.
10.3 scanf() 함수 표 10-2 형식 지정자 형식 지정자 의 미 %c 문자를 읽는다. %d 의 미 %c 문자를 읽는다. %d 10진수로 된 정수를 읽는다. %i %e 실수를 읽는다. %f %g %o 8진수로 된 부호가 없는 정수를 읽는다. %s 문자열을 읽는다. %x 16진수로 된 부호가 없는 정수를 읽는다. %p 포인터를 읽는다. %n 지금까지 읽은 문자들의 수에 해당하는 정수값을 받아들인다. %u 10진수로 된 부호가 없는 정수를 읽는다. %[] 문자들을 찾는다.
10.3 scanf() 함수 [예] int a, b, c; short d; long e; scanf("%d %x %o", &a, &b, &c); scanf("%hd %ld", &d, &e); printf("%d %d %d %hd %ld", a, b, c, d, e); <입력> -25 25 25 43 42431 <출력> -25 37 23 43 42431
10.3 scanf() 함수 %s는 문자열의 입력을 위해 사용된다. 그러나 이렇게 입력되면 공백까지만 입력 데이터로 간 주한다. 따라서 주로 gets()를 많이 쓴다. [예] char str[100]; scanf("%s", str); printf("%s", str); <입력> This is a string <출력> This
10.3 scanf() 함수 %p는 기억 장소의 주소를 입력하기 위해 사용된다. 특정한 문자들만을 입력하기 위하여 스캔셋(scanset)이라는 것을 사용한다. 스캔셋을 아래와 같은 방법으로 지정하여 사용한다. ① 특정한 문자들의 지정 % [문자 문자 문자… 문자] 예) char s1[100], s2[100]; scanf("%[ABC]%[XYZ]", s1, s2); printf("%s\n%s", s1, s2); <입력> ACBAXXYZAC <출력> ACBA XXYZ // s1에는 A 또는 B 또는 C 문자만 입력되고, A, B, C가 아닌 문자가 나오면 다음 입력이 시작된다. ② -를 사용하여 문자들의 범위를 지정한다 %[A-Z]는 A에서 Z까지의 문자를 나타낸다. ③ ^를 사용하여 이 문자들에 포함되지 않는 문자들을 지정한다. %[^01234]는 0, 1, 2, 3, 4를 제외한 모든 문자를 나타낸다.
10.3 scanf() 함수 %*를 사용하여 특정 문자의 입력을 생략한다. 예) int a, b; scanf("%d%*%d", &a, &b); <입력> 214-323 //a에 214가 입력되고 -는 건너뛰어 b에 323이 입력된다.
10.3 scanf() 함수 필드 너비를 사용하여 입력될 데이터의 칸 수를 지정할 수 있다. 예) int d1, d2; 예) int d1, d2; char str[100]; scanf("%3d%2d", &d1, &d2); <입력> 53242 // d1에는 532, d2에는 42, s1에는 17개의 문자, 즉 “This is a string”이 입력된다.
10.3 파일 입출력 파일로부터의 입출력을 위한 표준함수들을 제공 <stdio.h> 헤더파일에 정의 이 헤더파일에는 표준 입출력 및 파일 입출력을 위한 매크로 타입 및 함수 등이 정의되어 있다. 먼저 파일 입출력의 위한 간단한 예를 보고 기본적인 개념을 이해한 후 상세한 설명을 하겠다. 4장에서 약간 언급한 파일 입출력을 상세하게 설명하기로 한다.
예제 10-3 (p301) 아래 프로그램은 in.dat 파일로부터 데이터를 입력하여 합과 평균을 구한 후 그 결과를 out.dat 파일에 저장하는 프로그램이다. #include <stdio.h> void main(void) { float x, sum, avg; int k; FILE *fp, *fpo; fp = fopen("in.dat", "r"); fpo = fopen("out.dat", "w"); sum = 0.0; for(k = 1; k <= 10; k++){ fscanf(fp,"%f", &x); printf("%f ", x); sum = sum+x; } avg = sum / 10; fprintf(fpo, "Sum is %f\n", sum); fprintf(fpo, "Average is %f\n", avg); fclose(fp); fclose(fpo); }
예제 10-3 (p301) (계속) 위 프로그램을 실행하기 위해서는 아래와 같은 두 개의 입력파일과 출력파일이 필요하다. 입력파일의 데이터는 임의로 작성되어 in.dat에 저장되어 있다. 출력 파일(out.dat)은 입력파일에 저장된 데이터를 이용하여 프로그램 실행결과 생성된 파일이다. 입력 파일(in.dat) 출력 파일(out.dat) 10.4 34.6 4.5 5.6 3.5 2.4 2.4 3.5 78.9 34.6 Sum is 180.399994 Average is 18.039999
예제 10-3 (p301) (계속) 프로그램 설명 FILE *fp, *fpo; fp = fopen("in.dat", "r"); C 프로그램에서는 파일을 사용할 때 파일 이름 대신 파일 포인터를 사용 fp와 fpo는 stdio.h에 정의되어 있는 FILE 타입을 가리키는 포인터로 선언 fp = fopen("in.dat", "r"); fpo = fopen("out.dat", "w"); in.dat는 읽기 목적으로(“r”) 열어서 그 파일 포인터를 fp에 저장하였고, out.dat 파일은 쓰기 목적으로(“w”) 열어서 그 파일 포인터를 fpo에 저장하였다. 이후에 in.dat 파일에 관련된 것은 fp를 사용하여 접근하고, out.dat 파일에 관련된 것은 fpo를 사용하여 접근 fscanf(fp, "%f", &x); fp 파일로부터 하나의 실수를 읽어 x에 저장하는 문이다. fprintf(fpo, "Sum is %f\n", sum); fpo 파일 포인터가 지정하는 곳에 “Sum is …”를 Tm라는 문장이다. fclose(fp); fclose(fpo); 모든 작업이 끝나면 파일을 더 이상 사용할 필요가 없기 때문에 닫기를 해야 한다.
FILE *fopen(char *fname, char *mode); 10.4 파일의 열기 및 닫기 10.4.1 fopen() 함수 파일 이름이 fname인 파일을 mode 접근 방법으로 열어서 파일 포인터를 리턴한다. fname은 파일 이름을 나타내는 문자열이고, mode는 사용 목적을 나타내는 문자열이다. mode의 종류는 표 10-3과 같다. 파일을 여는 작업이 성공적이면 파일 포인터를 리턴하고, 그렇지 않고 에러가 발생했으면 널 포인터인 NULL 값을 리턴한다. FILE *fopen(char *fname, char *mode);
10.4.1 fopen() 함수 예) FILE *fp; if( (fp = fopen("in.dat", "r")) == NULL ) { printf("파일 open 에러\n"); exit(1); } //파일 열기에 에러가 생겼는가를 검사하는 부분이다. 파일은 크게 나누어 두 가지 타입으로 나눌 수 있다. 즉, 텍스트 파일과 이진 파일(binary file)이다.
10.4.1 fopen() 함수 [표 10-3] 파일 입출력 모드 모 드 의 미 r w a rb wb ab r+ w+ a+ [표 10-3] 파일 입출력 모드 모 드 의 미 r 읽기 위해 텍스트 파일을 연다 w 쓰기 위해 텍스트 파일을 생성한다. a 텍스트 파일에 추가한다. rb 읽기 위해서 2진 파일을 연다. wb 쓰기 위해서 2진 파일을 생성한다. ab 2진 파일에 추가한다. r+ 읽기와 쓰기를 위해 텍스트 파일을 연다 w+ 읽기와 쓰기를 위해 텍스트 파일을 생성한다. a+ 읽기와 쓰기를 위해 텍스트 파일을 추가하거나 생성한다. r+b 읽기와 쓰기를 위해 2진 파일을 연다. w+b 읽기와 쓰기를 위해 2진 파일을 생성한다. a+b 읽기와 쓰기를 위해 2진 파일을 추가한다.
10.4.1 fopen() 함수 fopen() 함수의 mode에 대하여 좀더 상세히 설명하면, 읽기 모드로 파일을 열 경우, 파일이 존재하지 않으면 에러이다. 쓰기 모드로 파일을 열 경우 파일이 없으면 새로 만들어지고, 있으면 그 파일 속의 모든 내용이 없어진다. 추가 모드는 원래 파일은 그대로 있고 파일의 끝에 추가하기 위해 사용되는 모드이다. 이 때 파일이 존재하지 않으면 새로운 파일이 생성된다. “r+”와 “w+”의 차이점은 파일이 존재하지 않을 때 “r+”는 파일을 생성하지 않으나 “w+”는 파일을 생성한다. 또한, 파일이 존재할 때 “w+”는 파일의 내용을 지우나 “r+”는 파일을 지우지 않는다.
이를 버퍼 비우기(flushing the buffer)라 한다. 10.4.2 fclose() 함수 int fclose(FILE *fp); fp가 가리키는 파일(앞으로는 간단히 fp 파일이라 함)을 닫는다. 이 때 디스크에 쓸 내용이 버퍼에 남아 있으면 디스크에 저장시킨다. 이를 버퍼 비우기(flushing the buffer)라 한다. fclose()가 정상적으로 수행되면 0을 리턴하고 그렇지 않으면 EOF가 리턴된다.
10.5 파일에 문자와 문자열 입출력 10.5.1문자 입출력 입력형식 fp 파일로부터 한 문자를 읽어 리턴한다. 에러가 생겼거나 파일의 끝에 도달했으면 EOF를 리턴한다. int fgetc(FILE *fp); int getc(FILE *fp);
예제 10-4 “test.dat” 파일의 내용을 한 문자씩 읽어 화면에 출력하는 프로그램 test.dat #include <stdio.h> #include <stdlib.h> void main(void) { char ch; FILE *fp; if((fp = fopen("test.dat", "r")) == NULL) { printf("파일 열기 에러\n"); exit(1); } ch = fgetc(fp); while(ch != EOF) { putchar(ch); ch = fgetc(fp); fclose(fp); } test.dat This is example. Hello! This is my file.
예제 10-5 “source.dat” 파일의 내용을 “dest.dat”에 복사하는 프로그램이다. #include <stdio.h> #include <stdlib.h> void main(void) { char ch; FILE *sr, *des; if((sr = fopen("source.dat", "r")) == NULL) { printf("파일 열기 에러\n"); exit(1); } if((des = fopen("dest.dat", "w")) == NULL) { ch = fgetc(sr); while(ch != EOF) { fputc(ch, des); fclose(sr); fclose(des);
예제 10-5 (계속) source.dat dest.dat #include <stdio.h> void main(void) { printf("Welcome C program.\n"); } #include <stdio.h> void main(void) { printf("Welcome C program.\n"); }
예제 10-6 “testfile.txt”를 읽어와 디스플레이 해주는 예제이다. #include <stdio.h> #include <stdlib.h> void main(void) { char ch; FILE *fp; if((fp = fopen("testfile.txt", "r")) == NULL) { printf("Cannot open file\n"); exit(1); } ch = fgetc(fp); printf("open file's content \n\n"); while(ch != EOF) { putchar(ch); ch = fgetc(fp); fclose(fp); }
예제 10-7 명령어라인 인자(main() 함수의 인자)를 사용하여 이 프로그램의 실행 파일이 copy일 때, copy source.dat dest.dat와 같은 명령이 수행되면 복사가 되는 프로그램이다. #include <stdio.h> #include <stdlib.h> void main(int argc, char *argv[]) { char ch; FILE *sr, *des; if((sr = fopen(argv[1], "r")) == NULL) { printf("파일 열기 에러\n"); exit(1); }
예제 10-7 (계속) if((des = fopen(argv[2], "w")) == NULL) { printf("파일 열기 에러\n"); exit(1); } ch = fgetc(sr); while(ch != EOF) { fputc(ch, des); ch = fgetc(sr); fclose(sr); fclose(des); }
예제 10-8 “This is a file system test”이라는 문자열을 지정한 파일에 저장하는 간단한 예제이다. 먼저 파일포인터 fp를 선언하고 파일 “testfile.txt”를 생성한 다음 문자열 str을 p에 복사하여 “This is a file system test”을 종료되는 시점까지 문자단위로 기록한다. 그리고 파일을 닫게 된다. 실행이 끝나고 하드디스크에 생성되어 있는 파일을 확인할 수 있을 것이다. #include <stdio.h> #include <stdlib.h> char str[80] = "This is a file system test\n"; void main(void) { FILE *fp; char *p; int i; if((fp = fopen("testfile.txt", "w")) == NULL) { printf("Cannot open file\n"); exit(1); }
예제 10-8(계속) p = str; while(*p) { if(fputc(*p, fp) == EOF) { printf("Error writing file\n"); exit(1); } p++; } fclose(fp); if((fp = fopen("testfile.txt", "r")) == NULL) { printf("Cannot open file\n"); exit(1); for( ; ; ) { i = fgetc(fp); if(i == EOF) break; putchar(i); }
앞에서 배운 puts()와 다른 점은 뉴라인 문자를 문자열 뒤에 덧붙이지 않는다는 것이다. 10.5.2 파일에서 문자열 입출력 int fputs( char *str, FILE *fp ); char *fgets( char *str, int num, FILE *fp ); fputs 함수는 fp 파일에 str의 문자열을 쓰는 함수이다. 에러가 생기면 EOF를 리턴한다.문자열의 끝에 있는 널 문자는 기록되지 않는다. 앞에서 배운 puts()와 다른 점은 뉴라인 문자를 문자열 뒤에 덧붙이지 않는다는 것이다. fgets함수는 fp 파일로부터 num개의 문자들을 읽어 str에 저장하는 함수이다. num개 문자 전에 뉴라인 문자가 나오든가 파일의 끝이 오면 그때까지 읽은 것을 str에 저장한다. 항상 끝에는 널 문자가 추가된다. 뉴라인 문자를 만났을 때 이 문자도 저장된다. 에러가 발생하면 널 포인터를 리턴한다.
10.6 파일 처리 함수 feof() 함수 ferror() 함수 파일 포인터와 관련된 파일이 파일의 끝에 도달했다면 0이 아닌 값을 반환하며, 그렇지 않으면 0을 반환한다. 이 함수는 2진 파일과 텍스트 파일 모두에서 동작한다. ferror() 함수 파일포인터와 관련된 파일에 에러가 발생하면 0이 아닌 값을 반환하며, 그렇지 않으면 0을 반환한다. int ferror(FILE *fp); int feof(FILE *fp);
10.6 파일 처리 함수 예) FILE *fp ⋮ while (!feof(fp)) fgetc(fp); ⋮ while (!feof(fp)) fgetc(fp); 위 예는 fp 파일의 끝이 아닌 동안 계속 문자를 읽는 작업이다. 예) while (!feof(fp)) { fgetc(fp); if(ferror(fp)) { printf("파일 에러\n"); break; } } 위 예는 fp 파일의 끝이 아닌 동안 계속 한 문자씩 읽는다. 문자를 읽을 때 에러가 생기면 읽는 작업을 끝낸다.
예제 10-9 void main(void) { char str[50]; FILE *str_file; 문자열을 입력받아 파일에 저장하고 다시 저장결과를 9개씻 문자를 읽어와서 출력하는 예제 void main(void) { char str[50]; FILE *str_file; if((str_file = fopen("testfile.txt", "w")) == NULL) { printf("Cannot open file\n"); exit(1); } printf("문자열을 입력하라.\n"); do { gets(str); strcat(str, "\n"); if(*str != '\n') fputs(str, str_file); } while(*str != '\n');
예제 10-9(계속) 저장결과 fclose(str_file); if((str_file = fopen("testfile.txt", "r")) == NULL) { printf("Cannot open file\n"); exit(1); } do { fgets(str, 9, str_file); if(! feof(str_file) ) puts(str); } while(! feof(str_file) ); fclose(str_file); } 저장결과
10.7 이진 파일 생성과 입출력 size_t fread(void *buffer, size_t size, size_t num, FILE *fp); size_t fwrite(void *buffer, size_t size, size_t num, FILE *fp); fread()는 fp 파일에서 num개의 데이터(각 데이터의 길이는 size 바이트임)를 읽어 buffer가 가리키는 곳에 저장하는 함수 이 함수는 실제로 읽은 데이터의 개수를 반환한다. fwrite()는 buffer가 가리키는 곳에 있는 num개의 데이터를 fp 파일에 쓰는 함수이다. 역시 쓰여진 데이터의 개수를 반환한다. 파일의 끝이나 에러의 발생은 앞에서 설명한 feof()와 ferror()를 이용하여 조사할 수 있다.
함수의 형식에 나온 void 타입을 가리키는 포인터와 size_t는 아래와 같은 의미를 가진다. 10.7 이진 파일 생성과 입출력 함수의 형식에 나온 void 타입을 가리키는 포인터와 size_t는 아래와 같은 의미를 가진다. void형을 가리키는 포인터는 어떤 형도 가리킬 수 있는 포인터를 나타낸다. size_t형은 stdio.h에 정의되어 있는 형으로써 컴파일러가 지원 가능한 가장 큰 데이터의 크기를 나타내기 위한 것이다. 보통 size_t형은 unsigned형이나 unsigned long으로 생각할 수 있다.
예제 10-10 하나의 정수를 입력받아 이것을 “binary.dat"라는 이진 파일에 기록하는 예제 #include <stdio.h> #include <stdlib.h> void main(void) { int i; FILE *fp; fp = fopen("binary.dat", "wb"); scanf("%d", &i); fwrite(&i, sizeof(int), 1, fp); fclose(fp); }
예제10-10에서 생성한 이진파일을 읽어서 화면에 디스플레이하는 예제 예제 10-11 예제10-10에서 생성한 이진파일을 읽어서 화면에 디스플레이하는 예제 #include <stdio.h> #include <stdlib.h> void main(void) { int i; FILE *fp; fp = fopen("binary.dat", "rb"); fread(&i, sizeof(int), 1, fp); printf("binary.dat파일의 내용은 : %d\n", i); fclose(fp); }
10.8 fprintf()와 fscanf() 함수 fprintf(FILE *fp, char *control-string, … ); fscanf(FILE *fp, char *control-string, … ); 이 함수들은 printf()와 scanf()들과 똑같은 작업을 한다. 단지 입출력이 키보드와 화면이 아닌 fp 파일로부터 입력되고 fp 파일로 출력된다.
예제 10-12 2개의 정수와 1개의 실수가 ex12.txt에 아래와 같이 저장되어 있다. 이를 입력하여 out12.txt에 출력하는 프로그램이다. #include <stdio.h> #include <stdlib.h> void main(void) { int a, b; float x; FILE *in, *out; if((in = fopen("ex12.txt", "r")) == NULL) { printf("파일 열기 에러\n"); exit(1); } if((out = fopen("out12.txt", "w")) == NULL) {
예제 10-12 (계속) fscanf(in, "%d %d", &a, &b); fscanf(in, "%f", &x); printf(" Input data\n"); printf(" Two integer: %d %d\n", a, b); printf(" Float data: %f\n", x); fprintf(out, " Input data\n"); fprintf(out, " Two integer: %d %d\n", a, b); fprintf(out, " Float data: %f\n", x); fclose(in); fclose(out); }
예제 10-12 (계속) Ex12.txt ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ 3 4 3.14 Out12.txt ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ Input data Two integer: 3 4 Float data: 3.140000
10.9 표준 입출력 파일 C 프로그램의 실행이 시작될 때, 3개의 표준 파일이 자동으로 열리고 사용 가능하게 된다. 표준 입력 파일(키보드), 표준 출력 파일(화면), 표준 에러 파일(화면)이다. 이들 표준 파일의 파일 포인터는 stdio.h에 이미 아래와 같이 정의되어 있다. 예) ch = fgetc(stdin); fputc(ch, stdout); //위 문장은 stdin 파일, 즉 키보드로부터 한 문자를 입력받아 stdout 파일, 즉 화면에 출력하는 문장 파일 포인터 표준 입력 파일 stdin 표준 출력 파일 stdout 표준 에러 파일 stderr
int fseek(FILE *fp, long offset, int origin); 10.10 파일의 임의 위치 접근 및 기타 파일 관련함수 지금까지는 파일을 처음부터 끝까지 순차적으로 읽거나 썼다. 그러나 fseek() 함수를 사용하여 파일의 어떠한 지점이라도 접근할 수 있다. 일반적으로 이진 파일에서만 임의 위치 접근을 사용한다. fp 파일의 현재 위치를 origin에서 시작하여 offset 바이트 떨어진 곳으로 이동시키는 함수이다. 이 때, origin의 값은 아래의 세 매크로 중 하나의 값을 가지며, 이 매크로들은 stdio.h에 정의되어 있다. int fseek(FILE *fp, long offset, int origin); origin의 값 의미 SEEK_SET 파일의 처음 SEEK_CUR 파일의 현재 위치 SEEK_END 파일의 끝 fseek()가 성공하면 0을 리턴한다.
ftell() 함수 fp 파일의 현재 위치를 알려준다. 10.10 파일의 임의 위치 접근 및 기타 파일 관련함수 long ftell(FILE *fp);
예제 10-13 파일의 임의 접근 명령을 사용한 프로그램 #include <stdio.h> #include <stdlib.h> #define NUM 3 struct student { char name[20]; int age; char grade; } st; void main(void) { int i; FILE *fp; if((fp = fopen("student.txt", "rb")) == NULL) { printf("파일 열기 에러"); exit(1); }
예제 10-13(계속) fseek(fp, 2*sizeof(struct student), SEEK_SET); if(fread(&st, sizeof(struct student), 1, fp) != 1) { printf("읽기 에러"); exit(1); } fclose(fp); printf(st.name); printf(" %d %c\n", st.age, st.grade); }
예제 10-14 지정한 파일 내에 있는 임의의 위치의 바이트 값을 출력하는 예제이다. /* fseek() 함수 사용 예제 */ #include <stdio.h> #include <stdlib.h> void main(int argc, char *argv[]) { long loc; FILE *fp; if(argc != 2) { printf("File name missing"); exit(1); } if((fp = fopen(argv[1], "rb")) == NULL) { printf("Cannot open file");
예제 10-14 (계속) printf("Enter byte to seek to : "); scanf("%ld", &loc); if(fseek(fp, loc, SEEK_SET)) { printf("seek error"); exit(1); } printf("Value at loc %ld is %d", loc, fgetc(fp)); fclose(fp); }
remove() 함수를 사용하여 파일을 지울 수 있다. 예제 10-15 remove() 함수를 사용하여 파일을 지울 수 있다. #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <ctype.h> void main(int argc, char *argv[]) { char fname[80]; printf("Enter name of file to erase : "); gets(fname); printf("Are you sure?(y/n) "); if(toupper(getche()) == 'Y') { remove(fname); printf("\nerase success!\n"); } }
예제 10-16 “abcdefghijklmnopqrstuvwxyz”를 내용으로 갖고 있는 ‘testfile.txt'를 rewind()함수를 이용하여 다시 출력하는 예제 /* rewind() 함수 실행결과 */ #include <stdio.h> #include <stdlib.h> void main(int argc, char *argv[]) { FILE *fp; if(argc != 2) { printf("File name missing"); exit(1); } if((fp = fopen(argv[1], "r")) == NULL) { printf("cannot open file");
예제 10-16 (계속) while(!feof(fp)) putchar(getc(fp)); rewind(fp); while(!feof(fp)) putchar(getc(fp)); fclose(fp); }