15. 파일 입출력
<파일 입출력의 필요성>
- 프로그램이 꺼진 이후에도 데이터를 저장하기 위해서는 파일 입출력이 필요하다.
- 게임을 껐다 킬 때마다 다시 처음부터 캐릭터를 키워야 한다면 매우 억울할 것이다.
※ 파일이 실질적으로 저장되는 위치는?
- SSD (RAM인 CPU같은 경우는 휘발성 있게 저장한다는 특징이 있다. 즉 컴퓨터를 껐다 키면 데이터가 사라진다는 것이다. 그래서 일반적으로 바탕화면에 있는 파일들은 SSD나 하드디스크 같은 보조기억장치에 저장이 되고 그것을 더블 클릭 해서 실행을 하면 그 프로그램이 프로세스로 변환되면서 RAM에 들어가서 구동을 하게 되는 것이다. CPU는 그 RAM에서 하나하나씩 코드를 읽어서 실행을 시켜준다. 따라서, 실질적으로 파일이 영구적으로 저장이 되는 위치라고 한다면 SSD라고 할 수 있는 것이다.
<파일을 열고 닫기>
- 파일 입출력 변수는 FILE형식의 “포인터 변수”로 선언한다.
FILE *fp;
fp=fopen(“파일 경로”, “접근 방식”);
fclose(fp);
- 파일을 열 때는 fopen()함수를 이용한다.
- 파일을 닫을 때는 fclose()함수를 이용한다.
-파일 열기 함수인 fopen()함수에는 파일 경로와 접근 방식을 설정 할 수 있다.
◇ 기본 경로는 현재 프로그램의 경로이다.
◇ 가장 많이 사용되는 접근 방식은
r: 파일에 접근하여 데이터를 읽는다.
w: 파일에 접근하여 데이터를 기록한다.(파일이 이미 존재하면 덮어쓰기)
a: 파일에 접근하여 데이터를 “마지막(뒤)”에서부터 기록한다.
<파일 입출력 함수>
- 기본적인 입출력을 위해서 printf()와 scanf()함수를 사용하곤 했다.
- 파일 입출력에서는 그 대신에 fprintf()와 fscanf()가 사용된다. ▶ “파일 포인터”라는 매개변수가 하나 더 들어간다고 보면 된다. ex) fprintf(fp,"%s\n",s)
fprintf(파일 포인터, 서식, 형식지정자);
fscanf(파일 포인터, 서식, 형식지정자);
<파일 입출력의 과정>
- 파일 입출력은 열고, 읽고/쓰고, 닫기의 과정을 “철저히” 따라야한다.
- 파일을 열 때는 “파일 포인터가 사용”되며, 이는 “동적으로 할당”된 것이다.
- 따라서 파일 처리 이후에 파일을 닫아주지 않으면 메모리 누수가 발생한다.
「파일 열기 ▶ 파일 읽기.쓰기 ▶ 파일 닫기」
<파일을 열어 문자열 쓰기>
- 현재 프로그램의 경로에서 특정한 파일을 쓰기 모드로 생성하여 문자열을 기록할 수 있다.
(예제1)파일을 열어 문자열 쓰기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
char s[20] = "Hello World";
FILE* fp;
fp = fopen("temp.txt", "w");
fprintf(fp,"%s\n",s);
fclose(fp);
system("pause");
return 0;
}
(해설) #include _CRT_SECURE_NO_WARNINGS 를 넣어준 이유는 기본적으로 파일 입출력 또한 입력으로 보기 때문이다. 이는 우리 컴퓨터 시스템에 안좋은 영향을 미칠 수 있는 그런 공격들이 들어 올 수 있다는 점에서 기본적으로 프로그램을 작성 할 때 파일 입출력 또한 보안적으로 굉장히 신경을 써야 되는 부분인 점을 알려준다고 보면 된다.
먼저, 문자열을 선언해주고 FILE *fp; 로 파일 포인터를 하나 만들어 준다. 그 다음에 fopen을 통해 하나의 파일을 열어주고 이제 그 파일에 접근할 수 있는 메모리 주소값을 fp에 담아준 것이다.(fp= fopen(“temp.txt”,”w”);) 그 후, fpritf()를 통해서 이 파일 포인터에 접근해서 거기에다가 하나의 문자열을 쓰도록 해주는 것이다(fprintf(fp,”%s\n”,s);). 마지막으로 fclose(fp)로 파일을 닫아주면 된다.
※ <비주얼 스튜디오에서 기본 실행 파일 경로를 확인하는 방법>
- 프로젝트 이름에 마우스를 대고 우 클릭 ▶ 파일 탐색기에서 폴더 열기
- 그러면 앞선 (예제1)에서 만들어준 text.txt파일에 “Hello World” 라고 쓰여져 있는 것을 확인 할 수 있다.
(예제2) 간단한 학생 정보 시스템 만들기
- 학생들의 이름과 성적 파일 만들기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
typedef struct {
char name[20];
int score;
} Student;
int main(void) {
int n, sum = 0;
FILE* fp;
fp = fopen("input.txt","r");
fscanf(fp,"%d",&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>
#include "main.h"
typedef struct {
char name[20];
int score;
} Student;
int main(void) {
int n, sum = 0;
FILE* fp;
fp = fopen("input.txt","r");
fscanf(fp,"%d",&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;
}
system("pause");
fclose(fp);
printf("점수 평균:%.2f\n", (double)sum / n);
return 0;
}
(해설) 성적 평균을 구하고 메모리 할당 해제
(정리)
1) 파일 입출력을 이용해 데이터를 파일로부터 가져오거나 데이터를 파일로 내보낼 수 있다.
2) 파일 입출력이 끝난 이후에도 반드시 파일 객체를 메모리에서 “할당 해제”해주어야 한다.
'컴퓨터 공부 > © C' 카테고리의 다른 글
[C언어] 14. 구조체 (0) | 2021.02.14 |
---|---|
[C언어] 13. 함수 포인터 (0) | 2021.02.14 |
[C언어] 12. 동적 메모리 할당 (0) | 2021.02.14 |
[C언어] 11. 다차원 배열과 포인터 배열 (0) | 2021.02.14 |
[C언어] 10. 컴퓨터가 변수를 처리하는 방법 (0) | 2021.02.14 |