Download presentation
Presentation is loading. Please wait.
1
Chapter 17 파일 처리
2
함수 fopen() 파일을 만들기 위해서는 함수 fopen()을 이용
함수 fopen()의 함수 원형은 다음과 같으며 헤더 파일 stdio.h 파일에 정의 함수 fopen()에서 f는 파일(file)의 f를 의미 함수 fopen()은 두 개의 문자열 전달인자를 이용, 반환 값은 포인터 값인 FILE * 반환 값의 유형인 FILE *에서 FILE은 헤더 파일 stdio.h 파일에 정의되어 있는 구조체 유형, 그러므로 반환 값의 유형 FILE *은 구조체 FILE의 포인터 유형 struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
3
파일 열기 함수 fopen()에서 첫 번째 문자열은 처리하려는 파일 이름이고, 두 번째 문자열은 파일 처리 종류(모드)
다음 소스는 파일 “basic.txt”을 여는 모듈로서, 파일에 자료를 쓰기 위해 파일을 열므로 모드 값을 “w”로 기술 함수 fopen()은 성공적으로 파일을 열면(open), FILE 포인터를 반환하므로 그 값을 변수 f에 저장 함수 fopen()은 파일을 여는데 실패하면 NULL 값을 반환 조건문 if를 위와 같이 함수 fopen()과 함께 이용하면 파일 열기에 실패할 경우 문장 "파일이 열리지 않습니다.\n"을 출력 파일 처리가 모두 끝났으면 파일 포인터 f를 인자로 함수 fclose(f)를 호출하여 반드시 파일을 닫도록 함수 fopen()의 두 번째 인자는 파일 처리 종류(모드) “r”, “w”, “a”, “r+”, “w+”, “a+”의 종류 FILE *f; char fname[] = "basic.txt"; if ((f = fopen(fname, "w")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); }; … fclose(f);
4
파일 처리 모드 파일 처리 모드 종류 의미 모드 의미 r 읽기(read) 모드로 파일을 연다. 파일이 없으면 에러가 발생한다.
w 쓰기(write) 모드로 파일을 연다. 파일이 없으면 새로 만들고, 기존의 파일이 있으면 그 이전의 내용은 없어지고 파일의 처음부터 쓴다. 이 모드로는 파일 내용을 읽을 수 없다. a 추가 쓰기(append) 모드로 파일을 연다. 파일이 없으면 새로 만들고, 기존의 파일이 있으면 그 파일의 가장 뒤부터 파일에 추가한다. r+ 읽기(read)와 쓰기(write) 모드로 파일을 연다. 파일이 없으면 에러가 발생한다. w+ 읽기와 쓰기(write) 모드로 파일을 연다. 파일이 없으면 새로 만들고, 기존의 파일이 있으면 그 이전의 내용은 없어지고 파일의 처음부터 쓴다. a+ 추가 쓰기(append) 모드로 파일을 연다. 파일이 없으면 새로 만들고, 기존의 파일이 있으면 그 파일의 가장 뒤부터 파일에 추가한다. 파일의 어느 곳이나 읽기는 가능하나 쓰기는 추가적으로만 가능하다.
5
파일에 글자 쓰기 함수 fprintf() 함수 fopen()을 이용하여 쓰기 모드로 파일을 연 다음, 원하는 자료를 파일에 써 보자. C 언어는 파일에 자료를 쓰는 함수로 fprintf()를 제공 함수 fprintf()는 함수 printf()와 유사하며, 첫 인자로 출력하려는 목적지인 파일을 지정 위 문장은 파일 f에 문자열 "이름이 %s인 학생의 성적은 %d 입니다.\n"을 쓰는 구문 위 구문으로 변수 name과 point에 저장된 문자열과 정수 값이 적절히 연결된 문자열이 파일에 기록 fprintf(f, "이름이 %s인 학생의 성적은 %d 입니다.\n", name, point);
6
예제 소스 Filebasic.c 함수 fopen(), fprintf()를 이용하여 표준입력으로 받은 이름과 점수를 파일 “basic.txt”에 출력하는 프로그램 파일이 쓰기 모드로 열리지 않으면 함수 exit()를 이용하여 프로그램을 종료 함수 exit()를 이용하려면 헤더 파일 stdlib.h를 포함 함수 exit()는 함수를 강제로 종료하는 기능을 수행하며, 인자로 정수 값을 쓰는데, 0은 정상적인 종료를 의미하고, 0이 아닌 값은 정상적인 종료가 아님을 운영체제에게 알리는 의미로 사용 if ((f = fopen(fname, "w")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); exit(1); };
7
소스와 결과
8
함수 fprint, fscanf int fprintf(FILE *, const char *, ...);
파일에 자료를 쓰거나 읽기 위하여 함수 fprintf()와 fscanf()를 이용 이 함수를 이용하기 위해서는 헤더 파일 stdio.h 파일을 포함 함수 fprintf()와 fscanf()의 함수 원형 위 함수의 첫 번째 인자는 입출력에 이용될 파일이고, 두 번째 인자는 입출력되는 문자열이며, 다음 인자들은 입출력될 변수 목록 함수 원형에서 기호 …은 여러 인자가 계속됨을 의미 함수 fprintf()와 fscanf()를 표준 입출력에도 이용 가능 즉 함수 fprintf()와 fscanf()의 첫 번째 인자에 각각 stdin 또는 stdout를 이용하면 표준 입력, 표준 출력으로 이용이 가능 기호 상수 stdin, stdout은 stderr과 함께 헤더 파일 stdio.h에 정의되어 있는 값으로 각각 표준입력, 표준출력, 표준에러를 의미 int fprintf(FILE *, const char *, ...); int fscanf(FILE *, const char *, ...); 표준 파일 키워드 장치(device) 표준입력 stdin 키보드 표준출력 stdout 모니터 화면 표준에러 stderr #define stdin (&_iob[0]) #define stdout (&_iob[1]) #define stderr (&_iob[2])
9
예제 소스 파일 내용 쓰기, 읽기를 처리하는 프로그램 if ((f = fopen(fname, "w")) == NULL) {
쓰기 모드로 파일을 열어 표준입력으로 받은 이름과 중간 기말점수를 파일에 기록하고 파일을 닫은 후, 다시 읽기 모드로 그 파일을 열어 기록된 내용을 파일에서 읽어와 표준출력으로 출력하는 프로그램 쓰기 모드로 파일을 열어 표준 입력으로 이름, 중간점수, 기말점수를 받는 모듈 표준입력의 이름을 빈칸으로 구분하므로 빈칸이 없는 이름을 입력해야 함 if ((f = fopen(fname, "w")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); exit(1); }; printf("이름과 성적(중간, 기말)을 입력하세요.\n" ); scanf("%s%d%d", name, &point1, &point2);
10
구현 다음은 표준 입력으로 읽어들인 이름, 중간점수, 기말점수를 함수 fprintf()를 이용하여 파일 f에 출력하는 모듈
변수 cnt는 이름 앞에 번호를 붙이려는 목적으로 이용 다음은 위에서 자료를 쓴 파일의 내용을 다시 읽으려는 소스 파일을 읽기 모드로 열므로 모드 인자는 “r”로 지정 //파일 "grade.txt"에 쓰기 fprintf(f, "%d %s %d %d\n", ++cnt, name, point1, point2); fclose(f); if ((f = fopen(fname, "r")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); exit(1); }; //파일 "grade.txt"에서 읽기 fscanf(f, "%d %s %d %d\n", &cnt, name, &point1, &point2);
11
구현 위에서 함수 fscanf()를 이용하여 파일에서 적당한 내용을 읽은 후, 다시 함수 fprintf()를 이용하여 표준출력으로 출력 파일에서 함수 fscanf()를 이용하려면 파일의 내부 자료의 저장 형태를 알아야 정확히 읽을 수 있음 출력은 먼저 머리 부분으로 제목을 출력하고 다음에 내용을 출력 함수 fprintf()는 첫 인자를 stdout으로 지정하여 표준출력으로 이용 다음과 같이 함수 printf()를 이용도 가능 //표준출력에 쓰기 fprintf(stdout, "\n%6s%18s%8s%8s\n", "번호", "이름", "중간", "기말"); fprintf(stdout, "%6d%18s%8d%8d\n", cnt, name, point1, point2); fclose(f); printf("%6d%18s%8d%8d\n", cnt, name, point1, point2);
12
예제 소스 Filewrite.c 파일 내용 쓰기, 읽기를 처리하는 프로그램
프로그램 실행이 성공적으로 종료되면 파일 grade.txt 파일이 생성
13
함수 fgets()와 fputs() 함수 fgets()와 fputs() 함수 fgets() 인자 함수 fputs() 인자
이 함수도 헤더파일 stdio.h 파일에 다음과 같은 함수원형으로 정의 함수 fgets()는 문자열을 개행문자(\n)까지 읽어 개행문자도 함께 입력 문자열에 저장 마찬가지로 함수 fputs()는 문자열을 그대로 출력 함수 fgets() 인자 첫 번째 인자는 문자열이 저장될 문자 포인터이고, 두 번째 인자는 입력할 문자의 최대 수이며, 세 번째 인자는 입력 문자열이 저장될 파일 함수 fputs() 인자 첫 번째 인자는 출력될 문자열이 저장된 문자 포인터이고, 두 번째 인자는 문자열이 출력되는 파일 char * fgets(char *, int, FILE *); int fputs(char *, FILE *);
14
함수 fgetc()와 fputc() 문자 하나를 파일에 입출력하는 함수로 fgetc()와 fputc()를 제공
이 함수의 원형은 헤더파일 stdio.h에 정의 이 함수들은 문자 하나의 입출력의 대상인 파일 포인터를 인자로 이용 이 함수와 같은 함수로 getc()와 putc()도 이용 가능 문자의 표준 입출력에 이용되는 getchar()와 putchar()는 다음과 같이 함수 getc()와 putc()를 이용한 매크로 함수 fgetc()와 fputc()는 getc()와 putc()와 그 기능은 동일하며, fgetc()와 fputc()는 함수이고, getc()와 putc()는 매크로 int fgetc(FILE *); int fputc(int, FILE *); int getc(FILE *); int putc(int, FILE *); #define getchar() getc(stdin) #define putchar(_c) putc((_c),stdout)
15
함수 feof()와 ferror() 함수 feof() 함수 ferror()
이 함수는 헤더파일 stdio.h에 다음 함수 원형으로 정의 파일의 위치가 파일의 마지막(end of file)인지를 검사하여, 파일의 마지막이면 0이 아닌 값을, 파일의 마지막이 아니면 0을 반환 그러므로 표준입력에서 계속적으로 입력을 받는 구문으로 다음을 이용 가능 함수 ferror() 파일 처리에서 오류가 발생했는지 검사하는 함수 함수의 원형은 헤더파일 stdio.h에 정의 이전 파일 처리에서 오류가 발생하면 0이 아닌 값을 발생하고, 오류가 발생하지 않으면 0을 반환 int feof(FILE *); while (!feof(stdin)) { … } int ferror(FILE *);
16
예제 소스 목적 함수 fgets()와 fputs()를 이용하여 표준입력으로 여러 줄을 입력 받아 여러 줄을 지정된 파일에 출력하는 프로그램을 작성 구현 주요 변수 표준입력으로 입력된 한 줄의 자료를 함수 fgets()를 이용하여 입력 받고, 바로 이 한 줄의 문자열을 함수 fputs()를 이용하여 파일 f에 저장하는 모듈 char fname[] = "grade.txt"; char names[80]; FILE *f; printf("이름과 성적(중간, 기말)을 입력하세요.\n" ); fgets(names, 80, stdin); while (!feof(stdin)) { //파일 "grade.txt"에 쓰기 fprintf(f, "%d ", ++cnt); fputs(names, f); } fclose(f);
17
구현 파일의 내용을 파일의 끝까지 한 줄 한 줄 출력하는 모듈
파일의 내용을 출력하기 전에 함수 printhead()를 호출하여 제목을 출력 파일 포인터 f를 이용하여 함수 feof()을 이용하며, 파일 내용의 형태를 알고 있으므로 함수 fscanf()를 이용하여 각 자료형으로 자료를 입력 입력 받은 자료는 함수 fprintf()를 이용하여 적절한 형태로 출력 파일을 함수 fopen()을 이용하여 열었으면, 잊지 말고 함수 fclose()를 이용하여 닫는 프로그래밍 습관을 기르도록 printhead(); while (!feof(f)) { //파일 "grade.txt"에서 읽기 fscanf(f, "%d %s %d %d\n", &cnt, names, &point1, &point2); //표준출력에 쓰기 fprintf(stdout, "%6d%18s%8d%8d\n", cnt, names, point1, point2); }
18
소스와 결과
19
예제 소스 목적 조건 도스 명령어 type와 같은 프로그램을 만들어보자.
이 프로그램은 프로그램 이름을 list로 하여 “list filename”을 입력하면 파일 filename의 내용을 표준출력으로 출력하는 프로그램 조건 명령어 줄 인자를 활용, 두 번째 인자가 파일이름에 해당 이 파일이름에 해당하는 인자를 기술하지 않으면 간단한 사용법을 알리고 프로그램은 종료 파일 내용의 출력은 한 줄마다 맨 앞에 줄 번호를 출력 첫 실행에서는 파일이름을 입력하지 않았고, 두 번째에는 이 프로그램의 소스를 파일이름으로 기술
20
구현 명령어 줄 인자가 2개가 아니면 사용법을 출력하고 종료
명령어 줄 인자에서 두 번째 인자인 argv[1]을 가지고 파일 열기 파일을 여는데 문제가 있으면 프로그램을 종료 if (argc != 2) { printf("사용법 : list filename\n" ); exit(1); }; if ((f = fopen(argv[1], "r")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); exit(1); };
21
구현 처음 줄에 줄 번호를 출력하고, fgetc(f)를 이용하여 파일 f에 문자를 하나 하나 읽어, 그 읽은 문자 ch를 putchar(ch)를 이용하여 표준출력으로 출력 아래 소스의 putchar(ch)는 putc(ch, stdout)로도 가능 출력된 문자가 개행문자이면 새로운 줄이 시작되므로 줄 번호를 출력 이러한 정수를 출력하는 부분에서는 함수 printf()를 이용 프로그램의 마지막에는 잊지 말고 파일을 닫음 printf("%4d: ", ++cnt); while ((ch = fgetc(f)) != EOF) { putchar(ch); if (ch == '\n') { }; } printf("\n"); fclose(f);
22
예제 소스 List.c 이 프로그램은 프로그램 이름을 list로 하여 “list filename”을 입력하면 파일 filename의 내용을 표준출력으로 출력하는 프로그램
23
텍스트 파일과 이진 파일 텍스트 파일 이진 파일 함수 fprintf()와 fscanf()는 자료의 입출력을 텍스트 모드로 처리
텍스트 파일은 텍스트 편집기(에디터)로 그 내용을 알 수 있으며, 텍스트 파일의 내용은 모두 지정된 문자 코드(일반적으로 아스키 코드) 값을 갖고 있어, 그 내용을 확인할 수 있을 뿐만 아니라 인쇄가 가능 함수 fprintf()를 이용하여 정수형 변수 cnt에 저장된 값을 파일 f에 출력하는 과정 함수 fprintf()를 이용하여 실제 정수 int형 변수 cnt를 출력하면, 실제적으로 파일에 저장되는 자료는 정수 값인 10에 해당하는 각 문자의 아스키 값을 저장 그러므로 함수 fprintf()를 이용하여 출력하면, 파일 f에는 정수 값 10에 해당하는 각각의 문자 ‘1’과 ‘0’의 아스키 코드 값이 저장 이진 파일 이러한 텍스트 파일과는 다르게 이진(binary) 파일은 C 언어의 자료형을 모두 유지하면서 바이트 단위로 저장하는 파일 이진 파일의 대표적인 예가 실행파일, 이러한 이진 파일은 일반 편집기로는 그 내용 확인 불가능
24
함수 fwrite와 fread 이진 파일 처리 인자와 반환 값 void *
이와는 다르게 이진(binary) 모드로 입출력을 처리하려면 함수 fwrite()와 fread()를 이용 함수 fwrite()는 헤더파일 stdio.h에 다음과 같은 함수원형으로 정의 이진 파일에 저장되어 있는 자료형을 입력하는 함수 fread() 각각의 인자는 출력 함수 fwrite()와 동일 인자와 반환 값 인자 첫 번째 인자는 출력될 자료의 주소 값이며, 두 번째 인자는 출력될 자료의 바이트 크기이고, 세 번째 인자는 출력될 단위 자료의 묶음 개수이고, 마지막 인자는 출력될 파일 포인터 반환값 값은 파일에 출력된 단위 자료형의 개수 void * 위에서 첫 번째 인자의 자료형이 void *로 모든 자료형의 포인터를 대신할 수 있는 포인터 변수 size_t fwrite(const void *, size_t, size_t, FILE *); size_t fread(void *, size_t, size_t, FILE *);
25
이진 파일 입출력 이해 함수 fwrite()를 이용하여 정수형 변수 cnt 값을 파일 f에 출력하는 과정
이진 파일 입출력 이해 함수 fwrite()를 이용하여 정수형 변수 cnt 값을 파일 f에 출력하는 과정 함수 fwrite()는 바이트 단위로 원하는 블록을 파일에 출력하기 위한 함수 함수 fwrite()에 의하여 출력된 자료는 함수 fread()를 이용하여 입력해야 그 자료유형 유지가 가능
26
예제 소스 Scorefile.c 학생의 성적정보를 다음과 같이 구조체로 표현하고, 표준입력으로 여러 명의 자료를 입력 받아 구조체 자료형에 저장하여 파일 “score.bin”에 저장하는 프로그램을 작성 구조체 personscore는 번호, 이름, 중간, 기말, 퀴즈 점수를 멤버로 가지며 이에 대한 정의는 헤더파일 score.h로
27
구현 이 구조체 자료형으로 한 학생의 정보를 저장하기 위하여, 표준입력으로 번호를 제외한 이름, 중간, 기말, 퀴즈 점수를 입력 표준입력은 사람마다 한 행씩 받으며, 입력된 학생 수로 학생 번호를 입력 표준입력은 한 행마다 fgets()를 이용하여 하나의 문자열로 받고, 이 입력된 문자열에서 각 구조체의 멤버 자료를 추출 문자열에서 자료를 추출하기 위하여 함수 sscanf()를 이용 함수 sscanf()는 문자열로부터 자료를 입력 받는 함수 printf("이름과 성적(중간, 기말, 퀴즈)을 입력하세요.\n" ); fgets(line, 80, stdin); while (!feof(stdin)) { //표준입력의 한줄을 구조체의 멤버 별로 자료를 입력 sscanf(line, "%s %d %d %d", score.name, &score.mid, &score.final, &score.quiz); score.number = ++cnt; fwrite(&score, sizeof(pscore), 1, f); }
29
예제 소스 Readscorefile.c 이전에 만들었던 이진 파일 score.bin 파일의 내용을 읽어 표준 출력으로 출력하는 프로그램 이전의 헤더파일 score.h 파일은 그대로 이용하고, 출력 형태는 다음과 같은 결과
30
구현 이진 파일을 읽기 위하여 읽기 모드 “r”로 파일 열기
이진 자료를 읽기 위하여 함수 fread()를 이용 함수 fread()에서 첫 인자는 읽은 자료를 저장할 구조체 변수 score의 주소 값을 기술 함수 feof()을 이용하여 파일의 마지막까지 구조체 자료를 읽어 적당한 출력 형태가 되도록 함수 fprintf()를 이용하여 출력 if ((f = fopen(fname, "r")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); exit(1); }; fread(&score, sizeof(pscore), 1, f); while (!feof(f)) { //표준출력에 쓰기 fprintf(stdout, "%6d%18s%8d%8d%8d\n", score.number, score.name, score.mid, score.final, score.quiz); }
32
파일 내부 위치 파일 위치 포인터 순차적, 임의 접근
파일을 열면 항상 파일 위치 포인터(file pointer)라는 것이 파일의 한 장소를 가리킴 여기에서의 파일 위치 포인터는 변수에서의 파일 포인터와는 다른 것으로 파일 내부를 바이트 단위로 파일 내부 위치를 나타내는 값 파일 포인터가 100L이라면 파일의 처음에서부터 100바이트 떨어진 위치에 현재 파일 포인터가 위치 파일 포인터 값은 일반적으로 자료형 long으로 취급하므로 상수를 기술할 때 100L처럼 수 뒤에 L을 기술 가능 파일 포인터는 파일 내부에서 자료를 읽거나 쓰는 만큼 파일의 현재 위치에서 뒤로 이동 순차적, 임의 접근 파일에서 원하는 장소로 자유롭게 이동하는 것을 임의 접근(Random Access) 파일의 임의 접근을 처리하기 위해서는 파일 포인터를 자유 자재로 이동하는 함수 fseek()이 필요
33
함수 fseek() fseek() offset 함수 fseek()는 함수 원형이 헤더파일 stdio.h 파일에 정의
함수 fseek()는 파일 fptr에서 기준점 mode에서 offset만큼 떨어진 곳으로 파일 포인터를 위치하는 함수 offset 함수 fseek()에서 두 번째 인자는 long 유형으로 기준점으로부터 떨어진 값을 말하며 흔히 오프셋(offset)이라 함 함수 fseek()에서 세 번째 인자는 정수형 기호 상수로 다음 세 가지 중의 하나를 이용 int fseek(FILE *fptr, long offset, int mode) 기호 값 의미 SEEK_SET 파일의 시작 위치 SEEK_CUR 1 파일의 현재 위치 SEEK_END 2 파일의 끝 위치
34
기준 세가지 함수 fseek(f, 100L, SEEK_SET)의 호출은 파일 포인터를 파일의 처음 위치에서 100바이트 떨어진 위치로 이동시킨다. 함수 fseek(f, 100L, SEEK_CUR)의 호출은 파일 포인터를 파일의 현재 위치에서 100바이트 떨어진 위치로 이동시킨다. 함수 fseek(f, -100L, SEEK_END)의 호출은 파일 포인터를 파일 끝 위치에서 앞으로 100바이트 떨어진 위치로 이동시킨다.
35
int fseek(FILE *, long, int)
파일 관련 여러 함수 함수 fseek()에서 두 번째 인자는 세 번째 인자인 기준점으로부터 떨어진 값을 말하며, 양수는 뒤, 음수는 앞으로 방향을 지시 파일 포인터와 관련된 함수로서 다음 세 가지 함수를 이용 함수 ftell()은 인자인 파일의 파일 포인터를 반환하며 함수 rewind()는 파일 포인터를 무조건 제일 앞으로 이동 함수 기능 int fseek(FILE *, long, int) 파일 포인터를 세 기준점으로부터 오프셋만큼 이동하는 함수 long ftell(FILE *) 파일의 현재 파일 포인터를 반환하는 함수 void rewind(FILE *) 파일의 현재 포인터를 0 위치(파일의 시작점)로 이동하는 함수
36
예제 소스 Appendscore.c 바로 이전에 작성한 readscorefile.c 프로그램을 발전시켜 더 많은 학생의 성적정보를 추가하는 프로그램을 작성 프로그램이 실행되면 제일 먼저 파일 score.bin 파일에 있는 학생 정보를 모두 읽어와 출력 파일에 있는 마지막 학생 정보로부터 마지막 학생 번호를 알아냄 이 번호에 1씩 증가시키면서 다음에 추가될 학생의 번호로 이용 추가되는 자료는 이전의 학생정보를 입력하는 방식과 동일하게 한 줄에 한 명의 학생 정보를 입력
37
구현 추가될 학생 정보는 위와 같이 학생마다 한 행씩 자료를 받아서 파일 score.bin 파일에 저장
키 ctrl + z를 누르면 입력이 종료되고, 다시 파일 score.bin에서 모든 자료를 읽어 모든 정보를 출력 프로그램에서 제일 먼저 자료를 추가할 score.bin 파일을 모드 “a+”로 연다. 파일을 “a+”로 여는 이유는 학생 정보를 추가도 하고, 다시 읽기도 하기 위함 이 프로그램에서는 파일 score.bin을 한번 열고, 프로그램 종료 시에 닫도록 파일에 저장된 정보를 출력하기 위해 함수 printscore()를 만들어 호출한다. if ((f = fopen(fname, "a+")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); exit(1); }; printscore(f);
38
구현 모든 정보를 출력하면 파일 포인터는 파일 끝에 위치
학생 정보의 마지막 자료를 구조체 변수 score에 저장하기 위하여 함수 fseek()을 다음과 같이 이용 다음에는 학생정보를 추가하는 함수 appendscore()를 호출하고 이어서 다시 모든 자료를 출력하는 함수 printscore()를 호출하고 파일을 닫음 offset = (long) sizeof(pscore); fseek(f, -offset, SEEK_CUR); fread(&score, sizeof(pscore), 1, f); //제일 마지막 자료의 번호를 찾기위하여 cnt = score.number; printf("\n제일 마지막 번호가 %d번 입니다. \n\n", cnt); fseek(f, 0L, SEEK_END); appendscore(f, cnt); printscore(f); fclose(f);
39
구현 함수 printscore()에서는 읽을 파일을 인자로 처리하고,
파일을 처음부터 읽어야 하므로 함수 rewind()를 호출하여 파일 포인터를 0으로 지정 void printscore(FILE *f) { pscore score; rewind(f); printhead(); fread(&score, sizeof(pscore), 1, f); while (!feof(f)) { … }
41
입출력 함수 여러 입출력 함수
42
파일 삭제, 이름 바꾸기 함수 remove() 함수 rename() 지정된 특정한 파일을 삭제하고
함수 remove()는 remove(“sample.txt”)와 같이 문자열로 지정된 파일을 삭제 함수 rename() 지정된 파일의 이름을 새로운 이름으로 바꾸는 역할을 수행 함수 rename()은 rename(“oldname.txt”, “newname.txt”)과 같이 앞의 파일이름을 뒤 파일이름으로 바꾸는 역할 함수 remove()와 rename()도 헤더 파일 stdio.h에 그 함수 원형이 정의 기능 함수 원형 파일 삭제 int remove(const char *) 파일 이름 바꾸기 int rename(const char *, const char *)
43
예제 소스 filepro.c 이 프로그램은 옵션과 파일이름을 명령어 줄 인자로 처리하는 프로그램으로 옵션에 따라 다음과 같은 기능을 수행하도록 프로그램 첫 번째 옵션은 다음과 같이 –c로 인자인 파일이름으로 파일을 생성하는 기능을 수행 이 파일 filename은 기존에 없으면 새로 생성하고, 만일 있으면 있는 파일을 이용 파일에는 이 명령어를 수행한 횟수를 함수 getw()를 이용하여 파일에 저장하는 기능을 수행 >fileproc –c filename 두 번째 옵션은 –d를 이용하며 지정된 파일 filename을 삭제한다. >fileproc –d filename 세 번째 옵션은 –n를 이용하며 지정된 파일 filename1을 새로운 이름 filename2으로 수정 >fileproc –n filename1 filename2
44
결과 다음은 이 프로그램을 명령어 프롬프트에서 실행한 결과
이 프로그램에서 옵션 –d는 함수 remove()를 이용하여 삭제하고, 옵션 –n은 함수 rename()을 이용하여 파일이름을 수정
45
구현 위 프로그램에서 옵션 –c는 지정된 파일에 옵션 –c를 실행한 횟수를 출력
이를 위하여 실행 시에 파일에서 이전에 저장한 정수를 getw() 함수로 읽어와 1을 더하여 함수 putw()를 이용하여 다시 그 파일에 저장 파일이 없는 경우에는 새로이 파일을 만들어서 1을 저장 명령어 줄 인자에서 옵션에 저장된 문자열은 argv[1] 다음 소스와 같이 옵션에 따라 변수 mode에 적당한 값을 저장 if (strcmp(argv[1], "-c") == 0) { mode = 1; } else if (strcmp(argv[1], "-d") == 0) { mode = 2; } else if (strcmp(argv[1], "-n") == 0) { mode = 3; };
46
구현 다음은 옵션이 –c인 경우 이전에 파일이 있으면, 모드 “r+”로 파일을 열고, 이전에 파일이 없으면 모드 “w+”로 파일을 여는 모듈 switch (mode) { case 1: if ((f = fopen(argv[2], "r+")) == NULL) { if ((f = fopen(argv[2], "w+")) == NULL) { printf( "파일이 열리지 않습니다.\n" ); exit(1); } }; …
47
구현 다음 소스는 이전에 사용한 파일은 파일 크기가 0이 아니므로, 그 파일에서 맨 앞의 정수 하나를 함수 getw()를 이용하여 읽어오는 모듈 다음은 변수 cnt에는 이전의 횟수가 저장되어 있으므로 1을 더한 ++cnt를 파일의 맨 앞 부분에 함수 putw()를 이용하여 다시 출력 fseek(f, 0L, SEEK_END); if (ftell(f) != 0) { fseek(f, 0L, SEEK_SET); cnt = getw(f); } fseek(f, 0L, SEEK_SET); putw(++cnt, f); printf("-c 옵션을 파일 %s에 %d번 사용했습니다.\n", argv[2], cnt); fclose(f); break;
48
구현 다음은 옵션이 –d인 경우 다음은 옵션이 -n인 경우 remove(argv[2]) 함수를 호출하여 파일을 삭제
rename(argv[2], argv[3]) 함수를 호출하여 파일이름을 수정 case 2: remove(argv[2]); break; case 3: if (argc != 4) { printf("사용법 : -[c,d,n] filename\n" ); exit(1); }; rename(argv[2], argv[3]); break;
49
예제 소스
50
프로그램 연습 프로그램 목적 이 장에서 배운 함수들을 이용하여 score.bin 파일에서 학생 번호를 이용하여 학생 정보를 검색하는 프로그램을 작성 헤더 파일 score.h를 그대로 이용하고, 함수 printscore()와 printhead()를 그대로 이용하며, 함수 searchscore()를 만들어 검색에 이용 프로그램은 다음 조건을 만족하도록 제일 먼저 score.bin 파일에 있는 모든 정보를 출력하자. 가장 큰 학생 번호를 출력하여 잘못된 학생번호를 입력하지 않도록 한다. 검색할 학생번호를 입력 받는다. 검색 함수 searchscore(FILE *f, int cnt)는 두 개의 인자를 가지며, 두 번째 인자가 검색할 학생 번호이다. 검색 결과를 출력한다.
51
결과 실행 결과
52
구현 구조체가 여러 개 저장되어 있는 파일에서, 파일의 전체 크기를 구조체 하나의 크기로 나누면 총 구조체의 수를 알 수 있음
파일의 전체 크기는 파일 포인터를 파일 가장 끝으로 보내고 함수 ftell()을 이용하면 알 수 있음 fseek(f, 0L, SEEK_END); max = ftell(f) / sizeof(pscore); printf("\n가장 큰 학생 번호는 %d번 입니다. >>\n", max); printf("찾을 학생 번호를 입력하세요. >> "); scanf("%d", &cnt); if (1 <= cnt && cnt <= max) searchscore(f, cnt); else printf("번호를 잘못 입력했습니다.\n"); fclose(f);
53
구현 파일에서 cnt 번째의 구조체를 읽어야 하므로 파일 포인터를 파일의 처음(SEEK_SET)에서부터 sizeof(pscore) * (cnt-1) 바이트만큼 이동 이를 함수 fseek()을 이용하여 이동하고, 함수 fread()로 구조체 하나를 이진 자료로 읽어 들임 void searchscore(FILE *f, int cnt) { pscore score; long offset = (long) (sizeof(pscore) * (cnt-1)); fseek(f, offset, SEEK_SET); fread(&score, sizeof(pscore), 1, f); printf("\n찾은 학생 정보는 >>\n\n"); fprintf(stdout, "%6s%18s%8s%8s%8s\n", "번호", "이름", "중간", "기말", "퀴즈"); fprintf(stdout, "%6d%18s%8d%8d%8d\n", score.number, score.name, score.mid, score.final, score.quiz); }
54
소스와 결과
Similar presentations