Download presentation
Presentation is loading. Please wait.
1
Chapter 10– 표준 함수(1) Outline 10.1 스트림과 파일 10.2 입출력 표준 함수
스트림과 파일 입출력 표준 함수 고수준 파일 입출력 함수 요약 10.5 예제
2
10.1 스트림(stream)과 파일(file)
텍스트 스트림(text stream) 인쇄가 가능한 문자들의 연속 입력시 각 줄의 끝 문자 뒤에 ‘\n’을 추가한다. 출력 시 ‘\n’까지의 문자들을 한 줄(레코드)로 출력한다. 2진 스트림(binary stream) 바이트들의 연속 문자 변환이 일어나지 않는다. 컴파일러의 중간 file이나 object 프로그램 등을 표시 C 언어의 file 디스크에 저장된 file, 입출력 장치(터미날, CD ROM 등)
3
10.1 스트림(stream)과 파일(file)
- C 프로그램에서 자동으로 open되는 file들 - C 프로그램이 동작시 3개의 file이 자동 개방(open)된다. - file descriptor가 0번, 1번, 2번인 file 들로 FILE* 형의 변수 stdin, stdout, stderr을 사용한다. 이를 표준입력, 표준출력, 표준 에러 file이라 부른다. - scanf나 getchar등은 실제 stdin에서 읽어 들이고, printf나 putchar는 stdout로 출력한다. 기술하는 형태 명 칭 file descriptor 의 미 FILE *stdin FILE *stdout FILE *stderr standard input file standard output file standard error file 1 2 키보드에 접속 화면(screen)에 접속 화면에 접속
4
10.1 스트림(stream)과 파일(file)
- 그림 10.1 표준 입출력 장치(file)
5
10.1 스트림(stream)과 파일(file)
- 표준 헤더 file(stdio.h) - 자료형 FILE이 정의되어 있다. - FILE*형 변수 stdin, stdout, stderr등이 선언되어있다. - getc와 putc, getchar와 putchar, ungetc등의 함수 정의 - fseek 등의 file 임의 접근에 필요한 매크로 SEEK_CUR, SEEK_END, SEEK_SET 등이 각각 0, 1, 2로 정의됨 - 매크로 NULL 이 0으로 정의됨 - ferror, feof, fileno 등의 FILE 구조체 내의 정보 이용하는 함수 - 버퍼크기(BUFSIZ), 최대 개방 file수(OPEN_MAX) 등의 정의
6
<표준 입력에서 읽기, 표준 출력으로 쓰기>
입출력 표준 함수 <표준 입력에서 읽기, 표준 출력으로 쓰기> int getchar(); int putchar(int c); getchar는 표준입력에서 문자를 int형으로 확장하여 읽어 들임 file 끝을 만나면 EOF(–1)를 반환함 putchar도 문자를 int형 인수로 받아 표준출력에 출력함
7
10.2 입출력 표준 함수 (예 10.3) getchar()와 putchar()의 사용 예
입출력 표준 함수 (예 10.3) getchar()와 putchar()의 사용 예 입력입력 file을 표준출력으로 복사하는 프로그램 (예 10.3) getchar()와 putchar() /* File : prog10-3.c getchar()와 putchar()의 사용 예 */ #include <stdio.h> int main(void) { int c; while ((c = getchar()) != EOF) putchar(c); }
8
10.2 입출력 표준 함수 (예 10.3 계속) getchar()와 putchar()의 사용 예
입출력 표준 함수 (예 10.3 계속) getchar()와 putchar()의 사용 예 입력 file을 표준출력으로 복사하는 프로그램
9
<표준 입력, 표준 출력에서 한 줄씩 읽고 쓰기>
입출력 표준 함수 <표준 입력, 표준 출력에서 한 줄씩 읽고 쓰기> char *gets(char *s); char *puts(char *s); gets는 표준입력에서 한 줄을 읽어 s가 가리키는 버퍼에 저장한다. 단 끝의 ‘\n’은 널문자( ‘\0’)로 바꾼다. puts는 s가 가리키는 문자열을 표준출력으로 출력. 단 문자열 끝의 널문자를 ‘\n’으로 바꾸어 출력한다. [주의] gets 컴파일 시 경고 메시지를 주는 C언어도 있다. 가능하면 gets, puts 대신 일반적인 fgets, fputs를 사용하시오.
10
10.2 입출력 표준 함수 (예 10.5) gets()와 puts()의 사용 예
입출력 표준 함수 (예 10.5) gets()와 puts()의 사용 예 표준입력 file을 표준출력으로 줄 단위로 복사 (예 10.5) gets()와 puts() /* File : prog10-5.c gets()와 puts()의 사용 예 */ #include <stdio.h> int main(void) { char buf[512]; while (gets(buf)) puts(buf); }
11
10.2 입출력 표준 함수 void printf(fmt, arg1, arg2, . . .)
입출력 표준 함수 <표준 출력으로 쓰기> void printf(fmt, arg1, arg2, . . .) const char *fmt; /* 양식 제어 문자열 */ 기본적으로 첫 인수인 fmt를 출력한다. 단 fmt내에 %와 변환문자가 나오면 다음의 인수값으로 치환하여 출력한다. 즉 fmt내의 %와 변환문자가 나온 수 만큼의 인수가 추가로 필요하다.
12
10.2 입출력 표준 함수 표 10.2 printf 용 변환 문자 변환 문자 의 미 예 d o x(또는 X) u e(또는 E)
입출력 표준 함수 표 printf 용 변환 문자 변환 문자 의 미 예 d o x(또는 X) u e(또는 E) f g(또는 G) c s 10진 정수 8진 정수(0이 앞에 나오지 않음) 16진 정수(0x가 앞에 나오지 않음) 비부호화 10진 정수 지수를 가진 부동 소수점 수 지수 없는 부동 소수점 수 e 또는 f 중 짧은 쪽 단일 문자 문자열 45 55 2d e+03 t Millennium
13
10.2 입출력 표준 함수 (예 10.6) printf에서의 변환 문자의 사용 (예 10.6) printf의 변환문자
입출력 표준 함수 (예 10.6) printf에서의 변환 문자의 사용 (예 10.6) printf의 변환문자 output printf(“~0 = %d %o %x %u\n”, ~0, ~0, ~0, ~0); /* (1) */ printf(“%e %f\n”, 31.4, 31.4); /* (2) */ printf(“%c %s\n”, ‘x’, “century”); /* (3) */ printf(“%5d%4d\n”, 1234, 56); /* (4) */ printf(“%-8s=%04d\n”, “century”, 21); /* (5) */ printf(“57%% students passed\n”); /* (6) */ ~0 = ffffffff e x century Century =0021 57% students passed
14
10.2 입출력 표준 함수 (예 10.6 계속) printf에서의 변환 문자의 사용 (예 10.6 계속) [해 설]
입출력 표준 함수 (예 10.6 계속) printf에서의 변환 문자의 사용 (예 10.6 계속) [해 설] (1) 변환문자 d, o, x는 각각 10진수, 8진수, 16진수로 출력한다. printf의 첫 인수가 출력되는데, %와 변환문자형은 다음 인수값으로 치환된다. 변환문자 u는 비부호(unsigned) 10진수로 출력하기 위해 사용한다. ld, lo, lx의 변환문자는 long 형 출력에 사용된다. x대신 X를 쓰면 16진수에서 대문자로(가령 f를 F로) 표시한다. (2) e는 부동 소수점, f는 고정 소수점으로 출력 e대신 E사용하면 출력 시 지수표기 e가 E로 표기됨 (3) 단일 문자 출력은 %c로 문자열의 출력은 %s로 지정 (4) %와 변환문자 사이에 필드폭을 명시할 수 있다. (예)%5d는 5자리를 잡고 우정렬로 십진수를 출력하라는 의미 (5) %직후에 –를 넣으면 좌정렬된다. %04d같이 0을 넣으면 남는자리는 0으로 채운다. 가령 %04d로 56을 출력하면 0056이 출력된다. (6) %%는 %를 출력한다.
15
10.2 입출력 표준 함수 int scanf(fmt, arg1, arg2, . . .)
입출력 표준 함수 <표준 입력에서 읽기> int scanf(fmt, arg1, arg2, . . .) char *fmt; /* 양식 제어 문자열 */ 주의할 점은 arg1, arg2 등의 인수는 저장할 변수의 포인터이어야 한다는 점이다. (예) scanf(“%d”, &count); 값에 의한 참조(call by value)로는 인수 값을 호출 환경에 전달할 수가 없기 때문이다.
16
10.2 입출력 표준 함수 표 10.3 scanf 용 변환 문자 변환 문자 입력열의 해석법 d (또는 D) o (또는 O)
입출력 표준 함수 표 scanf 용 변환 문자 변환 문자 입력열의 해석법 d (또는 D) o (또는 O) x(또는 X) u (또는 U) e(또는 E) f (또는 F) lf 또는 le c s [string] 10진 정수 8진 정수 16진 정수 비부호화 10진 정수 float형 e와 f는 같다. double형 상수 단일 문자 문자열 특별 문자열
17
10.2 입출력 표준 함수 (예 10.7) scanf에서의 변환 문자의 사용(1) (예 10.7) scanf의 변환문자(1)
입출력 표준 함수 (예 10.7) scanf에서의 변환 문자의 사용(1) (예 10.7) scanf의 변환문자(1) [해 설] input output int id, io, ix; float e, f; double de, df; int d1, d2; char c, s1[20], s2[20]; /* (1) */ scanf(“%d %o %x %e %f %le %lf”, &id, &io, &ix, &e, &f, &de, &df); printf(“%d %d %d %e %f %e %f\n”, id, io, ix, e, f, de, df); scanf에서는 저장할 변수의 포인터를 사용함에 주의하시오. e e
18
10.2 입출력 표준 함수 (예 10.7 계속) scanf에서의 변환 문자의 사용(2) (예 10.7 계속) scanf의
입출력 표준 함수 (예 10.7 계속) scanf에서의 변환 문자의 사용(2) (예 10.7 계속) scanf의 변환문자(2) [해 설] input output int id, io, ix; float e, f; double de, df; int d1, d2; char c, s1[10], s2[20]; /* (2) */ scanf(“%c”, &c); scanf(“%s”, s1) printf(“%c %s\n”, c, s1); %c는 문자입력에 %s는 문자열 입력에 사용됨 s1자체가 주소이므로 &s1으로 사용하지 않는다. 문자열을 읽어들일 때는 공백, 탭, 줄바꿈 문자(‘\n’)이외의 문자에서 시작되어, 공백, 탭, 줄바꿈 문자 직전까지이다. I student I student
19
10.2 입출력 표준 함수 (예 10.7 계속) scanf에서의 변환 문자의 사용(3) (예 10.7 계속) scanf의
입출력 표준 함수 (예 10.7 계속) scanf에서의 변환 문자의 사용(3) int id, io, ix; float e, f; double de, df; int d1, d2; char c, s1[10], s2[20]; /* (3) */ scanf(“%[st0-9]%[^0-9\n]”, s1, s2); printf(“(%s)(%s)\n”, s1, s2); (예 10.7 계속) scanf의 변환문자(3) [해 설] input output %[문자열]은 문자열의 문자들로 구성되는 최대 길이의 문자열 입력에 사용. 즉 [st0-9]는 s와 t 및 0에서 9 사이의 문자 12자들로 구성된 문자열 여기서 0-9는 0과 9 사이의 문자 즉 를 줄여 표현한 것임 %[^문자열]은 문자열 내의 문자를 제외한 문자로 구성된 최대 길이의 문자열 출력에 사용. 즉 [^0-9\n]은 0에서 9까지의 수와 줄 바꿈 문자를 제외한 최대 길이의 문자열 입력 받은 문자열 뒤에는 널문자가 추가된다. 21st century (21st)( century)
20
10.2 입출력 표준 함수 (예 10.7 계속) (4) 필드폭 지정 (예 10.7 계속) (4) 필드폭 지정 [해 설]
입출력 표준 함수 (예 10.7 계속) (4) 필드폭 지정 (예 10.7 계속) (4) 필드폭 지정 [해 설] input output int id, io, ix; float e, f; double de, df; int d1, d2; char c, s1[10], s2[20]; /* (4) */ scanf(“%d%3d”, &d1, &d2); scanf(“%s%3s”, s1, s2); printf(“%d %d (%s) (%s)\n”, d1, d2, s1, s2); s1, s2는 자체가 포인터이므로 scanf의 인수로 사용시 앞에 &가 불필요하다. d2를 위한 필드폭이 3 이므로 3자리수를 읽어들인다. 즉 d1에는 12345가 d2에는 678이 저장된다. 또 s1에는 “90”이 s2에는 “abc”가 저장된다. abcde (90) (abc)
21
10.2 입출력 표준 함수 (예 10.7 계속) (5) 특정자료형의 자료를 뛰어 넘기 (예 10.7 계속) (5) 특정자료형의
입출력 표준 함수 (예 10.7 계속) (5) 특정자료형의 자료를 뛰어 넘기 (예 10.7 계속) (5) 특정자료형의 자료를 뛰어넘기 [해 설] input output int id, io, ix; float e, f; double de, df; int d1, d2; char c, s1[10], s2[20]; /* (5) */ scanf(“%*d%s”, s1); printf(“%s\n”, s1); % 직 후의 *는 그 뒤의 변환문자에 해당하는 입력을 읽지 않고 뛰어 넘게 한다. 즉 %*d는 정수형 자료를 읽지않고 뛰어 넘는다. 따라서 s1에는 “abc”가 저장된다. 123 abc abc
22
10.2 입출력 표준 함수 (예 10.7 계속) (6) 여백을 뛰어 넘기 (예 10.7 계속) (6)여백을 뛰어 넘기
입출력 표준 함수 (예 10.7 계속) (6) 여백을 뛰어 넘기 (예 10.7 계속) (6)여백을 뛰어 넘기 [해 설] input output int id, io, ix; float e, f; double de, df; int d1, d2; char c, s1[10], s2[20]; /* (6) */ scanf(“%d %c”, &d1, &c); printf(“%d %c\n”, d1, c); scanf의 첫 인수(fmt) 내의 공백문자는 입력자료에 공백, 탭, 줄바꿈 문자들이 있으면 뛰어넘게 하기 위해 필요 fmt 내의 다수의 여백 문자는 1개의 여백 문자와 동일 123\t x 123 x
23
10.2 입출력 표준 함수 (예 10.7 계속) (7) 특정 문자 뛰어 넘기 (예 10.7 계속) (7)특정 문자 뛰어 넘기
입출력 표준 함수 (예 10.7 계속) (7) 특정 문자 뛰어 넘기 (예 10.7 계속) (7)특정 문자 뛰어 넘기 [해 설] input output int id, io, ix; float e, f; double de, df; int d1, d2; char c, s1[10], s2[20]; /* (7) */ scanf(“%s = %d%%”, s1, &d1); printf(“%s %d\n”, s1, d1); 공백, 탭, 줄바꿈 문자 이외의 문자는 입력 자료에서 동일한 것이면 그 문자를 통과시키고, 다른 문자이면 scanf를 종료시킨다. %를 통과시키려면 %%를 사용한다. abc = 123% abc 123
24
10.3 고수준 파일 입출력 함수 FILE *fopen(char *filename, char *mode)
고수준 파일 입출력 함수 표준입출력이 아닌 사용자 file을 이용 입출력하는 방법 버퍼형 입출력 = 고수준 입출력: 장치마다 입력버퍼, 출력버퍼를 둠 <stdio.h>에서 정의된 FILE 형의 포인터를 사용함 #include <stdio.h> FILE *fp; <file 열고 닫기> FILE *fopen(char *filename, char *mode) int fclose(FILE *fp) fopen은 filename이란 이름을 갖는 file을 open한다. open된 file의 FILE 포인터가 반환된다. file을 읽기용으로 open(개방)하려면 mode값으로 “r”를, 쓰기 용이면 “w”를 사용한다. fclose는 open한 file을 닫을 때 사용한다.
25
10.3 고수준 파일 입출력 함수 표 10.4 file 접근 방식 문자열(mode) 의 미 “r”
고수준 파일 입출력 함수 표 10.4 file 접근 방식 문자열(mode) 의 미 “r” 파일의 처음부터 읽기(reading) 위해 개방한다. “w” 파일의 처음 위치부터 쓰기(writing) 위해 개방한다. 해당 파일이 존재하지 않으면 생성되고, 존재한다면 기존의 내용은 무시된다. “a” 파일의 끝에 추가로 쓰기 위해 개방한다. 해당 파일이 없으면, 파일을 생성하고 쓰기 위해 개방한다. “r+” 읽고 쓰기 위해 파일을 개방한다. 파일은 이미 존재해야 한다. “w+” 읽고 쓰기 위해 파일을 개방한다. 해당 파일이 존재하지 않으면 생성되고, 존재한다면 기존의 내용은 무시된다. “a+” 파일의 끝에서 읽고 쓰기 위해 개방한다. 해당 파일이 존재하지 않으면 a+는 w+와 같다.
26
10.3 고수준 파일 입출력 함수 int getc(FILE *fp) /* get character */
고수준 파일 입출력 함수 <문자 읽기와 쓰기> int getc(FILE *fp) /* get character */ int putc(int c, FILE *fp) /* put character */ fopen으로 읽기 위해 open한 file의 FILE 포인터를 인수로 getc를 호출하면 다음 문자가 int 형으로 확장되어 반환된다. 단 file끝에서는 EOF(-1)를 반환한다. fopen으로 쓸수 있게 open한 file의 FILE 포인터 fp를 이용하여 putc(c, fp)하면 해당 file에 int형 c에 저장된 문자를 출력 (예 10.8) getc()의 사용 while ((c = getc(fp)) != EOF) { . . . /* c를 처리한다. */ }
27
고수준 파일 입출력 함수 getchar와 putchar는 getc와 putc의 특별한 경우로 <stdio.h>에 다음처럼 매크로로 정의되어 있다. FILE 포인터 stdin, stdout, stderr의 경우에는 fopen(), fclose()가 불필요하다. #define getchar() getc(stdin) #define putchar(c) putc(c, stdout)
28
10.3 고수준 파일 입출력 함수 (예 10.9) 사용자 file의 복사 (1) getc()와 putc()의 사용
고수준 파일 입출력 함수 (예 10.9) 사용자 file의 복사 (1) getc()와 putc()의 사용 (예 10.9)(1) getc와 putc의 사용 (prog10-9a.c) /* File : prog10-9a.c getc()와 putc()의 사용 */ #include <stdio.h> int main(void) { int c; FILE *ifp, *ofp; if ((ifp = fopen(“input.data”, “r”)) == NULL) { printf(“Can’t open input file\n”); exit(1); } if ((ofp = fopen(“output.data”, “w”)) == NULL) { printf(“Can’t open output file\n”); exit(1); } while ((c = getc(ifp)) != EOF) putc(c, ofp); fclose(ifp); fclose(ofp); 20 }
29
10.3 고수준 파일 입출력 함수 (예 10.9 계속) 사용자 file의 복사 (1) getc()와 putc()의 사용
고수준 파일 입출력 함수 (예 10.9 계속) 사용자 file의 복사 (1) getc()와 putc()의 사용 (예 10.9)(1) getc와 putc의 사용 [해 설] output getc, putc, getchar, putchar를 사용하려면, 반드시 <stdio.h>를 포함하여야 한다. 줄 8과 12는 두 개의 file을 각각 입력용과 출력용으로 열고 있다. 두 file 명을 명령어 줄에서 제공하고 main의 인수로 읽어 들이면 편리하다. file 을 open하다 실패하면, NULL을 반환하므로 해당 에러 메시지를 주고 종료한다. 성공하면 반환되는 FILE 포인터를 각각 ifp와 ofp에 저장한다. 줄 16과 17: getc(ifp)로 “input.data”에서 한 문자씩 얻어 c에 저장하고, putc(c, ofp)로 “output.data”에 한 문자씩 저장한다. 줄 18,19 : 열린 두 file을 닫는다. 다음 동작에서 UNIX 명령어 cat은 해당 file의 내용을 화면에 출력한다. $ cat input.data Copy test program 2nd line $ cc –o prog10-9a prog10-9a.c $ prog10-9a $ cat output.data
30
10.3 고수준 파일 입출력 함수 (예 10.9 계속) 사용자 file의 복사
고수준 파일 입출력 함수 (예 10.9 계속) 사용자 file의 복사 (2) getchar()와 putchar()의 사용 (예 10.9)(2) getchar와 putchar의 사용 (prog10-9a.c) [해 설] output /* File : prog10-9b.c getchar()와 putchar()의 사용 */ #include <stdio.h> int main(void) { int c; while ((c = getchar) != EOF) putchar(c); } 표준 입력과 표준 출력을 열고 닫는 코딩이 불필요 file을 다루려면 동작시 입력방향전환(<)과 출력방향 전환(>)을 이용함 $ cat input.data Copy test program 2nd line $ cc –o prog10-9b prog10-9b.c $ prog10-9b < input.data > output.data $ cat output.data
31
<문자열/줄단위 입력과 출력>
고수준 파일 입출력 함수 <문자열/줄단위 입력과 출력> char *fgets(char *s, int n, FILE *fp) int fputs(char *s, FILE *fp) fgets는 FILE 포인터 fp가 가리키는 버퍼에 대한 file로 부터 s가 가리키는 길이 n의 버퍼에 한 줄을 입력하며, 마지막 줄바꿈 문자 뒤에 널문자를 추가하여 한 개의 문자열을 만든다. 한 줄(즉 레코드)의 크기가 n개 이상이면 fgets는 n-1개 문자를 읽어 들이고 널 문자를 추가한다. fgets 는 파일 끝이거나 에러이면 NULL을 반환한다. fputs는 문자열을 출력한다. 출력시 마지막 널문자는 생략된다. gets 및 puts는 fets와 fputs의 특수경우가 아니며, ‘\n’처리 방식이 다르다. 따라서 가능하면 표준형인 fgets, fputs를 사용하시오.
32
10.3 고수준 파일 입출력 함수 (예 10.11) fgets()와 fputs()의 사용 예
고수준 파일 입출력 함수 (예 10.11) fgets()와 fputs()의 사용 예 file을 줄 단위로 fgets로 읽어 fputs를 이용하여 복사 여기서는 편의상 file open 시 에러검사를 생략하였다. 존재하지 않는 file을 열때 error발생 등의 문제가 있으므로, 실제는 반드시 (예 10.9 식으로) 하여야 함 (예 10.11) fgets()와 fputs() (prog10-11.c) /* File : prog10-11.c fgets()와 fputs()의 사용 예 */ #include <stdio.h> int main(void) /* 1줄 단위로 file 입출력 */ { char buf[512]; FILE *ifp, *ofp; ifp = fopen(“input.data”, “r”); ofp = fopen(“output.data”, “w”); while (fgets(buf, 512, ifp)) fputs(buf, ofp); fclose(ifp); fclose(ofp); 14 }
33
고수준 파일 입출력 함수 <블록 단위의 입출력> int *fread(void *buffer, int num_bytes, int count, FILE *fp) int *fwrite(char *buffer, int num_bytes, int count, FILE *fp) fp는 fopen으로 반환된 FILE 포인터이다. buffer는 fread의 경우 file에서 읽어들일 자료를 저장할 버퍼 포인터이고, fwrite의 경우 file에 쓸 정보를 저장한 버퍼 포인터이다. num_bytes는 자료블록의 크기 count는 읽거나 쓸 자료블록의 수 fread의 반환값: 실제 읽어들인 블록의 수 fwrite의 반환값: 실제 출력된 블록의 수
34
10.3 고수준 파일 입출력 함수 (예 10.12) fread(), fwrite()의 사용
고수준 파일 입출력 함수 (예 10.12) fread(), fwrite()의 사용 (1) fp 파일에서 float형 자료를 변수 f로 읽어 오기 성공하면, fread의 반환값이 참이다. (2) float형 자료 f를 fp 파일에 쓰기 일부 C 언어에서는 fwrite()에 사용할 file을 fopen할때 ‘w’ 모드 대신 ‘wb’모드로 2진 file임을 명시해야 함. (3) 한번에 float형 자료 배열 저장하기 float f, balance[100]; /* (1) */ if (fread(&f, sizeof(float), 1, stdin) == 0) /* file의 끝 또는 error 발생 */ else /* 정상 경우 */ /* (2) */ fwrite(&f, sizeof(float), 1, fp); /* (3) */ fwrite(balance, sizeof(balance), 1, fp); (예 10.12) fread(), fwrite()
35
고수준 파일 입출력 함수 <임의 위치 접근> int fseek(FILE *fp, long offset, int mode) /* file seek */ void rewind(FILE *fp) long ftell(FILE *fp) /* file tell */ 위 함수들은 fp 파일에서 다음에 읽고 쓸 위치를 이동시킨다. 실제 read/write는 발생하지 않는다. fseek fp는 fopen으로 반환된 FILE 포인터이다. mode는 file의 맨 앞 기준이면 0(SEEK_SET), 현 위치 기준이면 1(SEEK_CUR), 맨 뒤 기준이면 2(SEEK_END)이다. offset은 mode가 정해주는 기준점에서 이동할 바이트 수이다. 뒤로 이동 시에는 음수를 사용한다. rewind(fp)는 fseek(fp, 0L, 0)과 같다. 맨 앞으로 위치를 이동한다. ftell(fp)는 fp 파일의 현재 위치를 반환한다.
36
10.3 고수준 파일 입출력 함수 (예 10.13) fseek()의 사용 (1) file의 특정 위치로 이동
고수준 파일 입출력 함수 (예 10.13) fseek()의 사용 (1) file의 특정 위치로 이동 offset이 80L이면 모드를 기준으로 앞으로 80바이트 이동하고, -80L이면 뒤로 80바이트 이동한다. L은 long형 자료를 나타낸다. /* fp가 가리키는 file에서 읽고 쓰는 위치를 다음 위치로 이동 */ fseek(fp, 0L, 0); /* file 맨 앞으로 이동 */ fseek(fp, 80L, 0); /* file 맨 앞에서 80바이트 위치로 이동 */ fseek(fp, 80L, 1); /* file 현 위치에서 80바이트 앞으로 이동 */ fseek(fp, -80L, 1); /* file 현 위치에서 80바이트 뒤로 이동 */ fseek(fp, 0L, 2); /* file 맨 뒤로 이동 */ fseek(fp, -80L, 2); /* file 맨 뒤에서 80바이트 뒤로 이동 */
37
10.3 고수준 파일 입출력 함수 (예 10.13) fseek()의 사용
고수준 파일 입출력 함수 (예 10.13) fseek()의 사용 (2) 개방되지않은 file의 특정 위치의 문자를 알아 내는 함수 filename에 저장된 이름의 file에서 off번 째 문자를 반환한다. /* filename에 저장된 이름의 file에서 off번 째 문자를 알아내는 함수 */ int get_the_char(char filename[], long off) { FILE *fp; int c; if (fp = fopen(filename, “rb”)) == NULL) { printf(“cannot open file\n”); exit(1); } fseek(fp, off, 0); /* off 번째 위치에서 */ c = getc(fp); /* 1 문자를 읽음 */ fclose(fp); return c;
38
<일반 file 출력/입력하기>
고수준 파일 입출력 함수 <일반 file 출력/입력하기> int fprintf(fp, format, arg1, arg2, . . .) /* file printf */ FILE *fp; const char *format; int fscanf(fp, format, arg1, arg2, . . .) /* file scanf */ FILE *fp; const char *format; printf, scanf와 동일하나 첫 인수가 가리키는 file로 출력/입력됨
39
<fprintf vs. printf> <fscanf vs. scanf>
고수준 파일 입출력 함수 <fprintf vs. printf> <fscanf vs. scanf> fprintf(stdout, format, arg1, arg2, . . .) printf(format, arg1, arg2, . . .) fscanf(stdin, format, arg1, arg2, . . .) scanf(format, arg1, arg2, . . .) printf와 scanf는 fprintf와 scanf의 특수 경우임
40
10.3 고수준 파일 입출력 함수 (예 10.14) fscanf(), fprintf()의 사용 예 (예 10.14)
고수준 파일 입출력 함수 (예 10.14) fscanf(), fprintf()의 사용 예 /* File : prog10-14.c fprintf(), fscanf()의 사용 예 */ #include <stdio.h> int main(void) { FILE *fp; char s[80]; int t; if ((fp = fopen(“test”, “w”)) == NULL) { printf(“cannot open file\n”); exit(1); } fscanf(stdin, “%s%d”, s, &t); /* 키보드로부터 읽기 */ fprintf(fp, “%s %d”, s, t); /* file에 기록 */ fclose(fp); if ((fp = fopen(“test”, “r”)) == NULL) { printf(“cannot open file\n”); exit(1); } fscanf(fp, “%s%d”, s, &t); /* file로부터 읽기 */ fclose(fp); fprintf(stdout, “%s %d\n”, s, t); /* 화면 출력 */ 23 } (예 10.14)
41
10.3 고수준 파일 입출력 함수 (예 10.14) fscanf(), fprintf()의 사용 예 (예 10.14 계속)
고수준 파일 입출력 함수 (예 10.14) fscanf(), fprintf()의 사용 예 줄 9에서 출력용 file을 open한다. 줄 10,11과 줄 17,18: file을 열다가 에러난 경우 메시지를 주고 종료함. 줄 13,14에서 문자열과 정수를 읽어들여 줄 9에서 open한 file로 출력하고, 줄 15: 그 file을 닫는다. 줄 16: 동일한 file을 이번에는 입력용으로 open함 줄 20에서 그 file의 내용을 읽어 들여 줄22에서 표준출력으로 출력 줄 21: 그 file을 닫는다. (예 계속) [해 설] output lee 98
42
<11장 참고>문자열에서 입력/ 문자열로 출력
고수준 파일 입출력 함수 <11장 참고>문자열에서 입력/ 문자열로 출력 int sprintf(s, format, arg1, arg2, . . .) /* string printf */ int sscanf(s, format, arg1, arg2, . . .) /* string scanf */ char *s; const char *format; fprintf, fscanf의 첫인수를 FILE포인터에서 문자 포인터로 바꾼 형태 sscanf는 첫 인수가 가리키는 문자 배열에서 읽어들인다. sprintf는 첫 인수가 가리키는 문자 배열로 출력한다.
43
<11장 참고>문자열에서 입력/ 문자열로 출력
고수준 파일 입출력 함수 <11장 참고>문자열에서 입력/ 문자열로 출력 /* 문자열에서 읽기, 쓰기 */ int main(void) { char s1 = “lee 67 kim 70”, s2[256], name1[16], name[16]; int score1, score2; sscanf(s1, “%s%d%s%d”, name1, score1, name2, score2); sprintf(str2, “%s & %s got %d”, name1, name2, score1+score2); printf(“%s\n”, str2); } sscanf와 sprintf [해 설] output sscanf문으로 s1에서 읽어 들여 name1에 “lee”, score1에 67, name2에 “kim”, score2에 70이 저장됨 sprintf문에서 s2에 “lee & kim got 137”이 저장됨 lee & kim got 137
44
10.3 고수준 파일 입출력 함수 int feof(FILE *fp) /* file eof */
고수준 파일 입출력 함수 <feof 와 ferror> int feof(FILE *fp) /* file eof */ int ferror(FILE *fp) /* file error */ 두 함수 모두 <stdio.h>에 매크로로 정의되어 있음 feof(fp); 파일 fp의 끝에 도달시 호출하면 참(1)을 반환, 아니면 거짓(0)을 반환 ferror(fp); 종전의 file작업 중 에러 발생하였으면 참을 반환, 아니면 거짓(0)을 반환
45
<출력버퍼의 내용을 강제로 file로 보내기>
고수준 파일 입출력 함수 <출력버퍼의 내용을 강제로 file로 보내기> int fflush(FILE *fp) /* flush output buffer */ 파일 fp의 출력 버퍼 자료를 강제로 file에 저장 시킴 입력 file의 경우 버퍼의 내용을 소거(clear)
46
<디스크 파일에서 정수 데이터 읽기/쓰기>
고수준 파일 입출력 함수 <디스크 파일에서 정수 데이터 읽기/쓰기> int getw(FILE *fp) /* flush output buffer */ int putw(int w, FILE *fp) 정수 단위로 읽고 쓴다는 점을 제외하면 getc(), putc()와 같다. <방금 읽은 문자를 반납> int ungetc(int c, FILE *fp) /* undo get character */ /* fp가 가리키는 file에 방금 읽은 문자 c를 반납 */ 가령 FILE 포인터가 가리키는 곳에 567이 있다하자. 방금 읽은 문자가 ‘5’(즉 ‘0’에서 ‘9’사이)면 ungetc로 반납하고, 정수 읽기로 567을 한번에 읽어 올 수 있다.
47
10.5 예 제 입력형태 :피연산자 뒤에 연산자 (예) 100 100 + (예제 10.1) 가감승제 계산기
예 제 (예제 10.1) 가감승제 계산기 입력형태 :피연산자 뒤에 연산자 (예) 예제 output 프로그램 ex10-1.c 두 수와 연산자를 넣으시오: /* File : ex10-1.c 가감승제 계산기(입력: 두 수와 연산자) 사용 예: */ #include <stdio.h> int main(void) { float num1, num2; char op; printf(“두 수와 연산자를 넣으시오: ”) scanf(“%f%f %c”, &num1, &num2, &op); switch (op) { case ‘+’: printf(“%f\n”, num1+num2); break; case ‘-’: printf(“%f\n”, num1-num2); break; case ‘/’: printf(“%f\n”, num1/num2); break; case ‘*’: printf(“%f\n”, num1*num2); break; default: printf(“Unkown operator”); } 17 }
48
(예제 10.2) 문자열, 정수, 부동 소수점 출력하는 printf문은?
int dec; float flt; char str[10]; printf(“%s %d %.3f”, str, dec, flt); 예제 [해 설] 문자열, 정수, 부동 소수점 출력을 위해 %s, %d, %f를 사용한다.
49
int d1, d2; char str[10]; . . . . . scanf(“%s%d%d”, str, &d1, &d2);
예제 [해 설] 호출 환경으로 읽어 들인 값을 받기 위해 d1과 d2의 포인터를 인수로 사용한다. 문자열 str은 그 자체가 주소이므로 그대로 인수로 사용한다. [참고] str은 배열의 첫 성분의 주소 즉 &str[0]와 동일함
50
줄 9-10: argc가 2가 넘으면 에러 메시지 주고 동료
/* File : ex10-4.c 실수들을 저장한 file의 이름을 인수로 받아 그 수들의 평균을 출력하는 프로그램 file명을 인수로 제공하지 않으면 표준입력에서 읽어 들임 */ #include <stdio.h> int main(int argc, char *argv[]) { FILE *fp; void mean(); if (argc > 2) { printf(“Usage: %s [filename]\n”, argv[0]); exit(1); } else if (argc == 1) mean(stdin); /* 인수가 없으면 표준입력에서 */ else { /* 인수의 수가 2인 경우 */ if ((fp = fopen(argv[1], “r”)) == NULL) { printf(“Can’t open %s\n”, argv[0]); exit(1); } mean(fp); fclose(fp); } 21 } 22 예제 10.4 줄 9-10: argc가 2가 넘으면 에러 메시지 주고 동료 줄 11-12: argc가 1 즉 file명이 생략되면 표준입력에서 실수들을 받음 줄 14: 해당 file을 연다. 실패면 줄15,16에서 에러 메시지 내고 종료 줄 18,19: 파일 fp의 실수들의 평균 구하는 함수 호출 후 종료
51
예제 10.4(계속) void mean(FILE*)
23 void mean(FILE *fp) 24 { double num, sum = 0; long ct = 0; while (fscanf(fp, “%lf”, &num) > 0) { sum += num; ct++; } if (ct == 0) printf(“No input\n”); else printf(“The average is %f\n”, sum / ct); 34 } 예제 10.4(계속) void mean(FILE*) 함수 mean: FILE 포인터를 받아 해당 file의 실수들의 평균 구함 줄 26-28: double형으로 실수를 읽어 들여 sum에 더하고, ct를 증가시킴 [참고]%lf는 double(즉 long float)형 상수를 읽기 위해 사용 줄 30,31: ct가 0(읽어들인 자료가 없음)인 경우 처리 줄 32,33: 평균을 출력한다. $ cat ex10-4.data 22 33 $ cc –o ex10-4 ex10-4.c $ ex10-4 The average is
52
예제 10.5 1 /* File : ex10-5.c 2 입출력 명을 명령어 줄에서 받아, 파일을 복사하는 프로그램
입출력 명을 명령어 줄에서 받아, 파일을 복사하는 프로그램 getc, putc 사용하여 file복사하시오. */ #include <stdio.h> int main(int argc, char *argv[]) /* 복사 프로그램 */ { int c; FILE *fp1, *fp2; if (argc != 3) { printf(“Usage: %s infile outfile\n”, argv[0]); exit(1); } if ((fp1 = fopen(argv[1], “r”)) == 0) { printf(“cannot open %s\n”, argv[1]); exit(1); } if ((fp2 = fopen(argv[1], “w”)) == 0) { printf(“cannot open %s\n”, argv[2]); exit(1); } while ((c = getc(fp1)) != EOF) putc(c, fp2); fclose(fp1); fclose(fp2); 24 } 예제 10.5
53
줄 9-12: argc가 3이 아니면 에러 메시지 주고 동료
줄 13-16: 입력 file을 open함; 실패면 에러메시지 주고 종료 줄 17-20: 출력 file을 open함; 실패면 에러메시지 주고 종료 줄 21-22: 1 문자씩 읽어 복사함 줄 23: 입, 출력용 두 file을 닫음 다음은 본 프로그램을 동작시키는 장면이다. 입력 파일 input.data를 복사하여 출력 파일 output.data를 만든다. 예제 10.5 [해 설] output $ ex10-5 input.data output.data
54
줄 15-18: 줄바꿈 문자까지 표준입력에서 읽어들여 file로 저장
/* File : ex10-6.c 키보드로부터 텍스트 1줄을 읽어들여 디스크 file로 저장하는 프로그램 */ #include <stdio.h> int main(int argc, char *argv[]) /* 키보드에서 file로 */ { FILE *fp; int c; if (argc != 2) { printf(“Usage: %s filname\n”, argv[0]); exit(1); } if ((fp = fopen(argv[1], “w”)) == NULL) { printf(“cannot open %s\n”, argv[1]); exit(1); } do { c = getchar(); putc(c, fp); } while (c != ‘\n’) /* 줄바꿈 문자가 아닌한 루프를 동작 */ fclose(fp); 20 } 예제 10.6 줄 15-18: 줄바꿈 문자까지 표준입력에서 읽어들여 file로 저장 $ ex10-6 output.data Hi, there! $ cat output.data
55
줄 15-16: file에서 한 문자씩 읽어들여 표준출력으로 내보냄
/* File : ex10-7.c 디스크 file에서 읽어 그 내용을 화면에 복사하는 프로그램 */ #include <stdio.h> int main(int argc, char *argv[]) /* file에서 화면으로 */ { FILE *fp; int c; if (argc != 2) { printf(“Usage: %s filname\n”, argv[0]); exit(1); } if ((fp = fopen(argv[1], “r”)) == NULL) { printf(“cannot open %s\n”, argv[1]); exit(1); } while ((c = getc(fp)) != EOF) /* 1문자를 읽어 들임 */ putchar(c); /* 화면에 출력 */ fclose(fp); 18 } 예제 10.7 줄 15-16: file에서 한 문자씩 읽어들여 표준출력으로 내보냄
56
/* File : ex10-8.c 명령어줄의 인수로 제공된 file의 내용을 역전시켜 화면에 출력하는 프로그램 */ #include <stdio.h> int main(int argc, char *argv[]) { int c; FILE *fp; long count, last, ftell(); if (argc != 2) { printf(“Usage: %s filname\n”, argv[0]); exit(1); } if ((fp = fopen(argv[1], “rb”)) == NULL) { printf(“cannot open %s\n”, argv[1]); exit(1); } fseek(fp, 0L, 2); /* file의 끝으로 이동 */ last = ftell(fp); for (count = 1L; count <= last; count++) { fseek(fp, -count, 2); /* 맨 뒤에서 1바이트씩 이동 */ c = getc(fp); putchar(c); } fclose(fp); 24 } 예제 10.8
57
줄 19 :file끝에서 count개 바이트 뒤의 위치로 이동
예제 10.8 [해 설] output $ cat input.data Hi, there! 2nd line $ ex10-8 input.data enil dn2 !ereht ,iH
58
명령어 줄 인수수가 3인가를 점검하고, 입력,출력용 file을 open한다.
/* File : ex10-9.c 입,출력 file명을 명령어 줄에서 받아, 줄번호 붙여 파일을 복사하는 프로그램 */ #include <stdio.h> #define MAXLINE 80 int main(int argc, char *argv[]) /* 줄번호 붙여 복사 프로그램 */ { char *lineptr; int c; char s[MAXLINE]; FILE *fp1, *fp2, *fopen(); int i = 1; int j = 0; if (argc != 3) { printf(“Usage: %s infile outfile\n”, argv[0]); exit(1); } if ((fp1 = fopen(argv[1], “r”)) == 0) { printf(“cannot open %s\n”, argv[1]); exit(1); } if ((fp2 = fopen(argv[1], “w”)) == 0) { printf(“cannot open %s\n”, argv[2]); exit(1); } 예제 [해 설] 명령어 줄 인수수가 3인가를 점검하고, 입력,출력용 file을 open한다. 실패 시 에러메시지를 주고, exit(1)을 수행하여 종료한다.
59
예제 10.9(계속) [해 설] 줄 28-31: 문자를 배열 s의 다음 위치에 저장
while ((c = getc(fp1)) != EOF) if (c == ‘\n’) { s[j] = ‘\0’; lineptr = s; fprint(fp2, “%3d %s\n”, i, lineptr); i++; j = 0; } else { s[j] = c; j++; } fclose(fp1); fclose(fp2); 33 } 예제 10.9(계속) [해 설] 줄 28-31: 문자를 배열 s의 다음 위치에 저장 줄 21-27: 줄바꿈 문자이면, 그 대신 널문자를 저장하고, lineptr(즉 배열 s)를 출력한다. 줄 24의 출력시 줄바꿈 문자도 추가해서 출력한다. 줄 32: 두 file을 닫는다.
60
줄 14-18: 한 문자씩 읽어, 소문자는 대문자로 바꾸어 출력하고, 그 외의 문자는 그대로 출력한다.
/* File : ex10-10.c 입력 file 명을 명령어 줄에서 받아, 표준출력으로 복사; 단 소문자는 대문자로 */ #include <stdio.h> int main(int argc, char *argv[]) { int c; FILE *fp, *fopen(); if (argc != 2) { printf(“Usage: %s filename\n”, argv[0]); exit(1); } if ((fp = fopen(argv[1], “r”)) == 0) { printf(“cannot open %s\n”, argv[1]); exit(1); } while ((c = getc(fp)) != EOF) if (‘a’ <= c && c <= ‘z’) putchar(c - ‘a’ + ‘A’); else putchar(c); fclose(fp); 20 } 예제 [해 설] 줄 8-10: 명령어 줄 인수의 수를 확인함 줄 11-13: 입력 file을 open한다. 줄 14-18: 한 문자씩 읽어, 소문자는 대문자로 바꾸어 출력하고, 그 외의 문자는 그대로 출력한다.
61
예제 10.11 double_space.c 줄마다 빈 줄 넣어 복사 [해 설]
/* File : double_space.c 입력,출력 file 명을 명령어 줄에서 받아, 줄마다 빈 줄 추가하여 복사 */ #include <stdio.h> int main(int argc, char *argv[]) { int c; FILE *ifp, *ofp, *fopen(); if (argc != 3) { fprintf(stderr, “Usage: %s filename\n”, argv[0]); exit(1); } if ((ifp = fopen(argv[1], “r”)) == NULL) { fprintf(stderr, “cannot open %s\n”, argv[1]); exit(1); } if ((ofp = fopen(argv[2], “w”)) == NULL) { fprintf(stderr, “cannot open %s\n”, argv[2]); exit(1); } while ((c = getc(ifp)) != EOF) putc(ofp); if (c == ‘\n’) /* double space 필요 */ putc(c, ofp); fclose(ifp); fclose(ofp); 22 } 예제 double_space.c 줄마다 빈 줄 넣어 복사 [해 설] 줄 9,12,15: 에러메시지를 표준에러(stderr)로 출력한다. 표준출력과 같이 화면에 출력되지만, 명령어의 표준출력을 파이프나 방향전환으로 사용할 때도 계속 화면에 출력하게 하는 장점이 있어 흔히 사용하는 방법이다. 줄 19-20: 줄바꿈 문자면 1번 더 출력
62
예제 10.11(계속) double_space.c output
$ cat input.data Line 1 Second line Line 3 $ double_space input.data output.data $ cat output.data
Similar presentations