작성
·
41
1
#define CRTSECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define SLEN 101
struct book
{
char name[SLEN];
char author[SLEN];
};
void print_books(const struct book* books, int n);
void write_books(const char* filename, const struct book* books, int n);
struct book* read_books(const char* filename, int* n);
int main()
{
int temp;
int n = 3;
struct book* my_books = (struct book*)malloc(sizeof(struct book) * n);
if (!my_books) {
printf("Malloc failed");
exit(1);
}
my_books[0] = (struct book){ "The Great Gatsby", "F. Scott Fitzgerald" };
my_books[1] = (struct book){ "Hamlet", "William Shakespeare" };
my_books[2] = (struct book){ "The Odyssey", "Homer" };
print_books(my_books, n);
printf("\nWriting to a file.\n");
write_books("books.txt", my_books, n);
free(my_books);
n = 0;
printf("Done.\n");
printf("\nPress any key to read data from a file.\n\n");
temp = _getch();
my_books = read_books("books.txt", &n);
print_books(my_books, n);
free(my_books);
n = 0;
return 0;
}
void print_books(const struct book* books, int n)
{
for (int i = 0; i < n; ++i)
{
printf("Book %d : \"%s\" written by \"%s\"\n", i + 1, books[i].name, books[i].author);
}
}
void write_books(const char* filename, const struct book* books, int n)
{
FILE* fw;
if ((fw = fopen(filename, "w")) == NULL)
{
fprintf(stderr, "Can't open \"%s\" file.\n", filename);
exit(EXIT_FAILURE);
}
fwrite(books, sizeof(struct book), n, fw);
fclose(fw);
}
struct book* read_books(const char* filename, int* n)
{
FILE* fp;
if ((fp = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Can't open \"%s\" file.\n", filename);
exit(EXIT_FAILURE);
}
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
rewind(fp);
struct book* all_books;
int si = file_size / sizeof(struct book);
*n = si;
all_books = (struct book*)malloc(sizeof(struct book) (n));
if (all_books == NULL)
{
printf("Failed");
return NULL;
}
fread(all_books, sizeof(struct book), *n, fp);
fclose(fp);
return all_books;
}
예제를 풀다보니 바이너리형식으로 추가,저장되는 코드로 만들어 버렸는데 이 경우에는 메모장에서 텍스트를 추가할 수 없으니 틀렸다고 보는게 맞겠죠?
답변 1
0
안녕하세요? 질문&답변 도우미 durams입니다.
바이너리 형식이라는 개념에 대해 오해가 있으신 것 같습니다. 텍스트 파일도 결국 컴퓨터에 저장되는 값들은 이진 값들이며, 텍스트 파일 뷰어 프로그램(예 : 메모장)으로 보는 경우 이를 인코딩하여 사람이 인식할 수 있는 문자열 형태로 보인다는 것을 이해하셔야 합니다.
또한 바이너리 형식과 바이너리 모드로 파일을 여는 것은 다르게 보아야 합니다.
바이너리 형식 : 파일에 데이터가 저장된 방식.
바이너리 모드로 파일을 여는 것 : fopen
으로 파일을 열 때, mode에 "b"
를 지정하는 것.
바이너리 형식으로 추가/저장되는 코드를 작성했다고 하셨지만, 제시해주신 코드를 보면 fopen
에서 바이너리 모드를 사용하지는 않으며, 강의에서 제시한 정답 코드와의 주된 차이점은 입출력 함수로 fprintf
/fscanf
를 사용한 것 대신에 fwrite
/fread
를 사용했다는 점입니다. fprintf
와 fscanf
는 문자열에 대해 동작하도록 설계된 함수이기 때문에 개행 문자에 대한 처리가 자동으로 이루어지지만, fwrite
와 fread
는 그렇지 않습니다.
바이너리 모드로 열고 fwrite
와 fread
로 입출력을 진행하더라도, 메모장에서 얼마든지 읽기/쓰기가 가능합니다. 위 코드를 실행했을 때 제대로 동작하지 않았던 이유는 개행 문자에 대한 고려가 없었기 때문입니다.
프로그램이 제대로 동작하도록 충분히 고민하며 현 코드를 수정해보시고, 그래도 잘 모르겠다면 다시 질문주세요.