410 likes | 560 Views
13. chapter. Input/Output and Files. 내 용. The Output Function printf() The Input Function scanf() The Function sprintf() and sscanf() The Function fprintf() and fscanf() Accessing Files An Example : Double-Spacing a File Using Temporary Files and Graceful Functions
E N D
13 chapter Input/Output and Files
내 용 • The Output Function printf() • The Input Function scanf() • The Function sprintf() and sscanf() • The Function fprintf() and fscanf() • Accessing Files • An Example : Double-Spacing a File • Using Temporary Files and Graceful Functions • Accessing a File Randomly
The Output Function printf() • printf() • 가변길이의 인자 리스트를 출력할 수 있다. • 간단한 변환 명세나 출력 포맷들로 출력을 제어한다. • printf() 함수의 인자 리스트:control_string과 other_arguments • control_string: "she sells %d %s for $%f" • other_arguments: 99, "sea shells", 3.77 printf("she sells %d %s for $%f", 99, "sea shells", 3.77);
The Output Function printf() • printf() 의 변환문자
The Output Function printf() • 예 : 제어 문자열의 포맷과 그에 대응하는 인자 • 포맷 정보가 변환 명세에 명시적으로 포함되어 있지 않은 경우에는 기본값이 사용(예를 들어%f에 인자에 대해서는 본값으로 소수점 이하 6자리까지 출력) printf("she sells %d %s for $%f", 99, "sea shells", 3.77);
The Output Function printf() • 변환 명세에 올 수 있는 것들 • 변환 명세의 의미를 조절하는 0개 이상의 플래그 문자들 • 변환되는 인자의 최소 필드 폭을 지정하는 양의 정수(선택 사항) printf(“%d |%d|\n”, 1234_); printf(“%8d |%8d|\n”, 1234_); printf(“%-8d |%-8d|\n”, 1234_); printf(“%08d |%08d|\n”, 1234_); printf(“%3d |%3d|\n”, 1234_); %d |1234| %8d | 1234| %-8d |1234 | %08d |00001234| %3d |1234|
The Output Function printf() • 변환 명세에 올 수 있는 것들 • 음이 아닌 정수의 소수점에 의해 지정되는 정밀도(선택사항) • d, i, o, u, x, X변환에서 출력될 최소 자리수를 지정 • e, E, f변환에서는 소수점 이하 자리수를 지정 • g, G변환에서는 최대 유효숫자를 지정 • s 변환에서는 문자열로부터 출력될 문자의 최대 개수를 지정 • 각각 short나 long형 변환자인 h또는 l(선택사항) • long 형 변환자인 L(선택사항) • L다음에 e, E, f, g, G등의 변환 문자가 오면, 변환 명세는 long double형 인자에 적용
The Output Function printf() • 변환 명세의 플래그 문자들 • 좌측 정렬됨을 의미하는 빼기 기호 • 모든 음수들은 빼기 기호로 시작 • 변환 문자에 따라 다른 형태로 변환되게 하는 # • 공백 대신 영으로 채우라는것을 의미하는 0 • * : 인자 리스트로부터 그 값이 주어짐을 의미 • 예 intm, n; doublex = 333.7777777; ...../* get m and n from somewhere */ printf("x = %*.*f\n", m, n, x);
The Output Function printf() • 예 : 문자와 문자열 형식
The Output Function printf() • 예 : 숫자를 출력하기 위해 사용되는 형식
The Input Function scanf() • scanf() • 임의의 개수의 인자를 읽을 수 있다. • 간단한 변환 명세나 형식을 가지고 입력을 제어할 수 있다 • scanf()의 인자 리스트: control_string 과 other_arguments • control_string : "%c%c%c%d%s%lf" • other_arguments : &a, &b, &c, &n, s, &x chara, b, c, s[100]; intn; doublex; scanf("%c%c%c%d%s%lf", &a, &b, &c, &n, s, &x);
The Input Function scanf() • scanf()의 제어문자열 • 일반 문자 • 공백: 입력 스트림에서 무시될 공백을 지정한다. • 변환 명세 • 변환 명세 지시자는 %로 시작하고 변환 문자로 끝난다. • 변환 명세 지시자는 입력 스트림에서 어떻게 문자들이 매치되고 변환되는지는 결정한다. scanf("abc"); scanf(" %c %c %c", &c1, &c2, &c3); /아래와 동일*/ scanf("\t%c \t %c\n%c", &c1, &c2, &c3);
The Input Function scanf() • scanf() 의 변환 문자
The Input Function scanf() • 특수 scanf() 변환 문자
The Input Function scanf() • 입력 스트림에서의 부동소수점 실수 • 기호, 소수점, 숫자로 된 문자열, 지수부 • 지수부 : 기호 뒤에 오는 e 또는 E로 구성 • 예 77/* 부동소수점 실수로 변환 */ +7.7e1/*77과 같다 */ 770.0E-1/*77과 같다 */ +0.003
The Input Function scanf() • 스캔 세트 • 스캔 세트 : [과 ] 사이에 있는 문자들 • %[string] 형태의 변환 명세 • 특별한 문자열을 읽어 들임 %[abc] 포맷 : 단지 a, b, c 만 포함하는 문자열만 입력하고, : 공백이나 다른 문자를 만나게 되면 입력을 중단
The Input Function scanf() • 스캔 세트 • 첫 문자가 ^인 경우 • 스캔 세트 안에 있는 모든 문자들 중 지정된 문자열 이외의 문자들로만 구성 %[^abc] 포맷 : a, b, c를 포함하지 않는 문자열을 입력, : a, b, c 중 하나를 만나면 입력을 중단, : 공백은 받아들임
The Input Function scanf() • 스캔 세트 예 최대 29개의 문자들을 포함하는 문자열, 이 문자열은 A, B, 공백문자, 개행문자, 탭 등으로 구성됨 charstore[30]; scanf("%[AB \n\t]", store); charline[300]; while (scanf(" %[^\n]", line) == 1) printf(%s\n", line); 모든 빈 라인을 건너뛰고, 모든 라인에서 다른 문자보다 앞쪽에 위치하는 공백을 제거
The Input Function scanf() • getc() • 외부 file로 부터 문자를 읽는 함수 • getc는 보통 macro로 구현되어있고 stream의 실행은 최소한 한번 이상이다. • getc() Syntax • fgetc( )와 동일 stream이 point하고 있는 파일 이름 int getc ( FILE *stream ); ifp가 포인트 하는 파일로부터 문자를 읽어 들여 그 값을 c에 저장한다. while ( ( c = getc( ifp ) ) != EOF )
The Input Function scanf() • putc() • 외부 file에 문자를 저장하는 함수. • fputc()와 동일 • putc() Syntax putc가 에러없이 끝나면 c와 동일한 값을 리턴 int putc ( int c, FILE *stream ) ; c를 unsigned char로 변환하고, *stream이 저정하는 파일에 이것을 쓴다. putc( c, ofp ); ofp가 포인트하는 파일에 c값을 쓴다.
The Input Function scanf() • scanf()의 예 • 입력 스트림 : 23 , ignore_this % C abacus read_in_this** • 결과 • 23 : a로 저장 • 쉼표(,) : 매칭 • "ignore_this" : 무시됨 • % : 매칭됨 • ‘C’ : c에 저장 char c, *cntrl_string, save[7], store[15]; int a, cnt; cntrl_string = "%d, %*s %% %c %[ABC] %*s %5s %s"; cnt = scanf(cntrl_string, &a, &c, save, stroe, &store[5]); • "abac“ : save[0]~save[4] • "us" : 무시됨 • "read_“ : store[0]~ store[5] • "in_this**“ : store[5]~store[14] • scanf() :5를 반환
The Function sprintf() and sscanf() • int sprintf(char *s, const char *format, ...); • 키보드로 입력을 받는 대신 s가 가르키는 문자열로부터 읽음 • scanf()와의 차이점 • sscanf()를 이용하여 읽을 경우 이전에 s로부터 읽고 남겨진 부분부터 읽는 것이 아니라 문자열의 시작점부터 다시 읽음 • sprintf(string, control_string, other_arguments) ;
The Function sprintf() and sscanf() • int sscanf(const char *s, const char *format, ...); • 문자열 처리를 위한 printf()문 • 결과를 화면에 출력하는 대신에, 첫 번째 argument인 char형 포인터가 가르키는 곳에 출력 • sscanf(string, control_string, other_arguments);
The Function sprintf() and sscanf() • 예제 charin_string[] = "1 2 3 go"; charout_string[100], tmp[100]; inta, b, c; sscanf(in_string, "%d%d%d%s", &a, &b, &c, tmp); sprintf(out_string, "%s %s %d%d%d\n", tmp, tmp, a, b, c); printf("%s",out_string); go go 123
The Function fprintf() and fscanf() • fprintf() and fscanf() • printf()와scanf()의 파일 버전 • stdio.h에 있는 파일 포인터
The Function fprintf() and fscanf() • int fprintf(FILE *ofp, const char *format, ...); • file_ptr이 가리키는 파일에 쓴다는 것을 나타냄 • control_string과 other_arguments는printf()와 동일 • fprintf(stdout, ...);과 printf(...); 은 같은 의미 • int fscanf(FILE *ifp, const char *format, ...); • file_ptr가 지정하는 파일로부터 control_string의 지시에 따라 문자를 읽는다 • fscanf(stdin, ...); 과 scanf(...); 는 같은 의미
Accessing Files • File pointer • File I/O는 disk file명이 아닌 file pointer를 통해 stream을 생성하여 수행. • 선언 • ‘FILE’ Type • stdio.h file에서 typedef로 정의된 type으로 file에 대한 여러 정보를 수록한 struct type FILE *fp; /* file pointer로 ‘fp’ 선언 */
Accessing Files • fopen() • 외부 file을 프로그램에서 사용할 때 필요한 명령 • 예 FILE *fopen( const char *filename, const char *mode ); file pointer로 return disk에 있는 filename file open시의 mode /* 읽기 전용으로 in.txt파일을 연다. */ fp = fopen( “in.txt”, “r”);
Accessing Files • fopen() 의 모드
Accessing Files • fclose() • fopen으로 open한 파일의 사용이 끝나면 fclose를 써서 파일을 닫을 때 필요한 명령어 • Returns 0 : successful EOF : error (EOF is defined as –1 in stdio.h) int fclose( FILE *stream ); open했던 file pointer name
Accessing Files • fopen()과 fclose()의 예 int main(void) { int sum = 0, val; FILE *ifp, *ofp; ifp = fopen("my_file", "r"); /* open for reading */ ofp = fopen("outfile", "w"); /* open for writing */ ……. while (fscanf(ifp, "%d", &val) == 1) sum += val; fprintf(ofp, "The sum is %d.\n", sum); fclose(ifp); fclose(ofp); }
An Example : Double-Spacing a File #include <stdio.h> #include <stdlib.h> void double_space(FILE *, FILE *); void prn_info(char *); int main(int argc, char **argv) { FILE *ifp, *ofp; if (argc != 3) { prn_info(argv[0]); exit(1); } ifp = fopen(argv[1], "r"); /* open for reading */ ofp = fopen(argv[2], "w"); /* open for writing */ double_space(ifp, ofp); fclose(ifp); fclose(ofp); return 0; } prn_info()함수에서 exit()함수를 사용하기 때문에 포함시킴 명령어 라인의 인자로 두 개의 파일에 접근하게 되어있다. ex) a.out file1 file2 ifp, ofp는 파일 포인터 exit()함수는 오류가 발생하면 0이 아닌 값을 리턴한다.
An Example : Double-Spacing a File void double_space(FILE *ifp, FILE *ofp) { int c; while ((c = getc(ifp)) != EOF) { putc(c, ofp); if (c == '\n') putc('\n', ofp); /* found newline - duplicate it */ } } void prn_info(char *pgm_name) { printf("\n%s%s%s\n\n%s%s\n\n", "Usage: ", pgm_name, " infile outfile", "The contents of infile will be double-spaced ", "and written to outfile."); } file1에서 읽어 들이고 file2에 쓸 것이다. file2의 내용은 file1과 같지만 모든 개행 문자가 복사되어 매 줄마다 빈 줄이 한 줄씩 추가 되어있을 것이다.
Using Temporary Files and Graceful Functions • tmpfile() • C에서 파일이 닫히거나 프로그램이 종료될 때 자동적으로 삭제되는 임시 파일을 생성하기 위한 함수 • 최신의 자료로 수정되기 위해 “wb+” 모드로 열림 • 예 FILE *tmpfile(void); char *tmpnam(char *s); FILE *tempptr; tempptr = tmpfile( ); /* creates a temporary file */
Using Temporary Files and Graceful Functions • 예 : dbl_with_caps 프로그램의 동작 • 쓰기와 읽기용인 갱신 모드로 임시파일 열기 • 모든 소문자를 대문자로 바꾸어 첫 번째 파일의 내용을 임시파일로 복사하기 • 첫 번째 파일의 끝부분에 표시 줄을 써서 원래 파일의 내용과 덧붙일 내용 구분하기 • 임시파일의 내용을 첫 번째 파일의 끝부분에 덧붙이기
Using Temporary Files and Graceful Functions #include <ctype.h> #include <stdio.h> #include <stdlib.h> FILE *gfopen(char *filename, char *mode); int main(int argc, char **argv) { int c; FILE *fp, *tmp_fp; if (argc !=2) { fprintf(stderr, "\n%s%s%s\n\n%s%s\n\n", "Usage: ",argv[0], " filename", "The file will be doubled and some ", "letters capitalized."); exit(1); } fp = gfopen(argv[1],"r+"); /*open for read write*/ tmp_fp = tmpfile(); /*open for write read*/ 명령어 라인의 argument가 2개가 아니면 에러 메세지를 출력한다.
Using Temporary Files and Graceful Functions while ((c=getc(fp)) != EOF) putc(toupper(c), tmp_fp); /*capitalize lowercase*/ fprintf(fp, "---\n"); rewind(tmp_fp); while ((c=getc(tmp_fp)) != EOF) putc(c,fp); return 0; } /* A graceful version of fopen(). */ FILE *gfopen(char *fn, char *mode) { FILE *fp; if ((fp = fopen(fn,mode)) == NULL) { fprintf(stderr, "Cannot open %s - bye!\n",fn); exit(1); } return fp; } toupper()의 함수 프로토타입은 ctype.h에 정의되어 있다 file pointer의 indicator를 file의 시작하는 부분으로 옮긴다. fseek(tmp_fp, 0, 0); tmp_fp가 포인트하는 스트림에서 쓰기에서 읽기로 전환되기 전에 rewind()를 호출 A is for apple and alphabet pie. --- A IS FOR APPLE AND ALPHABET PIE.
Accessing a File Randomly • 파일에 random하게 접근하기 위해 fseek(), ftell() 사용 • file position indicator의 현재 값을 return • return된 값은 처음을 0으로 두고 처음부터 몇 byte 떨어져 있는가의 값을 나타냄 • 파일로부터 한 문자씩 읽을 때마다 indicator의 값을 1증가시킴 • place에서 offset만큼 떨어진 위치에 file position indicator를 둠 • place의 값 : 0(파일의 맨처음 ), 1(현재위치), 2(맨끝) ftell(file_ptr); fseek( file_ptr, offset, place);
Accessing a File Randomly • 예 : 파일을 역으로 출력 include <stdio.h> #define MAXSTRING 100 int main(void) { char file_name[MAXSTRING]; int c; FILE *ifp; fprintf(stderr, "\nInput a file name: "); scanf("%s", file_name); ifp = fopen(file_name, "rb"); /*ms-dos binary mode*/ fseek(ifp,0,2); /*move to end of file*/ fseek(ifp,-1,1); /*back one charcater*/ 문장의맨 끝에서 0번째 위치에 ifp를 둔다. 문장의 현재위치(위의 결과로 끝 문자)에서 -1번째, 즉 앞 문자에 ifp를 둔다
Accessing a File Randomly while (ftell(ifp) >= 0) { c = getc(ifp); /*ahead one character*/ putchar(c); fseek(ifp,-2,1); /*back two characters*/ } return 0; } ifp가 0보다 클 동안 while 함수를 실행하는데 true일 경우 ifp의 indicator 값을 하나 증가시킨다. fseek함수를 이용하여 현재위치에서 앞에 두 번째 문자를 ifp로 한다