Chapter 4. 보조자료 - 파일 입출력 파일의 기본 개념과 특징을 이해한다. 파일 처리 과정을 이해한다. 형식을 지정한 파일 입출력 fscanf/fprintf를 배운다. 문자 단위 입출력 fgetc/fputc를 배운다. 문자열 단위 입출력 fgets/fputs를 배운다. 이진 파일 입출력 fread/fwrite를 배운다. 임의 접근을 통한 파일 입출력을 위한 fseek, rewind, ftell을 배운다. 제목
개 요 표준 입출력과 파일 입출력 표준 입출력의 문제점 키보드 입력: 실행 마다 똑같은 데이터를 입력 모니터 출력: 실행 결과 창 스크롤링, 결과 창을 닫으면 출력 내용이 사라짐 해결: 데이터를 저장한 파일로부터 입력을 받고 결과를 파일로 저장하기 20 age 변수 C 프로그램 키보드 (표준 입력 장치) 입력 input.txt 20 파일에서 읽기 모니터 (표준 출력 장치) 출력 output.txt 나이: 20세 파일에 쓰기
개 요 스트림(stream) 기반의 입출력 stream - 연속된 데이터 바이트의 흐름 표준 입출력 함수 : printf 함수, scanf 함수 키보드나 모니터를 포함하여 모든 주변장치들을 파일처럼 취급 모든 입력과 출력은 공통된 접속(인터페이스)를 사용하여 파일로 취급되는 주변장치들과 연 결 그 밖의 표준 입출력 함수
fprintf(fp2, “나이:%d세”, age) 개 요 표준 입출력장치를 통한 입출력과 파일을 통한 입출력 예 C 프로그램 모니터 (표준 출력 장치) 키보드 (표준 입력 장치) age 변수 입력 출력 20 나이: 20세 scanf(“%d”, &age) printf(“나이:%d세”, age) C 프로그램 fp1에 연결된 파일 fp2에 연결된 파일 age 변수 20 파일에서 읽기 파일에 쓰기 나이: 20세 20 fscanf(fp1, “%d”, &age) fprintf(fp2, “나이:%d세”, age)
파일이란? 파일(file) 보조기억장치에 저장된 물리적인 데이터 집합체 저장된 내용의 용도에 따라 프로그램 파일과 데이터 파일로 구분 한글 프로그램 포토샵 프로그램 실험 관리 프로그램 응용 관리 프로그램 Text Mode Binary Mode 과제.hwp 풍경.jpg 분석결과.txt TEST.exe
파일 처리 과정 파일 입출력 네 단계 fp 파일 입력 프로그램 키보드 입력 프로그램 FILE * fp; : fp = fopen(“data.txt", “r"); fscanf(fp, "%d", &age); fscanf(fp, "%d", &height); fclose(fp1); ① 파일 포인터 선언 : scanf("%d", &age); scanf("%d", &height); ② 파일 열기 ③ 파일 읽기 (파일에서 읽은 데이터를 변수에 저장) ④ 파일 닫기 프로그램 변수 프로그램 변수 fp에 연결된 data.txt 파일 키보드 age age fp 20 20 170 20 20 170 height height 170 170
파일 포인터 선언하기 파일 포인터 선언과 파일 열기 파일 포인터가 할당되어 있는 파일에 대해서만 읽기/쓰기가 가능 → 파일 열기를 통해 파일 포인터를 파일에 연결해야 함 형식: “파일명” 파일을 열기 FILE *파일포인터명; 파일포인터명 = fopen(“파일명”, “모드”); → “파일명”의 파일을 “모드”에 맞게 열며 파일포인터가 열린 파일을 가리키게 된다. “r”: 읽기 전용, “r+” 읽기/쓰기용 →“파일명”의 파일이 없다면 에러로 NULL 반환 “w”: 쓰기 전용, “w+” 읽기/쓰기용 → 파일 내용을 모두 지움, “파일명”의 파일이 없다면 새로 만듬 “a”: 추가 전용, “a+” 읽기/쓰기 추가용 → 파일의 끝에 데이터를 추가, “파일명”파일이 없다면 새로 만듬 “b”: Binary mode에서 입출력
“data.txt” 파일의 정보를 가진 FILE 구조체 파일 열기 : fopen 함수 파일 포인터 선언과 파일 열기 예 파일의 위치 특별히 위치를 지정하지 않으면 프로젝트 폴더에 파일이 생성되며 읽기용 파일이라면 미리 프로젝트 폴더에 저장되어 있어야 함 프로젝트 폴더에 있지 않다면 “C:\\file\\age.txt”와 같이 절대경로를 명시해 야 함 // 선언과 동시에 파일 열기 FILE *fp = fopen(“data.txt”, “w”); FILE *fp; fp = fopen("data.txt", "w"); 쓰기 모드로 열린 빈 파일 data.txt 파일 fp 쓰기 모드로 열린 빈 파일 fp “data.txt”파일 “data.txt” 파일의 정보를 가진 FILE 구조체 단순화하여 fp가 “data.txt” 파일을 가리킨다고 생각하는 것이 편리
파일 열기 : fopen 함수 파일 열기 실패 처리 fopen 함수가 실패시 NULL이 반환됨 열기 에러 처리 코드의 예 지정한 이름의 파일이 존재하지 않는 경우의 에러 처리 코드 FILE *fp; fp = fopen("data.txt", "r"); if (fp == NULL) { printf("지정한 이름의 파일을 열 수 없습니다. \n"); exit(1); }
파일 입출력 함수 파일 입출력 함수
파일 닫기 : fclose 함수 파일 닫기 프로그램 종료 전에 열린 파일들을 닫아야 함 형식 예 : // 파일에 자료 쓰기 : → 닫은 파일에 연결된 파일포인터는 새로운 파일 열기에 사용 가능 형식 fclose(파일포인터명); 예 FILE *fp; fp = fopen("data.txt", "w"); : // 파일에 자료 쓰기 fclose(fp); // 파일 닫기 : fp = fopen(“result.txt", "w"); // 파일포인터 재사용 현재 파일포인터에 연결된 파일이 닫기며 파일포인터와의 연결이 해제됨
파일 닫기 : fclose 함수 ferror 함수 파일 입출력 시 발생하는 에러를 확인 리턴 값 : 스트림에 에러가 발생했으면 0을 이 아닌 값을 리턴하고, 에러가 발 생하지 않았으면 0을 리턴한다.
형식을 지정한 파일 출력 : fprintf 함수 지정한 형식에 맞추어 데이터를 파일로 출력 → printf를 사용한 모니터로의 출력과 똑 같은 내용의 결과를 얻음 형식 fprintf(파일포인터명, “변환명세 포함한 형식문자열”, 변수명); 변수 값이 “형식문자열”에 맞게 변환되여 파일포인터에 연결된 파일에 기 록됨 printf 함수 사용한 모니터 출력 결과 그대로 파일에 기록됨 상수 또는 식
형식을 지정한 파일 출력 : fprintf 함수
형식을 지정한 파일 출력 : fprintf 함수 예) FILE *fp = fopen(“data.txt”, “r”); age = 20; fprintf(fp, "나이: %d세", age); fprintf (fp, “나이: %d세“, age); 파일에 쓰기 나이: 20세 20 age 변수 C 프로그램 fp printf(“나이: %d세“, age); fprintf (stdout, “나이: %d세“, age); 모니터에 출력하기 stdout
형식을 지정한 파일 출력 : fprintf 함수 예) FILE *fp = fopen(“data.txt”, “r”); age = 20; fprintf(fp, "나이: %d세", age);
형식을 지정한 파일 출력 : fprintf 함수 파일 처리 방식과 구분 Text mode Binary mode
4 – 1 : 회원 5명의 나이 정보를 파일에 저장하기 1 #include <stdio.h> // fopen, fprintf, fclose 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 #define SIZE 5 // 회원 수 4 5 int main() 6 { 7 FILE *fp; // 파일 포인터 선언 8 char *f_name = "age.txt"; // 파일명, char f_name[20]="age.txt";도 가능 9 int age, i; 10 11 fp = fopen(f_name, "w"); // fp = fopen("age.txt", "w")도 가능 12 13 if (fp == NULL) // 파일 열기 에러 처리 14 { 15 printf(" %s 파일 열기 에러! \n", f_name); 16 exit(1); 17 } 19 printf("회원 %d명의 나이를 입력하면 파일로 저장합니다.\n", SIZE);
4 – 1 : 회원 5명의 나이 정보를 파일에 저장하기 21 for (i=0; i<SIZE; i++) // SIZE명의 나이를 키보드에서 입력받아 파일에 쓰기 22 { 23 printf("%2d번 회원의 나이는? ", i+1); 24 scanf("%d", &age); // 키보드에서 회원의 나이를 입력받기 25 26 fprintf(fp, "%d\n", age); // age의 값을 fp에 연결된 파일에 쓰기 27 } 28 29 fclose(fp); // fp에 연결된 age.txt 파일을 닫고 연결을 끊기 30 printf("회원 %d명의 나이를 %s 파일에 저장했습니다.\n", SIZE, f_name); 31 32 return 0; 33 } 20↲ 23↲ 25↲ 21↲ age.txt 파일의 내용 회원 5명의 나이를 입력하면 파일로 저장합니다. 1번 회원의 나이는? 20 2번 회원의 나이는? 23 3번 회원의 나이는? 25 4번 회원의 나이는? 21 5번 회원의 나이는? 20 회원 5명의 나이를 age.txt 파일에 저장했습니다 실행결과
Program 4 – 1 : 회원 5명의 나이 정보를 파일에 저장하기 분석 키보드로 입력받은 나이를 파일에 쓰는 과정(24, 26행)을 5번 반복하면 파일 에 5개의 나이가 저장됨 C 프로그램 fp age.txt 파일 키보드 20↲ 입력 age 변수 출력 20 scanf(“%d”, &age) fprintf(fp, “%d\n”, age)
형식을 지정한 파일 입력 : fscanf 함수 fscanf 함수 파일의 데이터를 변환명세로 지정한 형식에 맞게 읽어서 변수에 저장 → scanf의 키보드 자료 입력과 똑 같은 내용이 파일에 기록되어 있어야 함 형식 scanf(파일포인터명, “변환명세”, &변수명) 파일포인터가 가리키는 파일에서 변환명세 맞게 데이터를 읽어서 변수에 저장 읽기 실패 또는 파일의 끝에 도달했다면 EOF를 반환
형식을 지정한 파일 입력 : fscanf 함수 fscanf 함수
형식을 지정한 파일 입력 : fscanf 함수 예) fp FILE *fp = fopen("read.txt"); fscanf(fp, "%d", &age); fscanf(fp, "%d", &height); 파일에서 읽기 C 프로그램 read.txt 파일 fp fscanf(fp, “%d”, &age); 20 age 변수 20 170 170 height 변수 fscanf(fp, “%d”, &height);
4 – 2 : “age.txt” 파일의 나이 정보를 화면에 출력하기 1 #include <stdio.h> // fopen, fscanf, fclose 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 #define SIZE 5 // 회원 수 4 5 int main() 6 { 7 FILE *fp; // 파일 포인터 선언 8 char *f_name = "age.txt"; // 파일명, char f_name[20]="age.txt";도 가능 9 int age, i; 10 11 fp = fopen(f_name, "r"); // f_name 이름의 파일을 읽기용으로 열기 12 13 if (fp == NULL) // 파일 열기 에러 처리 14 { 15 printf(" %s 파일을 열 수 없습니다. \n", f_name); 16 exit(1); 17 }
4 – 2 : “age.txt” 파일의 나이 정보를 화면에 출력하기 19 for (i=0; i<SIZE; i++) // 파일의 나이를 SIZE개 읽어 모니터에 출력하기 20 { 21 // fp에 연결된 파일에서 정수 한 개를 읽어 age에 저장하기 22 fscanf(fp, "%d", &age); 23 24 // age에 저장된 나이를 모니터에 출력하기 25 printf("%2d번 회원의 나이는 %d세 \n", i+1, age); 26 } 27 28 fclose(fp); // fp에 연결된 age.txt 파일을 닫고 연결을 끊기 30 return 0; 31 } 20↲ 23↲ 25↲ 21↲ age.txt 파일의 내용 1번 회원의 나이는 20세 2번 회원의 나이는 23세 3번 회원의 나이는 25세 4번 회원의 나이는 21세 5번 회원의 나이는 20세 실행결과
fprintf와 fscanf의 주의점 주의 여러 값을 한꺼번에 파일에 쓸 때 공백 문자(빈칸, 탭키, 엔터키) 넣기 age = 20; height = 170; fprint(fp, "%d%d\n", age, height); 공백 문자가 없다. 20170 이후 이 파일을 읽기용으로 연 후 fscanf(fp, “%d%d“, &age, &height);를 사용한다면? 20170이 age에 저장되고 height에는 데이터가 입력되지 않음 → 20과 170 사이에 공백 문자를 넣어둬야 한다.
fprintf와 fscanf의 주의점 fscanf(fp, "키:%5d ", &height); 주의 일반 문자 사용 불가 필드폭은 생략 변환명세 끝에 빈칸이나 ‘\n’ 넣지 말기 fscanf(fp, "키:%5d ", &height); 일반 문자는 불가능 필드폭을 사용 않는 것이 더 안전 빈칸 또는 \n을 넣으면 데이터를 한 개 더 읽게 됨
파일의 추가 추가 모드의 필요성 쓰기 모드는 기존의 파일 내용을 모두 지우고 새로 쓰기를 함 → 이전 실행 결과와 함께 새 실행 결과도 같은 파일에 저장하고 싶을 때는 추 가 모드로 열어야 함 [프로그램] [프로그램 4-2]에서 만든 age.txt 파일에 n명의 나이를 추가하는 프로그램 파일 작성 두 가지 방법 프로그램을 통한 실행 결과로 만들기 프로그램에 사용할 데이터를 미리 일반 편집기를 이용하여 파일로 만들기 → 목적에 따라 두 방법 중 선태 가능 → [프로그램]을 실행하지 않고 age.txt 파일을 메모장 또는 비주얼 스튜디오에 서 직접 만든 후 [프로그램 4-3]을 실행해도 됨
4 – 3 : age.txt 파일에 n명의 나이 추가하기 1 #include <stdio.h> // fopen, fprintf, fclose 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 4 int main() 5 { 6 FILE *fp; // 파일 포인터 선언 7 char *f_name = "age.txt"; // 파일명, char f_name[20]="age.txt";도 가능 8 int age, i, n; 9 10 fp = fopen(f_name, "a"); // f_name 이름의 파일을 추가용으로 열기 11 12 if (fp == NULL) // 파일 열기 에러 처리 13 { 14 printf(" %s 파일 열기 에러! \n", f_name); exit(1); 15 } 추가 모드
4 – 3 : age.txt 파일에 n명의 나이 추가하기 17 printf("회원의 나이를 입력하면 %s 파일에 추가합니다.\n", f_name); 18 printf("추가할 회원의 수는? "); 19 scanf("%d", &n); // 파일에 추가할 회원 나이 개수를 입력 20 21 // n명의 나이를 키보드에서 입력받아 파일에 추가하기 22 for (i=0; i<n; i++) 23 { 24 printf("회원의 나이는? "); 25 scanf("%d", &age); // 키보드에서 회원의 나이를 입력 26 27 fprintf(fp, "%d\n", age); // age에 저장된 나이를 fp에 연결된 파일에 쓰기 28 } 29 fclose(fp); 30 printf("회원 %d명의 나이를 %s 파일에 추가했습니다.\n", n, f_name); 31 32 return 0; 33 }
프로그램 4 – 3 : age.txt 파일에 n명의 나이 추가하기 분석 20↲ 23↲ 25↲ 21↲ 실행 전 age.txt 파일의 내용 20 23 25 21 29 31 27 실행 후 age.txt 파일의 내용 회원의 나이를 입력하면 age.txt 파일에 추가합니다. 추가할 회원의 수는? 3 회원의 나이는? 29 회원의 나이는? 31 회원의 나이는? 27 회원 3명의 나이를 age.txt 파일에 추가했습니다. 실행결과
학생 평점 파일을 읽어 평점 순위 파일 만들기 문제 입력 파일: 학생의 이름, 평점이 저장된 students.txt 파일 출력 파일: 학생의 이름, 평점, 순위가 저장된 rank.txt 파일 나태희 2.31↲ 유현빈 4.23↲ 나원빈 4.42↲ 문건영 3.72↲ 소지법 3.74↲ 나보내 3.85↲ 장도건 4.06↲ 고수영 3.72↲ 이나라 4.43↲ 김해수 3.77↲ students.txt 파일 나태희 2.31 10↲ 유현빈 4.23 3↲ 나원빈 4.42 2↲ 문건영 3.72 8↲ 소지법 3.74 7↲ 나보내 3.85 5↲ 장도건 4.06 4↲ 고수영 3.72 8↲ 이나라 4.43 1↲ 김해수 3.77 6↲ rank.txt 파일 [프로그램 4-4]
학생 평점 파일을 읽어 평점 순위 파일 만들기 분석 학생의 정보 학생의 수는 10명임을 알고 있는 경우임 구조체(이름, 평점 저장) 학생의 수는 10명임을 알고 있는 경우임 students.txt 파일 메모장에서 직접 만들어 프로젝트 폴더 안에 저장 모든 학생의 평점 정보가 있어야만 순위를 구할 수 있음 → 파일에서 읽은 정보를 모두 배열에 저장해야 함 → 파일의 내용을 읽어서 구조체 배열 s에 저장 순위 구하기 나의 평점 s[i].GPA보다 높은 평점의 개수가 n개 → 나의 순위 s[i].rank는 n+1등
4 – 4 : 성적 처리 프로그램 1 #include <stdio.h> // fopen, fscanf, fprintf, fclose, EOF, printf의 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 #define SIZE 10 // 파일에 저장된 학생의 수 5 struct student // 구조체 정의 6 { 7 char name[20]; // 이름 8 double GPA; // 평점 9 int rank; // 순위 10 }; 11 12 int main() 13 { 14 struct student s[SIZE]; // 구조체 배열 선언 15 int i, u; 16 FILE *fp; // 파일 포인터 선언 17 18 fp = fopen("students.txt", "r"); // 학생 정보를 읽을 파일 열기 19 if (fp == NULL) // 파일 열기 에러 처리 20 { 21 printf("\n파일 열기 에러! \n"); exit(1); 22 }
4 – 4 : 성적 처리 프로그램 24 // 파일에 있는 학생 정보를 읽어 구조체 배열에 저장하기 25 for (i=0; i<SIZE; i++) 26 { 27 fscanf(fp, "%s %lf", s[i].name, &s[i].GPA); 28 } 29 fclose(fp); // 파일의 모든 자료를 배열에 저장했으므로 읽기용 파일을 닫기 30 31 // 파일에서 읽은 평점을 이용하여 나 s[i]의 순위를 구하기 32 for (i=0; i<SIZE; i++) 33 { 34 s[i].rank = 1; // 일단 나(i)의 순위를 1로 초기화 35 for (u=1; u<SIZE; u++) 36 { 37 // 나(i)의 평점이 다른 학생(u)의 평점보다 낮으면 순위를 1 증가 38 if (s[i].GPA < s[u].GPA) 39 s[i].rank ++; 40 } 41 }
4 – 4 : 성적 처리 프로그램 43 // 파일에 결과 출력하기 44 fp = fopen("rank.txt", "w"); // 결과를 출력할 rank.txt 파일을 쓰기용으로 열기 45 if (fp == NULL) // 파일 열기 에러 처리 46 { 47 printf("\n파일 열기 에러! \n"); exit(1); 48 } 50 // SIZE명의 이름, 평점, 순위를 파일에 쓰기 51 for (i=0; i<SIZE; i++) 52 { 53 fprintf(fp,"%-8s %4.2lf %2d\n",s[i].name,s[i].GPA,s[i].rank); 54 // printf("%-8s %4.2lf %2d\n", s[i].name, s[i].GPA, s[i].rank); 55 } 56 fclose(fp); // 파일 닫기 57 printf("파일 출력 완료! \n"); 58 59 return 0; 60 }
파일의 끝 확인하기 파일에 저장된 레코드(데이터) 수를 정확히 모른다면? 파일의 끝을 확인하여 파일 읽기를 중단하는 방법을 사용해야 한다. 대표적 방법 두 가지 feof 함수 이용하기 파일의 끝을 지나 제대로 읽기를 못했다면 파일에서 읽기를 그만하기 fscanf 함수의 반환값 활용하기 파일의 끝에 도착하거나 에러가 발생하여 EOF를 반환하지 않았다면 읽은 데이터를 사용하고 그렇지 않다면 읽기를 그만하기
파일의 끝 확인하기 feof 함수 예) feof(파일포인터명) 파일포인터에 연결된 파일의 끝을 지나갔다면 0이 아닌 값(참)을, 아직 파일의 끝을 지나지 않았다면 0(거짓)을 반환 ㈜ 필독 파일의 끝(문자)에 도달했을 때가 아니라 파일 끝(문자)을 지나갔을 때 0이 아닌 값(참)을 반환함 → 제대로 이해하지 못했다면 [프로그램 12-5]와 같이 잘못된 결과를 초래할 수 있으므로 주의해야 한다. 예) fp에 연결된 파일의 끝을 지났다면 파일을 닫기 if (feof(fp)) fclose(fp);
파일의 끝 확인하기 [프로그램 4-5] 문제 분석 입력: [프로그램 4-3]의 결과 파일인 age.txt 프로그램 실행 결과로 만들어진 파일에 저장된 데이터 수는 파일을 확인하지 않는 한 알 수 없다. → feof 함수를 이용하여 파일 끝을 지나지 않은 한 읽기를 계속하여 해결
4 - 5 : 파일의 끝을 확인하는 feof 함수의 정확한 사용 예 1 #include <stdio.h> // fopen, fscanf, fclose, feof 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 4 int main() 5 { 6 FILE *fp; // 파일 포인터 선언 7 int age; 8 9 fp = fopen("age.txt", "r"); // 파일을 읽기 모드로 열기 : 15 // 파일에 저장된 모든 나이를 읽어서 모니터에 출력하기 16 fscanf(fp, "%d", &age); // 일단 파일에서 정수(나이) 읽기를 시도 17 while (!feof(fp)) // 아직 파일의 끝을 지나지 않았다면 반복하기 18 { 19 printf("%2d \n", age); // 방금 파일에서 읽은 정수(나이)를 모니터로 출력하기 20 fscanf(fp, "%d", &age); // 파일에서 다음 정수(나이) 읽기를 시도 21 } 22 23 fclose(fp); // fp에 연결된 파일 닫기 25 return 0; 26 } 20↲ 23↲ 25↲ age.txt 파일의 내용
파일의 끝 확인하기 fscanf 함수의 반환값 활용하기 fscanf는 파일의 끝에 도착하거나 에러가 나면 EOF를 반환한다. // 일단 파일에서 정수를 한 개 읽어온 후 // 성공했다면 출력하기를 반복하기 while (fscanf(fp, "%d", &age) != EOF) { printf("%2d \n",age); } [프로그램 4-5] : 9 fp = fopen("age.txt", "r"); 15 // 파일에 저장된 모든 나이를 읽어서 모니터에 출력하기 16 fscanf(fp, "%d", &age); 17 while (!feof(fp)) 18 { 19 printf("%2d \n", age); 20 fscanf(fp, "%d", &age); 21 } 22 23 fclose(fp); // fp에 연결된 파일 닫기 20↲ 23↲ 25↲ age.txt 파일의 내용
판매실적 우수자 파일 만들기 문제: 판매실적 우수자 파일 만들기 분석 입력: 사원 번호, 자동차 판매 실적이 저장된 sales_report.txt 파일 출력: 판매 실적이 30보다 큰 사원 번호, 판매 실적을 저장한 good.txt 파일 분석 “sales_report.txt” 파일 만들기 자료를 읽을 순서에 맞게 자료형에 맞게 만들어야 하며 마지막 자료 뒤에도 엔터키를 입력하는 것을 잊지 않는다. 1203 25↲ 1102 35↲ 1103 21↲ 1205 29↲ 1105 32↲ 1202 40↲ 1207 25↲ 1112 27↲ 1113 52↲ 1212 27↲ sales_report.txt 파일 판매실적 우수자 ------------ 사원번호 판매수 1102 35대 1105 32대 1202 40대 1113 52대 good.txt 파일 [프로그램 4-5]
4 – 6 : 사원 정보 파일에서 판매 실적 우수자 명단 파일 만들기 1 #include <stdio.h> // fopen, fscanf, fprintf, fclose, EOF, printf의 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 4 int main() 5 { 6 int no, sales; 7 FILE *fpr, *fpw; // 읽기용, 쓰기용 파일 포인터 선언 8 9 fpr = fopen("sales_report.txt", "r"); // 판매 실적 파일을 읽기용으로 열기 10 if (fpr == NULL) // 파일 열기 에러 처리 11 { printf("파일 열기 에러! \n"); exit(1); } 14 15 fpw = fopen("good.txt", "w"); // 우수자 명단 파일을 쓰기용으로 열기 16 if (fpw == NULL) // 파일 열기 에러 처리 17 { printf("파일 열기 에러! \n"); exit(1); } 20 21 // 출력 제목을 파일에 쓰기 22 fprintf(fpw, "판매실적 우수자 \n\n"); 23 fprintf(fpw, " ------------------- \n"); 24 fprintf(fpw, " 사원번호 판매수 \n"); 25 fprintf(fpw, " ------------------- \n");
4 – 6 : 사원 정보 파일에서 판매 실적 우수자 명단 파일 만들기 27 // 파일에서 읽기를 성공했다면 판매수가 30보다 클 때만 우수자 명단 파일에 저장하기 28 while (fscanf(fpr, "%d %d", &no, &sales) != EOF) 29 { 30 if (sales > 30) 31 { 32 fprintf(fpw, " %5d %5d대 \n", no, sales); 33 // printf(" %5d %5d대 \n", no, sales); 모니터 결과 확인용 34 } 35 } 36 fprintf(fpw, " ------------------- \n"); 37 38 fclose(fpr); fclose(fpw); // 파일 닫기 39 printf(" 우수자 명단 파일을 저장했습니다. \n"); 40 41 return 0; 42 } 파일에 저장된 레코드 수를 모를 때 파일 읽기가 제대로 되었을 때만 while 본체 실행하기 good.txt 파일 1203 25 1102 35 1103 21 1205 29 1105 32 1202 40 : : sales_report.txt 판매실적 우수자 ------------- 사원번호 판매수 1102 35대 fpr no 1102 sales 35
4 – 6 : 사원 정보 파일에서 판매 실적 우수자 명단 파일 만들기 1203 25 1102 35 1103 21 1205 29 1105 32 1202 40 1207 25 1112 27 1113 52 1212 27 sales_report.txt 파일의 내용 판매실적 우수자 -------------- 사원번호 판매수 1102 35대 1105 32대 1202 40대 1113 52대 good.txt 파일의 내용 [프로그램 12-13]
판매 실적 우수자 명단 파일 만들기 만일 판매실적을 내림차순으로 정렬하여 모니터로 출력하려면? 정렬을 하기 위해서는 모든 자료가 배열에 저장되어야 하므로 파일에서 읽은 자료를 다음 그림과 같이 배열에 저장해야 한다. sales_report.txt 파일의 내용 1203 25 1102 35 1103 21 1205 29 1105 32 1202 40 1207 25 1112 27 1113 52 1212 27 int no[10]; 1203 1102 1103 : 1212 int sales[10]; 25 35 21 : 27 배열을 정렬 후 모니터로 출력하기(printf) 또는 파일로 출력하기(fprinf)
파일 처리의 팁 파일 처리의 팁 모니터와 파일 출력을 둘 다 하기 파일로 출력하는 fprintf 부분을 39행 처럼 모두 printf 함수로 작성한 후 결과가 제대로 나오면 36행 처럼 fprintf 함수로 바꾸는 것도 결과를 쉽게 확 하는 방법 예) 32행을 printf(" %5d %5d대 \n", no, sales); 로 작성 후 fprintf(fpw, " %5d %5d대 \n", no, sales);로 수정하기 모니터와 파일 출력을 둘 다 하기 printf 함수로 출력하는 부분을 모두 복사하여 fprintf로 변경함으로써 모니터로도 결과를 출력하고 파일로도 출력 가능 32 fprintf(fpw, " %5d %5d대 \n", no, sales); 33 printf(" %5d %5d대 \n", no, sales);
문자 단위로 파일에 쓰기 : fputc 함수 Text file 입출력 함수
문자 단위로 파일에 쓰기 : fputc 함수 fputc 함수 파일에 한 문자씩 출력 형식 예 fputc(문자, 파일포인터명) → 문자를 파일포인터가 가리키는 파일에 씀 fputc(정수, 파일포인터변수명) → ASCII 코드 값이 정수에 해당하는 문자 한 개를 파일에 씀 예 fputc(67, fp); → fp에 연결된 파일에 'C'를 쓴다. ch = 'A'; fputc(ch, fp); → fp에 연결된 파일에 'A'를 쓴다.
문자 단위로 파일에 쓰기 : fputc 함수 fputc 함수 파일에 한 문자씩 출력
문자 단위로 파일 읽기 : fgetc 함수 fgetc 함수 파일에서 문자 한 개를 읽어 반환 형식 예) 파일포인터명에 연결된 파일에서 문자 한 개를 읽어서 반환 반환형은 int형(문자의 ASCII 코드값) 읽기 에러 / 파일의 끝 도달 → 매크로 상수 EOF(-1에 해당) 반환 예) char ch; FILE *fp = feopn("data.txt", "r"); ch = fgetc(fp); → data.txt 파일에서 문자 한 개를 읽은 후 ch에 저장
문자 단위로 파일 읽기 : fgetc 함수 fgetc 함수 파일에서 문자 한 개를 읽어 반환
프로그램 예 : 파일 복사 프로그램 문제 분석 입력: 사용자가 복사하고 싶은 원본 파일명과 복사본의 파일명 출력: 원본 파일과 동일한 복사본 파일 분석 원본 파일에서 한 문자를 읽은 후 복사본 파일에 읽은 문자를 쓰기 fp1 fp2 fputc(ch, fp2); ‘H’ ch 변수 C 프로그램 원본 파일 복사본 파일 Hello.↲ Hi.↲ How are you?↲ ch = fgetc(fp1) H 파일에서 읽기 파일에 쓰기
4 – 7 : 파일 복사 프로그램 1 #include <stdio.h> // fgetc, fputc, fopen, fclose 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 4 int main() 5 { 6 FILE *fp1, *fp2; // 원본 파일과 복사본 파일에 대한 파일 포인터 7 char f_name1[30], f_name2[30], ch; // 원본 파일명, 복사본 파일명 9 printf("파일을 복사합니다.\n"); 10 11 // 원본 파일을 읽기 모드로 열기 12 printf("원본 파일명: "); gets(f_name1); 13 fp1 = fopen(f_name1, "r"); 14 if (fp1 == NULL) 15 { 16 printf(" %s란 파일이 없습니다. \n", f_name1); exit(1); 17 } 19 // 복사본 파일을 쓰기 모드로 열기 20 printf("복사본 파일명: "); gets(f_name2); 21 fp2 = fopen(f_name2, "w"); 22 if (fp2 == NULL) 23 { 24 printf(" %s란 파일이 없습니다. \n", f_name2); exit(1); 25 }
4 – 7 : 파일 복사 프로그램 27 // 파일의 끝에 도달하지 않아서 ch에 저장된 값이 EOF가 아니라면 복사본에 쓰기를 반복 28 while ((ch = fgetc(fp1)) != EOF) 29 fputc(ch, fp2); // 복사본 파일에 읽은 문자 쓰기 30 31 fclose(fp1); fclose(fp2); 32 printf("원본 %s를 복사한 복사본 %s가 저장되었습니다. \n", f_name1, f_name2); 33 34 return 0; 35 } ch = fgetc(fp1); // 원본 파일에서 문자 한 개 읽기 while (!feof(fp1)) // 파일의 끝을 지나지 않았다면 반복하기 { fputc(ch, fp2); // 읽은 문자를 복사본 파일에 쓰기 ch = fgetc(fp1); }
문자열 단위 입출력 : fgets, fputs 함수 텍스트 파일 입출력에 사용 fputs 함수 문자열 단위의 파일 쓰기 puts와 달리 파일에 쓸 때 자동으로 개행 문자를 넣지 않음에 주의 fputs(문자열주소, 파일포인터명) 문자열의 끝을 나타내는 널문자 및 개행 문자가 자동으로 들어가지 않음 성공하면 출력한 바이트 수를 반환, 실패하면 EOF 반환 이곳에 저장된 문자열을 파일 포인터에 연결된 파일에 쓴다.
문자열 단위 입출력 : fgets, fputs 함수 문자열 단위의 파일 쓰기 puts와 달리 파일에 쓸 때 자동으로 개행 문자를 넣지 않음에 주의 fgets(문자열주소, 최대입력문자수, 파일포인터명)) “(최대 문자수 - 1)개의 문자 + 널 문자(\0)”를 지정한 문자열주소부터 저장 ㈜ gets와 달리 개행 문자도 포함해서 계속 읽음 if (최대문자수만큼 읽기 전 개행 문자(\n)를 읽음) → 읽기 중단, 널문자(\0) 합친 문자열을 저장 읽는 중 파일 끝에 도달 또는 에러 발생 → NULL 포인터 반환 파일에서 읽은 문자열을 저장
문자열 단위 입출력 : fgets, fputs 함수 예) char string1[20], string2[20], string3[20]; FILE *fp = fopen("address.txt", "r"); fgets(string1, 20, fp); fgets(string2, 20, fp); fgets(string3, 20, fp);
프로그램 예: 주소록 만들기 [프로그램 4-8] 입력: 학생 5명의 연락처를 한 행씩 입력 출력: 주소록 파일 address.txt 만든 후 주소록 파일의 내용을 화면에 표시 이름 전화번호 주소 입력 후 엔터키를 누르세요.(5명) 1. 나태희 010-5757-2828 서울 동작구↲ 2. 유현빈 010-2425-7979 서울 영등포구↲ 3. 나원빈 010-8282-1472 대구 북구↲ 4. 문건영 010-3344-8485 대전 동구↲ 5. 소지법 010-7889-5229 부산 해운대구↲ >> 주소록 목록 << 나태희 010-5757-2828 서울 동작구↲ 유현빈 010-2425-7979 서울 영등포구↲ 나원빈 010-8282-1472 대구 북구↲ 문건영 010-3344-8485 대전 동구↲ 소지법 010-7889-5229 부산 해운대구↲ 실행결과 22행 gets(info); 23행 fputs(info, fp);의 결과 24행 fputs(“\n”, fp); 의 결과 나태희 010-5757-2828 서울 동작구 ↲ 유현빈 010-2425-7979 서울 영등포구↲ 나원빈 010-8282-1472 대구 북구↲ 문건영 010-3344-8485 대전 동구↲ 소지법 010-7889-5229 부산 해운대구↲ address.txt 파일의 내용 39행 fgets(info, 80, fp); 38행 printf(“%s”, info);의 결과
4 – 8 : 문자열 단위의 파일 입출력 예 1 #include <stdio.h> // fputs, fgets 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 #define SIZE 5 5 int main() 6 { 7 char f_name[20] = "address.txt"; 8 char info[80]; 10 FILE *fp = fopen(f_name, "w"); // 주소를 저장할 파일 열기 11 int i; 12 13 if (fp == NULL) // 파일 열기 에러 처리 14 { printf("파일 열기 에러! \n"); exit(1); } 17 18 printf("이름 전화번호 주소 입력 후 엔터키를 누르세요.(%d명) \n", SIZE); 19 for (i=0; i<SIZE; i++) 20 { 21 printf("%d. ", i+1); 22 gets(info); // 키보드로 한 행씩 입력받는다. 23 fputs(info, fp); // 입력받은 문자열을 파일에 쓰기 24 fputs("\n", fp); // 문자열 뒤에 개행 문자 쓰기 25 } 26 fclose(fp); // 파일 닫기
4 – 8 : 문자열 단위의 파일 입출력 예 28 fp = fopen(f_name, "r"); // 주소를 저장한 파일 열기 29 if (fp == NULL) // 파일 열기 에러 처리 30 { printf("파일 열기 에러! \n"); exit(1); } 33 34 printf("\n>> 주소록 목록 << \n"); 35 fgets(info, 80, fp); // 파일에서 문자열을 읽어 info 문자열에 저장한다. 36 while (!feof(fp)) // 파일의 끝을 지나지 않았다면 반복한다. 37 { 38 printf("%s", info); // 파일에서 읽은 문자열을 모니터에 출력한다. 39 fgets(info, 80, fp); // 파일에서 문자열을 읽어 info 문자열에 저장한다. 40 } 41 fclose(fp); // 파일 닫기 42 43 return 0; 44 }
이진 파일 입출력 텍스트 파일 이진 파일 모든 데이터가 문자열로 변환되어 기록 예) 정수 123456 → 6개의 문자 ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’으로 변환되어 파일에 기록 파일에서 읽은 6개 문자 ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’ → 정수 123456로 변환됨 이진 파일 수치 데이터가 문자로 변환되지 않고 곧바로 수치로 저장 정수 123456 → 정수 한 개로 주기억장치의 4바이트에 이진 형식으로 표현되어 저장됨 → 텍스트 파일보다 저장 공간을 적게 차지 수치 읽을 때도 한 개의 수치로 바로 읽기 때문에 텍스트 파일의 수치와 문자 열 간의 변환 과정이 없고, 읽고 쓰기가 빠름
이진 파일 입출력 이진 파일은 텍스트 파일과 달리 행으로 분리되지 않으므로 행의 끝을 표시할 필요가 없으며 널 문자나 개행 문자같은 글자들도 데이터로 취급 (a): 이진 파일을 16진수로 출력한 화면 (b): 이진 파일을 메모장에서 열었을 때의 화면 이진 파일의 데이터 읽기과 쓰기는 fread 함수와 fwrite 함수 사용
이진 파일에 쓰기 : fwrite 함수 fwrite 함수 블록(연속된 데이터 집합) 단위의 파일 쓰기 → 구조체 데이터를 한 번에 쓸 수 있다. fread 함수로 이진파일 읽기 시 쓰기를 한 블록의 크기대로 읽어야 함 형식 FILE *fp = fopen(“파일명”, “wb”); // w: 쓰기, b: 이진 파일 fwrite(데이터시작주소, 블록크기, 블록개수, 파일포인터명); ‘데이터시작주소’부터 저장된 ‘블록크기 * 블록개수’ 바이트를 파일에 쓴 후 쓴 블록의 개수를 반환 쓰는 데이터의 형은 달라도 되지만 이럴 경우 이진 파일에서 읽어 올 때 데이 터를 기록한 순서와 정확히 일치하게 읽어야 함 파일에 쓰기
이진 파일에 쓰기 : fwrite 함수 fwrite 함수 이진 파일에서는 데이터의 단위를 block으로 처리하며 선언된 구조체 변수 st를 하나의 block으로 간주
4 – 9 : 구조체 멤버를 입력받아 이진 파일로 출력하기 1 #include <stdio.h> // fread, fopen, fclose 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 #define SIZE 3 // 정보를 입력할 사용자 수 4 5 struct person // 구조체 정의 6 { 7 char name[7], gender[3]; // 이름, 성별 8 int age; // 나이 9 }; 10 typedef struct person PERSON; // 자료형 재정의 11 12 int main() 13 { 14 int i; 15 PERSON user; // 사용자 정보를 저장할 구조체 변수 선언 16 FILE *fp = fopen("user.bin", "wb"); // 쓰기 모드로 이진 파일 열기 17 18 if (fp == NULL) // 파일 열기 에러 처리 19 { 20 printf("파일 열기 에러! \n"); exit(1); 21 }
4 – 9 : 구조체 멤버를 입력받아 이진 파일로 출력하기 23 // SIZE명의 사용자 정보를 키보드에서 입력받아 이진 파일에 출력하기 24 printf(">> 사용자 정보를 입력하세요.(%d명)", SIZE); 25 for (i=0; i<SIZE; i++) 26 { 27 printf("\n%d. 이름 : ", i+1); gets(user.name); 28 printf(" 성별 : "); gets(user.gender); 29 printf(" 나이 : "); scanf("%d", &user.age); 31 // user에 저장된 사용자 정보 즉 PERSON형 구조체 한 개를 파일에 쓰기 32 fwrite(&user, sizeof(PERSON), 1, fp); 33 fflush(stdin); // 다음 gets 입력을 위해 표준 입력 장치의 버퍼 비우기 34 } 35 fclose(fp); 36 printf("\n== 파일 출력 완료 ==\n"); 37 38 return 0; 39 } user 구조체 변수 C 프로그램 “나태희” “여” 20 블록 크기 fwrite(&user, sizeof(PEERSON), 1, fp); fp에 연결된 파일
이진 파일 읽기 : fread 함수 fread 함수 이진 파일에서 데이터 블록을 읽는 함수 형식 FILE *fp = fopen(“파일명”, “rb”); // r : 읽기, b : 이진 파일 fread(데이터저장주소, 블록크기, 블록개수, 파일포인터명); 파일에서 ‘블록크기 * 블록개수’ 바이트를 읽어서 저장주소에 저장한 후 에 저장한 후 읽은 블록 개수를 반환 데이터저장주소에 해당하는 기억장소는 (블록크기 * 블록개수) 바이트의 데이터를 저장하기에 충분한 기억장소여야 함 파일에서 읽은 블록을 저장
이진 파일 읽기 : fread 함수 fread 함수
4 – 10 : 이진 파일의 데이터를 모니터로 출력하기 1 #include <stdio.h> // fread, fopen, fclose 함수를 위한 헤더 파일 2 #include <stdlib.h> // exit 함수를 위한 헤더 파일 3 4 struct person // 구조체 정의 5 { 6 char name[7], gender[3]; // 이름, 성별 7 int age; // 나이 8 }; 9 typedef struct person PERSON; // 자료형 재정의 10 11 int main() 12 { 13 PERSON user; // 사용자 정보를 저장할 구조체 변수 선언 14 FILE *fp; 15 16 fp = fopen("user.bin", "rb"); // 읽기 모드로 이진 파일 열기 17 if (fp == NULL) 18 { 19 printf("파일 열기 에러!\n"); exit(1); 20 }
4 – 10 : 이진 파일의 데이터를 모니터로 출력하기 22 puts("-------------------------------------"); 23 puts(" 이름 성별 나이 "); 24 puts("-------------------------------------"); 25 26 // 파일에서 블록 1개를 제대로 읽었다면 계속 반복하기 27 while (fread(&user, sizeof(PERSON), 1, fp) == 1) 28 printf(" %-8s %-3s %4d\n", user.name, user.gender, user.age); 29 30 puts("-------------------------------------"); 31 fclose(fp); // 파일 닫기 32 33 return 0; 34 }
Text mode로 저장된 file을 Binary mode로 읽을 수 있는가? 물론 읽을 수 있다. 단, 텍스트 방식에서는 byte 단위로 처리되므로 텍스트 방식으로 저장된 파일을 이진 방식으로 파 일을 읽을 때는 fread 대신에 byte 단위의 fgetc를 사용한다. 추가로 파일에서 줄을 바꾸기 위해 입력한 Enter키('\n')에 대해서도 텍스트 방식은 파일에 저장 할 때 CR(Carrage return)과 LF(Line Feed)의 제어문자 쌍으로 변환하여 저장하고, 읽을 때는 반대 로 처리하지만 이진 방식은 어떤 변환도 사용하지 않는다. 마찬가지로 텍스트 방식에서 파일을 읽을 때 파일의 끝을 나타내는 Ctrl-Z (EOF)를 만날 때까지만 읽지만 이진 방식에서는 이 또한 하나의 데이터로 인식하므로 읽는 동작을 중단하지 않는다. 따라서 파일을 복사하는 프로그램을 만들 경우에 원본 파일이 텍스트 파일이건 이진 파일이건 이 진 방식으로 파일을 open하고 byte 단위로 읽은 다음 다시 byte 단위인 fputc를 사용하여 출력하는 방법을 이용한다.
파일의 임의 접근 파일의 임의 접근(random access) 순차적 접근이 아닌 파일의 임의의 위치에서 바로 읽기/쓰기를 할 수 있는 접 근 방식 파일 읽기/쓰기를 시작할 위치를 가리키는 포인터인 ‘파일 위치 지시자’를 조 작하는 함수가 필요 fseek, ftell, rewind 함수를 파일 위치 지시자 다음에 참조(읽기/쓰기)할 위치를 가리키는 포인터 키보드의 키를 누르면 글자가 나타나는 위치를 알려주는 커서와 같은 기능
파일의 임의 접근 fseek함수 파일에서 다음에 읽거나 쓸 데이터의 시작 위치를 변경 형식 ‘파일포인터’에 연결된 파일의 파일 위치 지시자가 ‘기준점’으로부터 ‘오프 셋’만큼 떨어진 곳을 가리키게 함 → 즉, 다음 읽기/쓰기 시작 위치를 (기준점+오프셋) 바이트 위치로 변경 기준점(whence): 오프셋을 적용할 기준점, 세 매크로 상수 중 한 개 SEEK_SET: 0 → 파일 시작지점 SEEK_CUR: 1 → 파일의 현재 지점 SEEK_END: 2 → 파일의 끝 지점 오프셋(offset): 기준점에서 이동할 바이트 수 기준점 이전 → 음수, 기준점 이후 → 양수 성공하면 0, 실패하면 0이 아닌 값을 반환
파일의 임의 접근 fseek함수
(현재 fp에 연결된 파일의 파일 위치 지시자가 가리키는 곳) 파일의 임의 접근 예 ftell(파일 포인터 변수명); 다음 읽기/쓰기를 시작할 위치를 반환 파일의 입출력 위치를 리턴 예) rewind(fp); position = ftell(fp); → position은 0 1000 fseek(fp, 100, SEEK_SET) 결과 다음 읽기/쓰기 시작 위치 (현재 fp에 연결된 파일의 파일 위치 지시자가 가리키는 곳) fseek(fp, 200, SEEK_CUR); 결과 fseek(fp, -100, SEEK_END); 결과
파일의 임의 접근
파일의 임의 접근 ftell(파일 포인터 변수명); 파일의 처음(시작)위치에서 현재의 파일 포인터 위치까지의 거리를 byte 크기 로 반환. 따라서 파일의 크기를 byte로 표시하거나 파일에 몇 개의 block이 저 장되어 있는가를 계산할 때 다음과 같이 사용
파일의 임의 접근 rewind(파일포인터명) 파일의 다음 읽기/쓰기 위치를 파일의 시작 지점으로 이동 → fseek(fp, 0, SEEK_SET)와 동일
임의 접근을 이용한 파일 정보 출력 및 수정 문제 이진 파일의 내용을 모니터에 출력 후 사용자로부터 수정하고 싶은 사용자 정보를 입력받은 후 파일의 내용을 수정하기 이 프로그램을 다시 실행하면 파일 내용이 변경된 것을 확인 가능
임의 접근을 이용한 파일 정보 출력 및 수정 분석 파일 내용 수정 시 수정할 정보가 저장된 곳으로 곧바로 이동한 후 수정 : 임의 접근 이용 파일에서 읽기와 수정 정보 쓰기를 해야 파일 열기 모드는 “r+b” 파일의 크기 position 구하기 fseek(fp, 0, SEEK_END); // 파일 위치 지시자를 (파일끝위치+0)로 이동 position = ftell(fp); // 파일 위치 지시자의 현 위치를 position에 저장 파일에 저장된 사용자 정보 수 size size = position / sizeof(PERSON); // 파일에 저장된 블록의 개수 수정 정보의 위치 사용자에게서 정보를 수정하고 싶은 사용자의 순번을 no에 입력 받는다면 no번째 사용자 정보가 저장된 시작 위치는 파일 시작 위치에서 sizeof(PERSON) * (no-1)바이트 떨어진 곳
4 – 11 : 이진 파일에 데이터를 추가하고 모니터로 출력하기 1 #include <stdio.h> // fseek, rewind, ftell을 위한 헤더 파일 2 #include <stdlib.h> // exit를 위한 헤더 파일 3 4 typedef struct person // 구조체 정의 5 { 6 char name[7]; 7 char gender[3]; 8 int age; 9 } PERSON; // 구조체 struct person을 PERSON으로 재정의 10 11 int main() 12 { 13 FILE *fp; 14 PERSON user; 15 int size, position, i, no; 16 17 fp = fopen("user.bin", "r+b"); // 읽기/쓰기 모드로 이진 파일 열기 18 if (fp == NULL) // 파일 열기 에러 처리 19 { 20 printf("파일 열기 에러! \n"); exit(1); 21 }
4 – 11 : 이진 파일에 데이터를 추가하고 모니터로 출력하기 23 // 파일에 저장된 구조체 정보의 개수를 구하기 위해 파일 위치 지시자 정보를 이용하기 24 fseek(fp, 0, SEEK_END); // (파일 끝 위치+0)으로 이동하기 25 position = ftell(fp); // 현 위치를 position에 저장하기 26 size = position / sizeof(PERSON); // PERSON 크기의 블록 개수 구하기 27 28 // 파일의 내용을 읽어서 모니터에 출력하기 29 puts("------------------------"); 30 puts(" 번호 이름 성별 나이 "); 31 puts("------------------------"); 32 rewind(fp); // 파일의 시작 위치로 이동 33 for (i=0; i<size; i++) 34 { 35 fread(&user, sizeof(PERSON), 1, fp); 36 printf("%3d %-8s %-3s %4d\n", i+1, user.name, user.gender, user.age); 37 } 38 puts("------------------------");
4 – 11 : 이진 파일에 데이터를 추가하고 모니터로 출력하기 40 // 정보를 수정할 번호와 수정 정보를 입력받기 41 printf("정보를 수정할 사용자의 번호는? "); scanf("%d", &no); 42 if ((no < 1) || (no > size)) // 잘못된 입력 번호 처리 43 { 44 printf("번호의 범위가 잘못되어 종료합니다.\n"); exit(1); 45 } 46 printf("\n이름 : "); scanf("%s", user.name); 47 printf("성별 : "); scanf("%s", user.gender); 48 printf("나이 : "); scanf("%d", &user.age); 49 50 // 파일 위치 지시자를 no번째 사용자 정보 시작 위치로 이동한 후 새 정보를 파일에 쓰기 51 fseek(fp, sizeof(PERSON) * (no-1), SEEK_SET); 52 fwrite(&user, sizeof(PERSON), 1, fp); 53 54 fclose(fp); 55 printf("\n파일 수정이 완료되었습니다. \n"); 56 57 return 0; 58 }