C언어 초급 - 14장: 예제 프로젝트 및 실습 (14.2 학생 성적 관리 프로그램)

2025. 2. 25. 15:27프로그래밍 언어/C

14.2 학생 성적 관리 프로그램

구조체와 파일 입출력을 활용하여 학생들의 성적을 관리하는 프로그램을 작성합니다.

프로그램 주요 기능

  1. 학생 정보(이름, 학번, 점수) 입력 및 파일 저장
  2. 저장된 성적을 파일에서 불러와 출력
  3. 학생 정보 추가, 수정, 삭제 기능
  4. 파일을 사용하여 프로그램 종료 후에도 데이터 유지

1. 학생 성적을 관리하기 위한 구조체 정의

학생 정보를 저장하기 위해 구조체(struct) 를 사용합니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 학생 정보를 저장할 구조체 정의
typedef struct {
    char name[30];  // 학생 이름
    int id;         // 학번
    float score;    // 성적
} Student;

#define FILE_NAME "students.dat"  // 학생 데이터 파일명

📌 구조체(struct)를 사용하여 학생 정보를 정의
📌 파일명은 students.dat로 설정하여 프로그램 종료 후에도 데이터 유지


2. 학생 정보 저장 (파일에 쓰기)

학생 정보를 입력받아 파일(students.dat)에 저장하는 기능을 구현합니다.

// 학생 정보 추가 및 파일 저장
void addStudent() {
    FILE *fp = fopen(FILE_NAME, "ab");  // 파일을 추가 모드("ab")로 열기
    if (fp == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return;
    }

    Student s;
    printf("\n학생 이름: ");
    scanf("%s", s.name);
    printf("학번: ");
    scanf("%d", &s.id);
    printf("성적: ");
    scanf("%f", &s.score);

    fwrite(&s, sizeof(Student), 1, fp);  // 구조체 데이터를 파일에 저장
    fclose(fp);

    printf("학생 정보가 저장되었습니다.\n");
}

📌 파일 모드 "ab"(append binary) 사용기존 데이터를 유지하면서 새로운 데이터를 추가
📌 fwrite()를 사용하여 구조체 데이터를 바이너리 형식으로 저장
📌 학생 정보를 입력받아 파일에 추가 저장 가능


3. 저장된 학생 정보 읽기 (파일에서 읽기)

파일(students.dat)에 저장된 학생 정보를 불러와 출력하는 기능을 구현합니다.

// 학생 목록 출력
void viewStudents() {
    FILE *fp = fopen(FILE_NAME, "rb");  // 파일을 읽기 모드("rb")로 열기
    if (fp == NULL) {
        printf("저장된 학생 정보가 없습니다.\n");
        return;
    }

    Student s;
    printf("\n===== 학생 목록 =====\n");

    while (fread(&s, sizeof(Student), 1, fp)) {  // 파일에서 학생 정보 읽기
        printf("이름: %s, 학번: %d, 성적: %.2f\n", s.name, s.id, s.score);
    }

    fclose(fp);
}

📌 파일 모드 "rb"(read binary) 사용파일에서 데이터 읽기
📌 fread()를 사용하여 구조체 데이터를 불러와 출력


4. 학생 정보 수정

특정 학번을 가진 학생의 성적을 수정하는 기능을 추가합니다.

// 학생 성적 수정
void updateStudent() {
    FILE *fp = fopen(FILE_NAME, "rb+");  // 파일을 읽기/쓰기 모드("rb+")로 열기
    if (fp == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return;
    }

    int id, found = 0;
    Student s;
    
    printf("\n수정할 학생의 학번 입력: ");
    scanf("%d", &id);

    while (fread(&s, sizeof(Student), 1, fp)) {  // 파일에서 학생 정보 읽기
        if (s.id == id) {
            printf("현재 성적: %.2f\n", s.score);
            printf("새로운 성적 입력: ");
            scanf("%f", &s.score);

            fseek(fp, -sizeof(Student), SEEK_CUR);  // 파일 포인터를 이전 위치로 이동
            fwrite(&s, sizeof(Student), 1, fp);  // 수정된 데이터 저장
            found = 1;
            break;
        }
    }

    fclose(fp);

    if (found)
        printf("학생 정보가 수정되었습니다.\n");
    else
        printf("학번 %d에 해당하는 학생이 없습니다.\n", id);
}

📌 파일 모드 "rb+"(read & write binary) 사용파일을 읽고 수정 가능
📌 fseek(fp, -sizeof(Student), SEEK_CUR);를 사용하여 위치를 조정한 후 fwrite()로 수정된 데이터를 저장


5. 학생 정보 삭제

특정 학번을 가진 학생의 정보를 파일에서 삭제하는 기능을 추가합니다.

// 학생 정보 삭제
void deleteStudent() {
    FILE *fp = fopen(FILE_NAME, "rb");
    FILE *temp = fopen("temp.dat", "wb");  // 임시 파일 생성
    if (fp == NULL || temp == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return;
    }

    int id, found = 0;
    Student s;

    printf("\n삭제할 학생의 학번 입력: ");
    scanf("%d", &id);

    while (fread(&s, sizeof(Student), 1, fp)) {
        if (s.id == id) {
            found = 1;
            continue;  // 삭제할 학생을 제외하고 복사
        }
        fwrite(&s, sizeof(Student), 1, temp);
    }

    fclose(fp);
    fclose(temp);

    remove(FILE_NAME);  // 기존 파일 삭제
    rename("temp.dat", FILE_NAME);  // 임시 파일을 원본 파일로 변경

    if (found)
        printf("학생 정보가 삭제되었습니다.\n");
    else
        printf("학번 %d에 해당하는 학생이 없습니다.\n", id);
}

📌 삭제할 데이터를 제외하고 새로운 파일(temp.dat)에 저장한 후 기존 파일을 교체
📌 remove(FILE_NAME)로 기존 파일 삭제 후, rename()으로 새로운 파일을 원본 파일로 변경


6. 전체 기능을 포함한 메인 함수

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char name[30];
    int id;
    float score;
} Student;

#define FILE_NAME "students.dat"

void addStudent();
void viewStudents();
void updateStudent();
void deleteStudent();

int main() {
    int choice;

    while (1) {
        printf("\n===== 학생 성적 관리 시스템 =====\n");
        printf("1. 학생 추가\n");
        printf("2. 학생 목록 조회\n");
        printf("3. 학생 성적 수정\n");
        printf("4. 학생 삭제\n");
        printf("5. 종료\n");
        printf("메뉴 선택: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1: addStudent(); break;
            case 2: viewStudents(); break;
            case 3: updateStudent(); break;
            case 4: deleteStudent(); break;
            case 5: printf("프로그램을 종료합니다.\n"); return 0;
            default: printf("잘못된 입력입니다. 다시 입력하세요.\n");
        }
    }
}

📌 반복문을 사용하여 메뉴를 계속 표시하며 사용자가 원하는 작업을 수행
📌 입력값을 기반으로 switch-case 문을 사용하여 적절한 기능을 호출


7. 정리

기능  설명
학생 추가 입력받은 학생 정보를 파일(students.dat)에 저장
학생 목록 조회 파일에서 학생 데이터를 불러와 출력
학생 정보 수정 특정 학번의 성적을 수정
학생 정보 삭제 특정 학번의 학생을 삭제하고 파일 갱신

📌 구조체를 사용하여 학생 정보를 효율적으로 저장 및 관리
📌 파일 입출력을 활용하여 프로그램 종료 후에도 데이터 유지
📌 추가, 수정, 삭제 기능을 포함하여 완전한 학생 성적 관리 시스템 구현