파일 입출력 2
1) fopen( ... )

-fopen 함수를 이용할 때는 꼭 습관처럼 fclose 를 아래에 먼저 작성하고 그 안에서 프로그래밍을 해야 합니다. 다른 프로그래밍 언어에서도 마찬가지 형태로 프로그래밍 하는 것을 권장드립니다. 이로 인해 발생할 수 있는 여러 가지 잘못된 런타임 오류를 미연에 방지할 수 있기 때문입니다.
2.fclose( ... )

fclose 함수는 nullptr을 파라미터로 받았을 경우(정확히는 올바르지 않은 모든 포인터) 런타임 오류(실행 도중 프로그램이 강제종료가 되는 현상)이 발생합니다. 이런 런타임 오류는 디버그 예외에도 잡히지 않기 때문에 꼭 인지하고 계셔야 합니다. fopen을 이용해 "r" 옵션을 이용해 파일을 열었을 경우, 파일이 없다면 nullptr을 파라미터로 리턴하게 되는데 이 경우에 fclose 함수를 이용해 nullptr을 fclose 할 경우 알 수 없는 오류와 함께 프로그램이 종료되는 경우가 있습니다.
fopen 과 fclose 사이에 항상 코딩을 해야한다. 또한 fclose의 특징은 파일을 열었을 때 파일이 없다면 fclose가 에러가 뜬다. 이를 이용해 파일이 있는지 없는지 알 수 있는 코드를 만들 수 있다.
예제코드)
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
bool file_exists(const char* filename) {
FILE* fp = fopen(filename, "r");
if (fp != nullptr) fclose(fp);
return fp != nullptr;
}
int main() {
bool exists = file_exists("sameple.txt");
if (exists) {
printf("파일이 존재합니다.\n");
}
else {
printf("파일이 존재하지 않습니다.\n");
}
return 0;
}
fprintf 예제코드)
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
bool file_exists(const char* filename) {
FILE* fp = fopen(filename, "r");
if (fp != nullptr) fclose(fp);
return fp != nullptr;
}
int main() {
FILE* outfile = fopen("out.txt", "w");
fprintf(outfile, "%d Hello World %d", 100, 100 );
fclose(outfile);
return 0;
}
fscanf 예제코드)
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
bool file_exists(const char* filename) {
FILE* fp = fopen(filename, "r");
if (fp != nullptr) fclose(fp);
return fp != nullptr;
}
int main() {
FILE* infile = fopen("in.txt", "r");
int data1;
int data2;
fscanf(infile, "%d, %d", &data1, %data2);
return 0;
}

3-1) 많은양의 데이터 한줄씩 읽어오기
3-1-1) fscanf 특성 알기
3-1-2) fgetc()
3-1-3) feof
ex)
while (true) {
char line[256];
fscanf(infile, "%255[^\n]s", line);
fgetc(infile);
if (feof(infile) == 1) break;
}
예제)
예제파일)
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Vivamus vitae aliquam massa. Sed pretium risus a enim suscipit,
ut finibus tortor ultricies. Integer non neque sem.
Nulla imperdiet accumsan sollicitudin. Vestibulum tempus sapien dolor,
ut imperdiet massa tincidunt vel. Quisque dapibus sem ante,
eu tincidunt ipsum vehicula eget. Vestibulum ac maximus massa,
sit amet tincidunt orci. Etiam placerat lacinia volutpat. Integer elit felis,
fringilla porttitor maximus in, gravida sollicitudin eros. Nunc vestibulum,
nulla nec interdum consectetur, ligula augue aliquam nulla, non pretium est
felis id nunc. Aenean accumsan, ex eget sodales hendrerit, justo nunc facilisis est,
a pulvinar diam lacus.
예제코드)
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
bool file_exists(const char* filename) {
FILE* fp = fopen(filename, "r");
if (fp != nullptr) fclose(fp);
return fp != nullptr;
}
int main() {
FILE* infile = fopen("in.txt", "r");
while (true) {
//line 크기 임의 설정
char line[256];
fscanf(infile, "%255[^\n]s", line);
// 파일스트림의 현재 포인터에서 문자 하나를 읽어서
// 리턴해주는 것(쉽게 말하면 다음줄을 읽어오게 하는 코드)
// fscanf는 개행문자 까지만 읽는것 (= fgetc는 개행문자를 읽어서 버려주는 역할을 하는 것)
fgetc(infile);
printf("%s\n", line);
if (feof(infile) == 1) break;
}
fclose(infile);
return 0;
}
연습문제)
sol)
헤더파일)
#ifndef __HEADER_H
#define __HEADER_H
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cmath>
#include <vector>
int getInteger(const char* promt);
std::string getString(const char* prompt);
class Student {
public:
std::string name;
int korean;
int math;
int eng;
Student(std::string name, int korean, int math, int eng);
void printInfo();
};
#endif
소스파일)
#include "Header.h"
int main() {
std::vector<Student> students;
FILE* infile = fopen("students.txt", "r");
while (true) {
if (feof(infile) == 1) break;
char name[100];
int korean;
int math;
int eng;
int result;
result = fscanf(infile, "%99[^\n]s", name);
if (result == -1) break;
fgetc(infile);
result = fscanf(infile, "%d %d %d", &korean, &math, &eng);
if (result == -1) break;
fgetc(infile);
Student s = Student(name, korean, math, eng);
students.push_back(s);
}
fclose(infile);
while(true) {
for (int i = 0; i < students.size(); i++) {
students[i].printInfo();
}
std::string name = getString("학생 이름 : ");
int korean = getInteger("국어점수: ");
int math = getInteger("수학점수 : ");
int eng = getInteger("영어 점수 : ");
Student s = Student(name, korean, math, eng);
students.push_back(s);
FILE* outfile = fopen("students.txt", "w");
for (int i = 0; i < students.size(); i++) {
fprintf(outfile, "%s\n", students[i].name.c_str());
fprintf(outfile, "%d %d %d\n", students[i].korean, students[i].math, students[i].eng);
}
fclose(outfile);
}
return 0;
}
int getInteger(const char* prompt) {
int input;
printf(prompt);
fseek(stdin, 0, SEEK_END);
scanf("%d", &input);
return input;
}
std::string getString(const char* prompt) {
char line[100];
printf(prompt);
fseek(stdin, 0, SEEK_END);
scanf("%99[^\n]s", line);
return line;
}
Student::Student(std::string name, int korean, int math, int eng) {
this->name = name;
this->korean = korean;
this->math = math;
this->eng = eng;
}
void Student::printInfo() {
printf("이름 : / %s 국어 : %d / 수학 : %d / 영어 : %d\n",name.c_str(), korean, math, eng );
}