9장 파일 입출력
목차 1. 파일 입.출력 2. 시스템 입.출력 함수 1.1 파일 포인터 1.2 파일 open 1.3 파일 유형별 입.출력 함수 1.4 레코드 포인터 2. 시스템 입.출력 함수
1. 파일 입.출력 ( ) 스트림을 사용하는 이유 바이트의 흐름을 나타내는 논리적인 장치(혹은 단위) ( ) 바이트의 흐름을 나타내는 논리적인 장치(혹은 단위) 입출력장치(키보드,모니터,파일,네트워크,DB등)와 Application(프로그램) 간의 데이터를 주고받는 인터페이스(interface)역할 스트림을 사용하는 이유 모든 입출력 장치에 ( )하기 위해 모니터 키보드 Application (프로그램) 파일 네트워크
1. 파일 입.출력 ( ) 입.출력 스트림 키보드,모니터로 데이터 입출력을 위한 인터페이스 ( )로 데이터를 입력 ( ) ( ) 입.출력 스트림 키보드,모니터로 데이터 입출력을 위한 인터페이스 ( )로 데이터를 입력 ( ) ( )로 데이터를 출력 ( ) 키보드 프로그램 모니터 표준 입력 스트림 표준 출력 스트림
1. 파일 입.출력 표준 입출력 스트림 표준 입출력 스트림의 생성과 소멸 생성 : 프로그램 시작 시 소멸 : 프로그램 종료 시 용도 장치 표준 입력을 담당 키보드 표준 출력을 담당 모니터 stderr 표준 에러를 담당
1. 파일 입.출력 표준 입출력 함수의 종류(헤더파일 : stdio.h) 함수의 원형 기능 스트림 int getchar (void); 키보드로 부터 한 문자를 입력 받는다. stdin int putchar (int c); 모니터에 한 문자를 출력한다. stdout char* gets (char *s); 키보드로 부터 문자열을 입력 받는다. int puts (char* str); 모니터에 문자열을 출력한다. int scanf (const char* format, …); 키보드로 부터 데이터를 서식에 맞춰 출력한다. int printf (const char* format, …); 모니터에 데이터를
getchar( ) 함수 putchar( ) 함수 EOF(End Of File) ( )를 입력하는 함수 ( ) 를 출력하는 함수 EOF(End Of File) 파일의 끝을 의미 stdio.h 에 -1로 매크로 상수 정의 [ctr+z]를 입력하면 EOF로 인식
예제. #include<stdio.h> int main(void) { char ch=0; while( ch != EOF) // EOF == -1 ch=getchar(); putchar(ch); }; return 0; }
1. 파일 입.출력 표준 입출력 스트림 파일 입출력 스트림 언제든지 표준 입출력 함수 대신 파일 입출력 함수를 이용해서 표준 입출력을 처리할 수 있다.
1. 파일 입.출력 파일 입출력의 필요성 ‘실행 중에 데이터가 생성되면 데이터는 메모리에 보관 된다.’ 문제점 : 프로그램이 종료되면 사라짐 데이터를 프로그램이 종료된 후에도 계속해서 사용하려면? 파일에 저장 ‘중요한 데이터를 파일에 저장한다.’ ‘필요할 때 파일을 읽어 데이터를 사용한다.’
1. 파일 입.출력 파일 입출력의 기본 틀
1. 파일 입.출력 파일의 입출력 절차 파일 열기 실제 파일입출력 작업 시행 모든 입출력이 끝나면 파일을 닫는다. 먼저 스트림을 생성한 다음에 입출력을 수행 fopen 함수로 파일을 열면 ( )가 리턴된다. 파일에 접근하려면 항상 ( ) 가 필요하다. 실제 파일입출력 작업 시행 텍스트 파일 입출력 : fgetc, fputc, fgets, fputs, fscanf, fprintf 바이너리 파일 입출력 : fread, fwrite 모든 입출력이 끝나면 파일을 닫는다. 파일을 닫을 때 fclose 함수 사용
1.1 파일 포인터 파일 포인터(파일 스트림) 선언 형식: FILE * 파일포인터이름; 예) FILE* fp; 파일 구조체
1.2 파일 Open 파일 스트림 생성/삭제 함수 fopen(filename, mode) 첫번째 인수 open할 파일이름 파일의 경로와 이름을 동시에 표현 : 절대경로, 상대경로 두번째 인수 파일(읽기,쓰기, 텍스트, 바이너리등) 모드 설정 파일의 접근 모드와 파일의 입출력모드 표현 리턴 값 생성된 파일 스트림(파일 포인터) 함수의 원형 설명 #include <stdio.h> FILE* fopen (const char* filename, const char* mode); 파일 스트림을 생성하고 파일을 연다. 호출 실패의 경우: ( )반환 int fclose (FILE* stream); 파일을 닫는다. 호출 실패의 경우: EOF 반환
1.2 파일 Open 파일의 접근 모드 (r, w, a, r+, w+, a+) 모드 설명 읽기 전용으로 파일을 연다. 파일이 없거나 찾을 수 없는 경우에 호출 실패 쓰기 전용으로 파일을 연다. 지정한 파일명이 있는 경우: 파일 내용을 모두 지우고 새로 만든다. 지정한 파일명이 없는 경우: 새로운 파일을 생성 한다. 추가 쓰기 전용으로 파일을 열다. 지정한 파일이 있으면 파일의 끝에서부터 내용을 추가합니다. 파일을 읽고 쓰기 위해 연다. 지정한 파일이 있는 경우: 기존의 내용을 덮어쓴다. 지정한 파일이 없는 경우: 새로운 파일을 생성하지 않는다(파일열기오류). 지정한 파일이 있는 경우: 파일의 내용을 모두 지우고 새 파일을 만든다. 지정한 파일이 없는 경우: 새로운 파일을 생성 한다. 파일을 읽고 추가 쓰기 위해 연다. 파일이 없으면 새로 생성하고, 파일의 어떤 위치도 읽을 수 있지만 쓰기는 파일의 맨끝에만 할 수 있다. 나머지 기능은 r+와 같다.
1.2 파일 Open 파일 입출력 모드 text 모드 binary 모드 모드 설명 t 텍스트 파일 모드 b 바이너리 파일 모드
1.2 파일 Open 파일의 유형 텍스트 파일(Text File) 바이너리 파일(Binary File) 데이터 내용을 확인할 수 있는 문자들을 저장해놓은 파일 문자열과 같은 텍스트 기반의 데이터 파일 예) *.txt, *c, *.doc 바이너리 파일(Binary File) 일반 문서 편집기에서 내용을 확인 할 수 없음 이진 형식으로 인코딩된 데이터 파일 바이너리 파일을 텍스트 모드로 열면 글자가 깨지는 현상이 발생 예) *.obj, .exe, *.lib
1.2 파일 Open r : 읽기 (read) w: 쓰기 (write) a: 추가 (append) 파일 접근 모드 텍스트/바이너리 모드 파일 오픈 모드 r : 읽기 (read) w: 쓰기 (write) a: 추가 (append) t : 텍스트 파일 모드(text file mode) b: 바이너리 파일 모드 (binary file mode)
/* case 1 */ FILE* stream; stream=fopen("d:\\project\\data.txt", "rt"); /* case 2 */ FILE* stream stream=fopen("data.txt", “wt"); /* case 3 */ stream=fopen(“.\\data.txt", “r"); /* case 4 */ stream=fopen("d:\\project\\data.txt", “w"); /* case 5 */ stream=fopen(“..\\data.txt", “ab"); 텍스트 모드의 경우 ‘t’ 생략 가능
파일 Close 파일 입출력이 끝나면 fclose 함수를 호출해서 반 드시 파일을 닫아야 한다. fclose 함수의 원형 stream : 파일 포인터 리턴 값 파일 닫기 성공 : 0 리턴 파일 닫기 실패 : EOF(-1) 리턴
(p231)
(P232)
예제. #include<stdio.h> int main(void) { FILE* fp; // 파일 스트림 생성을 위한 FILE 포인터 선언 int file_state; // 파일의 종료를 위한 상태 체크 변수 선언 // 파일 스트림 생성과 파일 열기 fp = fopen("data1.txt", "r+"); if (fp == ( )) // 파일이 없는 경우 printf("파일 열기 에러\n"); else puts("파일 열기 성공\n"); // 파일 닫기(파일 스트림 소멸) if (fp == ( )) puts("파일이 열려있지 않습니다."); else { file_state = fclose(fp); if (file_state == ( )) puts("파일 닫기 에러"); puts(“파일 닫기 성공"); file_state = fclose(fp); // 파일 닫기 재시도 } 예제.
1.3 파일 유형별 입.출력 함수 표준 입출력 함수와 표준 파일 입출력 함수 표준 입출력 함수 표준파일 입출력 함수 기능 int getchar (void); int fgetc (FILE* stream); 문자 단위 입력 int putchar (int c); int fputc (int c, FILE* stream); 출력 char* gets (char *s); char* fgets (char *s, int n, FILE* stream); 문자열 단위 int puts (char* str); int fputs (const char* s, FILE* stream); int scanf (const char* format, …); int fscanf (FILE* stream, const char* format, …); 자료형에 맞춘 int printf (const char* format, …); int fprintf (FILE* stream, const char* format, …);
1.3 파일 유형별 입.출력 함수 한 문자 입출력 함수 키보드로부터 한 문자 입력 파일로부터 한 문자 입력 fgetc(stdin) = getc(stdin) = getchar( ) 파일로부터 한 문자 입력 fgetc(fp) = getc(fp) 모니터로 한 문자 출력 fputc(c, stdout) = putc(c, stdout ) = putchar(c ) 파일로 한 문자 출력 fputc(c, fp) = putc(c, fp) 함수의 원형 설명 int fgetc (FILE* fp); 키보드/파일로 부터 한 문자를 입력 받는다. 파일의 끝에 도달 할 경우: ( ) 반환 int fputc (int c, FILE* fp); 모니터/파일에 한 문자를 출력한다. 호출 실패의 경우: ( ) 반환
1.3 파일 유형별 입.출력 함수 한 행(line) 입출력 키보드로부터 한 행 입력 파일로부터 한 행(line) 입력 fgets(buff, n, stdin); 키보드로부터 입력되는 값을 (n-1)만큼 buff로 읽어온다 엔터키(\n)값까지 포함시킨다. 명시된 크기(n)를 채우기 전 엔터키(\n)가 입력되면 엔터키까지만 buff로 읽어온다. gets(buff); 엔터키가 입력될 때까지 키보드로부터 입력되는 값을 buff로 읽어온다 엔터키(\n)값은 포함시키지 않는다. 파일로부터 한 행(line) 입력 fgets(buff, n, fp) 파일로부터 (n-1)만큼 또는 엔터키(\n)값까지 buff로 읽어온다 함수의 원형 설명 char* fgets (char* buff, int n, FILE* fp); 키보드/파일로 부터 문자열을 입력 받는다. 파일의 끝에 도달 할 경우: ( ) 포인터 반환 int fputs (const char* buff, FILE* fp); 모니터/파일에 문자열을 출력한다. 호출 실패의 경우: ( ) 반환
fgets( )/ fputs( )의 예제 1 다음 변수를 선언하라 FILE* fp; char buffer[50]; “oldfpnt.txt”을 쓰기모드(“w”)로 열어라 fp = fopen( … ) 사용 키보드로부터 buffer로 이름을 입력 받아라 fgets( … ) 사용 입력 받은 이름을 파일에 기록하라 fputs( … ) 사용 파일을 닫아라 fclose( … ) 사용
표준 입력스트림(stdin)으로부터 읽어서 fgets( )/ fputs( )의 예제 1 #include<stdio.h> int main(void) { FILE* fp; char buffer[50]; ( )= fopen("( )","( )"); if(fp == ( )) puts("파일 열기 오류"); else{ printf("이름을 입력하시오 :" fgets(( ), ( ), ( )); fputs(( ), ( )); fclose(( )); } return 0; 표준 입력스트림(stdin)으로부터 읽어서 표준 파일스트림(fp)에 씀
fgets( )/ fputs( )의 예제2 #include<stdio.h> int main(void) { FILE* fp; char buffer[50]; ( )= fopen("( )","( )"); if(fp == ( )) puts("파일 열기 오류"); else{ printf("이름을 입력하시오 :" fgets(( ), ( ), ( )); fputs(( ), ( )); fclose(( )); } return 0; 다음 명령문을 EOF가 입력되지 않는 동안 ((CTRL+Z)이 눌릴때까지) 반복하도록 수정하시오
fgets( )/ fputs( )의 예제2 -수정결과 #include<stdio.h> int main(void) { FILE* fp; char buffer[50]; fp= fopen("oldfpnt.txt","w"); if(fp == NULL) puts("파일 열기 오류"); else{ printf("이름을 입력하시오(종료 : Ctrl+z) : "); ( ) ( (fgets(buffer,sizeof(buffer),stdin)) != ( )) { fputs(buffer,fp); } fclose(fp); } return 0;
P235 NULL
실패시 리턴값 ( ) 반환 fopen, fgets ( ) 반환 fopen, fgets fclose, fgetc, fputc, fputs, fscanf, fprintf
파일 복사하기 예제 파일 이름 두개를 입력받는다. 이미 text2.txt가 존재하는 경우 덮어쓸지 물어본 다. 원본 파일 이름을 입력하시오 : test.txt 저장할 파일 이름을 입력하시오 : test2.txt test.txt를 text2.txt로 복사한다. 이미 text2.txt가 존재하는 경우 덮어쓸지 물어본 다. Y를 입력한 경우만 test2.txt를 덮어씌우고 N이 입력되면 그냥 종료 text2.txt가 존재하지 않으면 원본 파일을 복사해 저장한다.
파일 복사 화면
#include<stdio.h> void filecopy(FILE *source, FILE *target); void main(void) { char sfile[20], tfile[20]; FILE *source, *target; char answer; printf("원본 파일을 입력하시오. : "); gets(( )); printf("저장할 파일을 입력하시오. : "); source = fopen(( ), ( )); // 읽기 전용으로 열기 if(( ) == ( )) { printf("%s 파일이 존재하지 않습니다.\n", sfile); return; }
else if ((( ) = fopen(( ), ( ))) != ( )) { // 파일이 이미 존재 printf("%s 파일이 존재합니다. 덮어쓰시겠습니까? : (y/n)", tfile); if (answer == 'y') filecopy(( ), ( )); } else { target = fopen(tfile, ( )); // 존재하지 않으므로 새로 만듬 fclose(( )); puts("파일 복사를 종료합니다.\n"); 대소문자 변환 : tolower(), toupper() / ctype.h ex) answer = tolower(getchar());
void filecopy(FILE *source, FILE *target) { char buffer[50]; int i = 1; while( (fgets(( ), ( ), ( ))) != ( )) { fputs(( ), ( )); printf("%d..", i++); } puts("\n");
Main에 매개변수 넘겨주기 void main(int argc, char *argv[]) argc : 매개변수 개수 예) filecopy a.txt b.txt argc = 3 argv[0] = “filecopy” argv[1] = “a.txt” argv[2] = “b.txt”
void main(int argc, char *argv[]) { FILE *source, *target; char answer; if(argc != 3) { printf("[형식] filecopy 원본파일이름 저장할파일이름\n”); return; } printf("원본 파일 : %s\n", argv[1]); printf("저장 파일 : %s\n ", argv[2]); source = fopen(argv[1], "r"); if(source == NULL) { printf("%s 파일이 존재하지 않습니다.\n", argv[1]); else if ((target = fopen(argv[2], "r+")) != NULL) { // 파일이 이미 존재 printf("%s 파일이 존재합니다. 덮어쓰시겠습니까? : (y/n)", argv[2]); while( answer != 'y' && answer != 'n') answer = getchar(); // answer = getc(stdin); 과 동일 if (answer == 'y') filecopy(source, target); else { target = fopen(argv[2], "w"); // 존재하지 않으므로 새로 만듬
1.3 파일 유형별 입.출력 함수 형식이 있는 자료형(레코드) 단위 입출력 헤더파일: <stdio.h> 함수의 원형 설명 int fscanf (FILE* fp, const char* format, …); 키보드/파일로 부터 자료형에 맞춰 데이터를 입력한다. 파일의 끝에 도달한 경우: EOF 반환 int fprintf (FILE* fp, const char* format, …); 모니터/파일에 자료형에 맞춰 데이터를 출력한다.
1.3 파일 유형별 입.출력 함수 fscanf( )/ fprintf( ) 사용 예 #include<stdio.h> int main(void) { FILE* fp; char name[20]; int kor, eng, total; printf("1. 이름입력: "); fscanf(( ),"%s",name); // 키보드로부터 데이터를 입력 printf("2. 국어점수, 영어점수입력: "); fscanf(( ),"%d %d",&kor, &eng); // 키보드로부터 데이터를 입력 total = kor + eng; fp = fopen("data.txt","w"); fprintf(( ),"%s %d %d %d \n", name, kor, eng, total); //data.txt에 출력 fprintf(( ),"%s %d %d %d \n", name, kor, eng, total); // 모니터에 출력 fclose(fp); return 0; }
p236 atoi() 함수때문에 필요 getch() 함수때문에 필요 #include <string.h> 지정된 문자열(STR)을 int 형으로 변환 숫자로 인식 가능한 문자가 존재하지 않는다면 0을 리턴 예) atoi(“123abc” ) -> 123 예) atoi(“1234”) -> 1234 예) atoi(“abc123”) -> 0 (zero_check(bunho) || strlen(str) > 4) #include <string.h>
P236 SUB FUNCTION Y n==0인경우 숫자로 인식 가능한 문자가 존재하지 않는 경우로서 1를 리턴 숫자로 인식 가능한 문자가 존재하지 않는 경우로서 1를 리턴 Y toupper( ) 함수 지정된 문자를 대문자로 변환한다
p237 “C:\\newfile.dat <stdlib.h> 에 정의됨
학번 9자리와 이름 입력 학번 숫자 9자리와 이름을 계속 입력받아 현재 디렉토리에 student.txt 파일에 저장하고 학번이 0이거나 숫자 9자리가 아니면 계속 다시 입력받 음 현재 디렉토리에 student.txt 파일에 저장하고 순서대로 읽어서 출력하는 프로그램을 작성하시오.
#include <stdio.h> // standard input/output #include <stdlib.h> // standartd library #include <conio.h> // console input/output #include <string.h> // string int zero_check(int n); int more_data( ); void main( ) { FILE *dfpnt; long bunho; char *str, name[10]; char *filename = ".\\newfile.dat"; str = (char *) malloc(10); dfpnt = fopen(filename,"w"); do { printf(“\n\n학번="); gets(str); bunho = atoi(str); } while (( )|| ( ) != 9 ); printf("이름="); gets(name); fprintf(dfpnt, “ %9d %10s ", bunho, name); } while (more_data( )); printf("\n"); fclose(dfpnt);
if ((dfpnt = fopen(( ),( ))) ==( )) { printf("\n input file open error"); exit(1); // <stdlib.h> 에 정의됨 } while(fscanf(dfpnt, “ %9d %10s ", &bunho, name) != ( )) printf("\n%9d-%10s\n", bunho, name); fclose(dfpnt); int more_data( ) printf("\n계속 하시겠습니까?(y/n)="); if (tolower(getch( )) == 'y') return 1; else return 0;
1.3 파일 유형별 입.출력 함수 파일의 끝을 확인하는 방법 단점 단점 해결 ‘파일 끝에서 반환되는 값이 함수마다 다르다.’ feof()함수 함수 파일의 끝에서 반환하는 값 fgetc( ) EOF(-1) fgets( ) NULL(0) fscanf( )
1.3 파일 유형별 입.출력 함수 파일의 끝을 검사하는 feof()함수 함수 원형 설명 int feof(FILE* fp); 파일포인터가 파일의 끝에 도달했는지 아닌지를 검사 파일의 끝에 도달 : 0이 아닌 값 반환 파일의 끝에 도달하지 못한 경우 : 0 반환
feof( ) 함수 예 (p237 예제 수정) “C:\\newfile.dat” 다음 while 조건문을 feof( ) 함수를 이용하여 EOF를 확인하도록 바꾸시오
feof( ) 함수 예 - 수정결과 while( !feof(infpnt) ) { fscanf(infpnt, “ %4d %10s ”, &bunho, name); printf(“\n%4d-%10s”, bunho, name); } “C:\\newfile.dat”
1.3 파일 유형별 입.출력 함수 버퍼를 비우는 fflush( )함수 버퍼(Buffer) 처리할 데이터를 임시로 저장하는 장소 입력 버퍼 : 입력 데이터를 저장하기 위한 버퍼 출력 버퍼 : 출력 데이터를 저장하기 위한 버퍼 함수 원형 설명 int fflush(FILE* fp); 버퍼를 비움 실패 : EOF 반환 stdout stdin
1.3 파일 유형별 입.출력 함수 버퍼링으로 인한 문제 21\n 21 \n #include <stdio.h> int main(void) { int age; char name[20]; printf("나이입력: "); scanf("%d",&age); //fflush(stdin); // 입력 버퍼를비운다. printf("이름을 입력: "); fgets(name, sizeof(name), stdin); printf("%d\n",age); printf("%s\n",name); return 0; } 21\n 21 \n
1.3 파일 유형별 입.출력 함수 문제가 생기는 이유 문제점 해결 fflush(stdin)함수를 호출함으로써 입력버퍼를 비운다.
1.4 레코드 포인터(p238) fseek( ) 함수 두번째 인수(offset ) 음수일때-> 파일포인터를 앞쪽으로 이동 양수일때-> 파일포인터를 뒤쪽으로 이동(0 일때는 제자리에) 세번째 인수(origin ) 함수 원형 설명 int fseek(FILE* fp, long offset, int origin); origin부터 offset만큼 파일포인터를 이동시킨다. 성공 : 0 반환, 실패 : 0이 아닌 값 반환 기호 상수 값 설명 SEEK_SET 파일의 시작 위치 SEEK_CUR 1 파일의 현재 위치 SEEK_END 2 파일의 끝 위치
1.4 레코드 포인터 fseek(파일 포인터이름, 0, SEEK_SET); fseek(파일 포인터이름, 2,SEEK_SET);
1.4 레코드 포인터 fseek(파일 포인터이름, -1, SEEK_END);
1.4 레코드 포인터 SEEK_CUR의 위치 fseek(파일포인터이름, -2, SEEK_CUR);
ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ?? fseek( ) 함수 사용 예 #include <stdio.h> int main(void) { FILE* fp; fp=fopen("seek.txt", "w"); // 쓰기 모드 fputs("ABCDEFGHIJ", fp); fclose(fp); fp=fopen("seek.txt", "r"); // 읽기 모드 fseek(fp, 0, SEEK_SET); fprintf(stdout, "%c \n", fgetc(fp)); fseek(fp, 2, SEEK_SET); fseek(fp, -1, SEEK_END); fseek(fp, -2, SEEK_CUR); return 0; } ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ABCDEFGHIJ ??
예제 example.txt 파일을 생성(“w+”이용)하여 "This is an apple" 을 쓰고 화면에 표시(fputs이 용) 다시 fseek 함수를 이용하여 n 부터 “ sam” 으로 4개의 문자열을 바꾼다. (fseek, fputs이용) 즉, example.txt 에는 "This is a sample" 이 들어가게 된다. fseek을 이용하여 파일의 맨 처음으로 가서 한 문 장을 읽어 화면에 출력한다. (fseek, fgets, fputs 사용)
1.4 레코드 포인터(p237) ftell( ) 함수 파일의 시작위치로부터 떨어진 거리를 알려준다 읽기/쓰기 작업의 위치로서 함수 원형 설명 long ftell(FILE* fp); 파일 포인터의 위치를 확인 성공 : 파일 포인터의 위치 반환 실패 : EOF 반환 읽기/쓰기 작업의 위치로서 파일의 시작부분에서 부터의 offset 바이트 수
ABCDEFGHIJ ftell( ) 함수 사용 예1 1. 끝에서 -8이동 fgetc에 의해 1바이트 이동 #include <stdio.h> int main(void) { FILE* fp; long distance; fp=fopen("ftell.txt", "w"); // 쓰기모드 fputs("ABCDEFGHIJ", fp); fclose(fp); fp=fopen("ftell.txt", "r"); // 읽기모드 fseek(fp, -8, SEEK_END); fprintf(stdout, "%c \n", fgetc(fp)); distance=ftell(fp); printf("거리: %ld \n", distance); return 0; } ABCDEFGHIJ 3. ftell 거리 = 3 fgetc에 의해 1바이트 이동
ftell( ) 함수 사용 예2 파일 사이즈 구하기 #include<stdio.h> int main(void) { FILE* fp = fopen("ftell.txt", "rb"); fseek(fp, 0, SEEK_END); printf("ftell.txt 파일의 크기 : %d 바이트\n", ftell(fp)); fclose(fp); return 0; } [p.238 예제] 파일의 현재위치를 확인한 후 지정해준 옵셋과 origin 을 이용하여 새로운 위치로 이동시키는 프로그램을 작성
파일 크기 구하기 예제 파일의 이름을 입력받아 (char *filename, scanf) 해당 파일의 바이트수를 구해 출력하시오.(fseek, ftell이용)
void *malloc(size) char *filename; // 주소값을 가지는 문자열포인터 그냥 scanf(“%s”, filename) 이용하면 run-time 오류 발생 이유 : filename이 주소값만 가지는 문자열 포인터이기때문 해결 : 문자열을 보관할 수 있는 메모리 영역을 할당하여 filename이 그 주소를 지시할 수 있게 해야함. malloc의 리턴타입은 void * 이므로 캐스트 연산해주어야 함. filename = (char *) malloc(5); 할당해제 : free(포인터변수) free(filename); filename filename+1 filename+2 filename+3 filename+4 filename
파일 이름 입력받기 test.txt\n test.txt\0 문자열만 입력받는 함수 문자열의 끝 엔터값까지 입력받는 함수 scanf("%s",filename); gets(filename); 문자열의 끝 엔터값까지 입력받는 함수 fgets(filename,50,stdin); 다음처럼 마지막 엔터값을 없애줘야함. filename[strlen(filename)-1] = '\0'; filename 변수에 저장된 문자열길이 -1에 강제로 NULL을 넣어줌 test.txt\n test.txt\0
(P238 수정) char * filename; 을 사용한다면??? #include <stdio.h> int main( ) { char filename[20]; FILE *infpnt; int offset, origin; printf("파일 이름을 입력하세요.. : "); gets(filename); printf("파일 = %s\n", filename); if ((infpnt = fopen(filename,"r")) == NULL) printf("\n%s 파일 열기 오류\n", filename); return 1; } fseek(infpnt, 0, SEEK_END); // 파일끝으로 이동 printf("\n%s 파일의 크기 : %d 바이트\n",filename, ftell(infpnt)); fseek(infpnt, 0, SEEK_SET); // 파일 현재 위치 printf("\n파일 %s의 현재 위치=%d\n", filename, ftell(infpnt)); printf("\nOrigin(0-처음, 1-현재, 2-끝)과 바이트수(offset)를 입력하시오 :"); scanf("%d,%d", &origin, &offset); fseek(infpnt, offset, origin); printf("파일 %s의 %d부터 %d위치의 내용은 = %c\n", filename, origin, offset, getc(infpnt)); printf("\n--------------------\n"); fclose(infpnt); return 0; (P238 수정) char * filename; 을 사용한다면??? char *filename = (char *) malloc(20); free(filename);
int main( ) { char filename[20], *str_origin[3] = {"처음", "현재", "끝" } ; FILE *infpnt; int offset, origin; char temp[50]; printf("파일 이름을 입력하세요.. : "); gets(filename); printf("파일 = %s\n", filename); fseek(infpnt, 0, SEEK_SET); // 파일 현재 위치 fgets(temp, 5, infpnt); printf("%s\n", temp); printf("\n파일 %s의 현재 위치=%d\n", filename, ftell(infpnt)); printf("\nOrigin(0-처음, 1-현재, 2-끝)과 바이트수(offset)를 입력하시오 :"); scanf("%d,%d", &origin, &offset); fseek(infpnt, offset, origin); printf("파일 %s의 %s부터 %d위치의 내용은 = %c\n", filename, str_origin[origin], offset, getc(infpnt)); printf("\n--------------------\n"); fclose(infpnt); return 0; }
2. 시스템 입.출력 함수 고급 입출력 함수 저급 입출력함수 = 시스템 입출력 함수 버퍼를 사용한다. 버퍼를 사용하지 않는다. 헤더파일: <stdio.h> 버퍼를 사용한다. 버퍼에 데이터를 모았다가 한번에 처리 저속, 고효율 저급 입출력함수 = 시스템 입출력 함수 헤더파일 : <io.h> 버퍼를 사용하지 않는다. 데이터를 모으지 않고 바로 처리 고속, 저효율 이식성 문제
2.1 Open( ) Open ( ) 함수 첫번째 인수 두번째 인수 세번째 인수 리턴 값 open할 파일이름 파일의 접근 모드 새 파일 생성시 새 파일의 속성 설정 리턴 값 생성된 파일 핸들(양의 정수) 함수의 원형 설명 #include<io.h> int open (const char* filename, int oflag [, int mode]); 파일 핸들을 생성하고 파일을 연다. 호출 실패의 경우: -1 반환
2.1 Open( )- 접근모드(oflag) <fcntl.h>파일에 정의 oflag 값 의미 O_APPEND 0x0001 쓰기용으로 파일을 열어, 파일의 끝을 현재위치로 설정한다. O_CREAT 0x0002 쓰기 용으로 파일을 생성한다. 파일이 이미 존재하면 효과가 없다. O_EXCEL 0x0004 O_CREAT와 함께 사용되어 파일이 이미 존재할 경우 오류값을 반환 O_RDONLY 0x0100 읽기 전용으로 파일을 연다. O_RDWR 0x0200 읽고 쓰기용으로 파일을 연다. O_TRUNC 0x0400 파일을 열고 내용을 삭제하여 파일의 길이를 0으로 만든다. O_WRONLY 0x0800 쓰기 전용으로 파일을 연다. O_BINARY 0x4000 이진 모드로 파일을 연다. O_TEXT 0x8000 텍스트 모드로 파일을 연다.
2.1 Open( )- 파일모드(mode) 대부분의 경우, 이 mode 표기는 생략 creat ( ) 함수 <fcntl.h>파일에 정의 mode 의미 S_IWRITE 쓰기 허용 S_IREAD 읽기 허용 S_IREAD | S_IWRITE 읽기와 쓰기 허용 대부분의 경우, 이 mode 표기는 생략 O_CREAT을 사용할 경우 새로운 파일에 대한 접근 허가를 명시할 때 사용 creat ( ) 함수 새 파일 생성시 open( ) 대신 creat( )를 사용. 형식: int creat (char *filename, int mode); mode는 위 open( ) 함수와 동일 실패시 -1(EOF)을 반환.
2.2 Close( ) Close( ) 함수 함수의 원형 설명 Int close (int fd); 파일을 닫는다. 호출 실패의 경우: -1 (EOF)반환
파일 fd로부터 n바이트를 읽어 buf에 저장한다 2.3 read( ) read( ) 함수 예) int i; i = read(fd, buf, 10); i에는 실제 buf로 읽어온 바이트 수가 저장된다 함수의 원형 설명 #include<io.h> int read (int fd, void * buf, int n); 파일 fd로부터 n바이트를 읽어 buf에 저장한다 EOF를 만나면: 0 (NULL) 반환 호출 실패의 경우: -1 (EOF) 반환
2.4 write( ) write( )함수 예) int i; i = write(fd, buf, 10); 함수의 원형 설명 #include<io.h> int write (int fd, const char* buf, int n); buf로부터 n바이트를 읽어와 파일에 쓴다 호출 실패의 경우: -1(EOF) 반환
P242 <지시사항> ① "Let's learn C & C++"이라는 문자열 자료를 파일 sample.dat에 수록하라. ② 파일 끝 부분에 "1234567890"를 추가(append)하라. ③ 파일 sample.dat를 읽어 화면에 출력하라.
P242 예제-헤더파일/함수선언부분
P242 예제- main( )함수
P243 예제- file_create( ) 함수 EOF
P243 예제- file_write( ) 함수 EOF
프로그램이 올바로 수행되도록 오류를 수정해보자. P243 예제- file_read( ) 함수 프로그램이 올바로 수행되도록 오류를 수정해보자. (putchar( ) 함수 이용)
int file_read(void) { int fpnt; // file pointer void *buf; int no_of_bytes; buf = malloc(15); if ((fpnt=open(“sample.txt",O_RDONLY|O_TEXT)) == -1) { perror("Error(to read)="); return 1; } while( ( no_of_bytes = read(fpnt,buf,1)) > 0) putchar(*(char *)buf); free(buf); close(fpnt); printf("\nEnd of read phase\n"); return 0;