작업 1: 텍스트 파일을 이용한 도서 정보 관리
이 작업에서는 Book 구조체를 정의하고, 도서 목록을 텍스트 파일에 쓰고 다시 읽어오는 과정을 수행한다. 먼저 배열에 저장된 도서 정보를 fprintf()를 사용해 정형화된 형태로 data1.txt에 기록한다.
#include <stdio.h>
#include <stdlib.h>
#define MAX_LEN 80
#define MAX_BOOKS 100
typedef struct {
char title[MAX_LEN];
char author[MAX_LEN];
} Book;
void save_books_text();
void load_and_print_text();
int main() {
save_books_text();
load_and_print_text();
return 0;
}
void save_books_text() {
Book books[] = {
{"《조각가》", "스콧 맥클라우드"},
{"《등대》", "크리스토프 브루타르"},
{"《제5도살장》", "커트 보니것"},
{"《달을 팔았던 사나이》", "로버트 하인라인"},
{"《대지 위에서》", "로히튼 미스터리"},
{"《학교 가는 길》", "허자오우"},
{"《운명》", "차이충다"}
};
int count = sizeof(books) / sizeof(Book);
FILE *fp = fopen("data1.txt", "w");
if (!fp) {
printf("파일 생성 실패\n");
return;
}
for (int i = 0; i < count; ++i) {
fprintf(fp, "%-20s %-20s\n", books[i].title, books[i].author);
}
fclose(fp);
}
void load_and_print_text() {
Book buffer[MAX_BOOKS];
FILE *fp = fopen("data1.txt", "r");
if (!fp) {
printf("파일 열기 실패\n");
return;
}
int index = 0;
while (fscanf(fp, "%s %s", buffer[index].title, buffer[index].author) == 2) {
++index;
}
for (int i = 0; i < index; ++i) {
printf("%d. %-20s %-20s\n", i + 1, buffer[i].title, buffer[i].author);
}
fclose(fp);
}
작업 2: 이진 파일을 통한 데이터 블록 입출력
구조체 배열 전체를 하나의 데이터 블록으로 간주하여 fwrite()와 fread()를 사용해 이진 파일 data2.dat에 저장하고 복원하는 방식이다. 바이너리 모드("wb", "rb")를 사용하므로 형식 손실 없이 고속 전송이 가능하다.
void save_books_binary();
void read_books_binary();
void save_books_binary() {
Book list[] = {
{"《조각가》", "스콧 맥클라우드"},
{"《등대》", "크리스토프 브루타르"},
{"《제5도살장》", "커트 보니것"},
{"《달을 팔았던 사나이》", "로버트 하인라인"},
{"《대지 위에서》", "로히튼 미스터리"},
{"《학교 가는 길》", "허자오우"},
{"《운명》", "차이충다"}
};
int num = 7;
FILE *fp = fopen("data2.dat", "wb");
if (fp) {
fwrite(list, sizeof(Book), num, fp);
fclose(fp);
}
}
void read_books_binary() {
Book temp[10];
FILE *fp = fopen("data2.dat", "rb");
if (fp) {
size_t items = fread(temp, sizeof(Book), 10, fp);
for (size_t i = 0; i < items; ++i) {
printf("%zu. %-20s %-20s\n", i + 1, temp[i].title, temp[i].author);
}
fclose(fp);
}
}
작업 3: 문자열 단위 입출력 함수 활용
fputs()와 fgets()를 사용해 곡 제목 리스트를 파일에 기록하고, 한 줄씩 읽어 화면에 출력한다. 또한 fgetc()를 통해 문자 단위로 입력받아 전체 내용을 스트리밍 방식으로 출력할 수 있다.
#define MAX_SONGS 5
#define LINE_SIZE 80
void write_songs();
void read_with_fgets();
void read_char_by_char();
void write_songs() {
const char *music[] = {
"Working's Blues",
"Everything Will Flow",
"Streets of London",
"Perfect Day",
"Philadelphia"
};
FILE *fp = fopen("data3.txt", "w");
if (fp) {
for (int i = 0; i < MAX_SONGS; ++i) {
fputs(music[i], fp);
fputc('\n', fp);
}
fclose(fp);
}
}
void read_with_fgets() {
char lines[MAX_SONGS][LINE_SIZE];
FILE *fp = fopen("data3.txt", "r");
if (fp) {
for (int i = 0; i < MAX_SONGS && fgets(lines[i], LINE_SIZE, fp); ++i) {
printf("%d. %s", i + 1, lines[i]);
}
fclose(fp);
}
}
void read_char_by_char() {
FILE *fp = fopen("data3.txt", "r");
int c;
if (fp) {
while ((c = fgetc(fp)) != EOF) {
putchar(c);
}
fclose(fp);
}
}
작업 4: 공백 제외 문자 수 세기
지정된 텍스트 파일에서 공백(space), 탭(tab), 줄바꿈(newline)을 제외한 실제 문자의 개수를 카운트하는 프로그램이다. 각 문자를 순차적으로 읽으며 조건에 맞는 경우에만 카운터를 증가시킨다.
int count_non_whitespace() {
FILE *fp = fopen("data4.txt", "r");
int ch, count = 0;
if (!fp) return -1;
while ((ch = fgetc(fp)) != EOF) {
if (ch != ' ' && ch != '\t' && ch != '\n') {
count++;
}
}
printf("data4.txt의 비공백 문자 수: %d\n", count);
fclose(fp);
return count;
}
작업 5: 시험 결과 처리 및 합격자 추출
응시자 정보를 포함하는 구조체를 정의하고, 점수를 기반으로 합격 여부를 판단한다. 60점 이상인 경우에만 결과 배열에 저장하며, 이를 화면과 파일 list_pass.txt에 동시에 출력한다.
#define MAX_STUDENTS 10
typedef struct {
long id;
char name[20];
float obj_score;
float prac_score;
float total;
char result[10];
} Student;
void load_students(Student[], int);
void compute_results(Student[], int, Student[], int*);
void print_list(const Student[], int);
void save_passed(const Student[], int);
void load_students(Student students[], int n) {
FILE *fin = fopen("examinee.txt", "r");
if (fin) {
for (int i = 0; i < n; ++i) {
fscanf(fin, "%ld %s %f %f", &students[i].id, students[i].name,
&students[i].obj_score, &students[i].prac_score);
}
fclose(fin);
}
}
void compute_results(Student all[], int total, Student passed[], int *pass_count) {
*pass_count = 0;
for (int i = 0; i < total; ++i) {
all[i].total = all[i].obj_score + all[i].prac_score;
if (all[i].total >= 60.0) {
strcpy(all[i].result, "pass");
passed[(*pass_count)++] = all[i];
} else {
strcpy(all[i].result, "fail");
}
}
}
void print_list(const Student list[], int n) {
printf("ID\t\t이름\t객관식\t실기\t총점\t결과\n");
for (int i = 0; i < n; ++i) {
printf("%ld\t%s\t%.2f\t%.2f\t%.2f\t%s\n",
list[i].id, list[i].name, list[i].obj_score,
list[i].prac_score, list[i].total, list[i].result);
}
}
void save_passed(const Student pass[], int n) {
FILE *out = fopen("list_pass.txt", "w");
if (out) {
fprintf(out, "ID\t이름\t객관식\t실기\t총점\t결과\n");
for (int i = 0; i < n; ++i) {
fprintf(out, "%ld\t%s\t%.2f\t%.2f\t%.2f\t%s\n",
pass[i].id, pass[i].name, pass[i].obj_score,
pass[i].prac_score, pass[i].total, pass[i].result);
}
fclose(out);
}
}
작업 6: 무작위 추첨 시스템 구현
참가자 명단을 파일로부터 로드한 후, 난수 생성기를 사용해 5명을 무작위로 추첨하고 그 결과를 화면과 외부 파일 lucky.txt에 기록한다. srand()와 time()을 조합해 매번 다른 시드를 제공한다.
typedef struct {
long id;
char name[N];
char class[N];
} Person;
Person registry[N], winners[5];
void load_participants();
int pick_random_index();
void export_winners();
void load_participants() {
FILE *fp = fopen("list.txt", "r");
int idx = 0;
while (idx < N && fscanf(fp, "%ld %s %s", ®istry[idx].id,
registry[idx].name, registry[idx].class) == 3) {
++idx;
}
fclose(fp);
}
int pick_random_index() {
return rand() % 80;
}
void export_winners() {
FILE *fp = fopen("lucky.txt", "w");
if (fp) {
for (int i = 0; i < 5; ++i) {
fprintf(fp, "%ld\t%s\t%s\n", winners[i].id, winners[i].name, winners[i].class);
}
fclose(fp);
}
}
// 메인 로직
int main() {
load_participants();
srand((unsigned)time(NULL));
for (int i = 0; i < 5; ++i) {
int selected = pick_random_index();
winners[i] = registry[selected];
printf("%ld\t%s\t%s\n", winners[i].id, winners[i].name, winners[i].class);
}
export_winners();
return 0;
}