미니 프로젝트로 마무리
드디어 C언어 커리큘럼의 마지막 시간입니다. 지금까지 변수와 자료형부터 시작해서 조건문, 반복문, 배열, 함수, 포인터, 구조체, 동적 메모리, 파일 입출력, 전처리기, 그리고 지난 시간의 자료구조까지 정말 많은 내용을 다뤄왔습니다. 오늘은 이 모든 개념을 한 곳에 모아서, 실제로 쓸 수 있는 “간단한 학생 성적 관리 프로그램”을 함께 만들어 보겠습니다. 이론 공부를 아무리 많이 해도 직접 손으로 코드를 짜보지 않으면 금방 잊어버리기 마련인데, 이런 작은 프로젝트 하나를 끝까지 완성해보는 경험이 실력을 늘리는 데 훨씬 도움이 됩니다.
어떤 프로그램을 만들까요
오늘 만들 프로그램은 학생 이름과 점수를 구조체로 관리하면서, 동적 메모리로 학생 수만큼 배열을 할당하고, 평균 점수를 계산해서 파일에 저장하는 프로그램입니다. 요구사항을 정리하면 다음과 같습니다.
- 구조체로 학생의 이름과 점수를 묶어서 관리한다.
malloc을 이용해 학생 수만큼 동적으로 배열을 만든다.- 함수로 평균 계산과 출력 로직을 분리한다.
- 최종 결과를 파일(
result.txt)에 저장한다.
이 네 가지만 봐도 지난 시간들에 배운 구조체, 포인터, 함수, 동적 메모리, 파일 입출력이 전부 들어가 있는 셈입니다.
전체 코드 작성하기
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LEN 20
typedef struct {
char name[MAX_NAME_LEN];
int score;
} Student;
double calculateAverage(Student *students, int count) {
int sum = 0;
for (int i = 0; i < count; i++) {
sum += students[i].score;
}
return (double)sum / count;
}
void printReport(Student *students, int count, double average) {
printf("===== 성적 리포트 =====\n");
for (int i = 0; i < count; i++) {
printf("%-10s : %d점\n", students[i].name, students[i].score);
}
printf("-----------------------\n");
printf("평균 점수: %.2f점\n", average);
}
void saveToFile(const char *filename, Student *students, int count, double average) {
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
printf("파일을 열 수 없습니다.\n");
return;
}
fprintf(fp, "===== 성적 리포트 =====\n");
for (int i = 0; i < count; i++) {
fprintf(fp, "%-10s : %d점\n", students[i].name, students[i].score);
}
fprintf(fp, "-----------------------\n");
fprintf(fp, "평균 점수: %.2f점\n", average);
fclose(fp);
}
int main(void) {
int count = 3;
Student *students = (Student *)malloc(sizeof(Student) * count);
if (students == NULL) {
printf("메모리 할당에 실패했습니다.\n");
return 1;
}
strcpy(students[0].name, "민준");
students[0].score = 88;
strcpy(students[1].name, "서연");
students[1].score = 95;
strcpy(students[2].name, "지호");
students[2].score = 76;
double average = calculateAverage(students, count);
printReport(students, count, average);
saveToFile("result.txt", students, count, average);
printf("\n결과가 result.txt 파일에 저장되었습니다.\n");
free(students);
return 0;
}
코드 동작 설명
Student 구조체는 이름과 점수를 한 묶음으로 관리합니다. main 함수에서는 malloc으로 학생 수(count)만큼 Student 배열을 동적으로 할당하는데, 이렇게 하면 학생 수가 나중에 바뀌더라도 코드를 거의 고치지 않고 대응할 수 있습니다. strcpy로 각 학생의 이름을 채우고 점수를 직접 대입한 뒤, calculateAverage 함수에 배열의 포인터와 개수를 넘겨서 평균을 계산합니다. 함수 안에서는 배열을 포인터처럼 인덱스로 접근해서 합계를 구하고, 정수 나눗셈으로 소수점이 날아가지 않도록 (double)로 형변환을 해준 뒤 개수로 나눕니다.
printReport는 화면에 결과를 보여주는 역할만 하고, saveToFile은 똑같은 내용을 fopen, fprintf, fclose를 이용해 파일에 그대로 기록합니다. 화면 출력과 파일 저장 로직을 분리해두면 나중에 둘 중 하나만 바꾸고 싶을 때 훨씬 편합니다. 프로그램이 끝나기 직전에는 free(students)로 동적 할당했던 메모리를 반드시 해제해서 메모리 누수를 막습니다.
실행하면 화면에는 다음과 같이 출력됩니다.
===== 성적 리포트 =====
민준 : 88점
서연 : 95점
지호 : 76점
-----------------------
평균 점수: 86.33점
결과가 result.txt 파일에 저장되었습니다.
그리고 프로그램을 실행한 폴더에 result.txt 파일이 생성되어 동일한 내용이 저장되어 있는 것을 확인할 수 있습니다.
핵심 요약
- 구조체로 서로 관련 있는 데이터(이름, 점수)를 하나의 단위로 묶어서 관리하면 코드가 훨씬 깔끔해집니다.
malloc을 이용한 동적 배열 할당은 데이터 개수가 실행 중에 정해지는 상황에서 유연하게 대응할 수 있게 해줍니다.- 기능을 작은 함수 단위(평균 계산, 화면 출력, 파일 저장)로 나누면 코드를 읽고 수정하기가 훨씬 쉬워집니다.
fopen,fprintf,fclose를 활용하면 프로그램 실행 결과를 파일로 영구히 남길 수 있습니다.- 동적으로 할당한 메모리는 사용이 끝나면 반드시
free로 해제해야 합니다.
이렇게 해서 변수와 자료형이라는 아주 기초적인 내용부터 시작해 구조체, 포인터, 자료구조, 그리고 오늘의 미니 프로젝트까지 C언어의 핵심 흐름을 한 바퀴 돌아봤습니다. 20편에 걸쳐 함께 달려와 주셔서 감사합니다. 여기서 배운 내용을 바탕으로 각자 작은 프로그램들을 직접 만들어보시면서 실력을 계속 다져가시길 바랍니다. C언어 커리큘럼은 이것으로 마무리하지만, 배운 기초는 앞으로 다른 언어나 더 큰 프로젝트를 공부할 때도 든든한 밑거름이 되어줄 것입니다.