파일 입출력
파일 입출력의 필요성
- 프로그램이 꺼진 이후에도 데이터를 저장하기 위해서는 파일 입출력이 필요
- 어떠한 데이터를 프로그램 안에서만 사용되는 게 아니라 프로그램 외부로 일시적으로 저장을 시켜놨다가 다시 프로그램을 실행하거나 혹은 어떠한 데이터를 불러오도록 해서 이전의 상태를 그대로 프로그램 내부로 가져올 수 있게 하기 위해 필요
- 파일이 실질적으로 저장되는 위치는 cpu, ssd, ram가 있음
- ram, cpu 같은 경우는 휘발성 있게 저장한다는 특징이 있음, 컴퓨터를 껐다 켜면 데이터가 사라짐
- 일반적으로 바탕화면에 있는 일반적인 파일들은 ssd 혹은 하드 디스크와 같은 보조 기억 장치에 저장이 되고, 그것을 실행하면 그 프로그램이 프로세스로 변환되면서 ram에 들어가서 구동을 하게 되는 거고, cpu가 ram에서 코드를 읽어서 실행을 시켜줌
파일을 열고 닫기
1.
- 파일 입출력 변수는 file형식의 포인터 변수로 선언
- 파일을 열 때는 fopen( ) 함수를 이용
- 파일을 닫을 때는 fclose( ) 함수를 이용
FILE *fp;
fp = fopen(파일 경로, 접근 방식);
// 파일 관련 처리
fclose(fp);
2.
- 파일 열기 함수인 fopen( ) 함수에는 파일 경로와 접근 방식을 설정할 수 있음
- 기본 경로는 현재 프로그램의 경로
- 가장 많이 사용되는 접근 방식은 다음과 같음
r (read) - 파일에 접근하여 데이터를 읽음
w (write) - 파일에 접근하여 데이터를 기록(파일이 이미 존재하면 덮어쓰기)
a - 파일에 접근하여 데이터를 뒤에서부터 기록
파일 입출력 함수
- 기본적인 입출력을 위해서 printf()와 scanf() 함수를 사용하곤 했음
- 파일 입출력에서는 그 대신에 fprintf()와 fscanf()가 사용됨
fprintf(파일 포인터, 서식, 형식 지정자);
fscanf(파일 포인터, 서식, 형식 지정자);
파일 입출력의 과정
- 파일 입출력은 열고, 읽고/쓰고, 닫기의 과정을 철저히 따라야 함
- 파일을 열 때는 파일 포인터가 사용되며, 이는 동적으로 할당된 것
- 따라서 파일 처리 이후에 파일을 닫아주지 않으면 메모리 누수가 발생
파일 열기 > 파일 읽기/쓰기 > 파일 닫기
* 현재 프로그램의 경로에서 특정한 파일을 쓰기 모드로 생성하여 문자열을 기록할 수 있음
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void){
char s[20] = "Hello World";
FILE *fp;
fp = fopen("temp.txt", "w");
fprintf(fp, "%s\n", s); // 일반적인 printf와 동일하다고 볼 수 있음
fclose(fp);
return 0;
}
Visual Studio에서 기본 실행 파일 경로 확인하는 방법
1. 프로젝트 이름에 마우스 우 클릭 > 파일 탐색기에서 폴더 열기
* 학생 정보 시스템 만들기
- 학생들의 이름과 성정 파일 만들기
1. 학생 구조체 만들기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // 학생 구조체
char name[20];
int score;
} Student;
2. 학생 데이터를 읽어 그대로 출력하기
int main(void) {
int n, sum = 0; // 학생의 명수를 의미하는 n을 만들고, 학생의 성적을 더한 변수 sum 생성
FILE *fp;
fp = fopen("input.txt", "r"); // 읽기 모드로 파일을 엶
fscanf(fp, "%d", &n); // 특정한 파일로 부터 하나의 정수형 변수를 읽을수 있도록 함
// 여려 명의 학생들의 정보가 담길수 있기 때문에 동적 메모리 할당을 이용해서 총 n명의 학생에 대한 정보가
// 담길수 있는 공간을 메모리 주소상에 할당을 해줌
Student *students = (Student*)malloc(sizeof(Student) * n);
for (int i = 0; i < n; i++) {
// 학생들에 대한 이름과 점수 정보를 파일로 부터 입력을 받아서 입력을 해줌
fscanf(fp, "%s %d", &((students + i)->name), &((students + i)->score));
printf("이름: %s", "성적: %d\n", (students + i)->name, (students + i)->score);
}
system("pause");
return 0;
}
3. 성적 평균을 구하고 메모리 할당 해제하기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // 학생 구조체
char name[20];
int score;
} Student;
int main(void) {
int n, sum = 0; // 학생의 명수를 의미하는 n을 만들고, 학생의 성적을 더한 변수 sum 생성
FILE *fp;
fp = fopen("input.txt", "r"); // 읽기 모드로 파일을 엶
fscanf(fp, "%d", &n); // 특정한 파일로 부터 하나의 정수형 변수를 읽을수 있도록 함
// 여려 명의 학생들의 정보가 담길수 있기 때문에 동적 메모리 할당을 이용해서 총 n명의 학생에 대한 정보가 담길수 있는 공간을 메모리 주소상에 할당을 해줌
Student *students = (Student*)malloc(sizeof(Student) * n);
for (int i = 0; i < n; i++) {
// 학생들에 대한 이름과 점수 정보를 파일로 부터 입력을 받아서 입력을 해줌
fscanf(fp, "%s %d", &((students + i)->name), &((students + i)->score));
}
for (int i = 0; i < n; i++) {
sum += (students + i)->score;
}
free(students); // 메모리 주소 공간을 할당 해제
fclose(fp); // 열려있는 파일 닫기
printf("점수 평균: %.2f\n", (double) sum / n); // 소수점 자리 둘째까지 출력, 합계를 실수형으로 형 변환을 한 다음 전체 학생의 수로 나누어서 평균 값을 출력
system("pause");
return 0;
}
- 파일 입출력을 이용해 데이터를 파일로부터 가져오거나 데이터를 파일로 내보낼 수 있음
- 파일 입출력이 끝난 이후에는 반드시 파일 객체를 메모리에서 할당 해제해주어야 함