[C언어 소스] 학생 성적 관리 프로그램 (학생 수 입력, 동적 메모리 할당, 파일 입출력)

안녕하세요. 언제나 휴일입니다.

이번 게시글은 학생 성적 관리 프로그램 C언어 소스 코드입니다.

관리할 학생 수는 사용자로부터 입력받습니다. 그리고 학생 데이터를 추가할 때도 동적 메모리 할당 함수를 사용합니다.

제공하는 기능은 학생 추가, 성적 입력, 삭제, 검색, 전체 보기입니다.

프로그램 종료할 때 학생 데이터를 파일에 기록하며 프로그램 시작할 때 파일의 데이터를 로딩합니다.

#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_NAME_LEN	20

enum Subject
{
    KOREAN, ENGLISH, MATH, MAX_SUBJECT
};
const char *stitle[MAX_SUBJECT] = { "국어","영어","수학" };

typedef struct _Student Student;
struct _Student
{
    int num;
    char name[MAX_NAME_LEN];
    int scores[MAX_SUBJECT];
};

#define DEF_FNAME    "data.stu"

int max_student;
Student **stues;

void Init();
void Run();
void Exit();

int getnum();
int main()
{
    Init();
    Run();
    Exit();
    return 0;
}
void Init()
{
    FILE *fp = fopen(DEF_FNAME, "r");
    if (fp)
    {
        int i = 0;
        fread(&max_student, sizeof(int), 1, fp);
        stues = (Student **)malloc(sizeof(Student *)*max_student);
        memset(stues, 0, sizeof(Student *)*max_student);
        while (1)
        {            
            if (fread(&i, sizeof(int), 1, fp) < 1)
            {
                break;
            }
            stues[i] = (Student *)malloc(sizeof(Student));
            fread(stues[i], sizeof(Student), 1, fp);
        }
        fclose(fp);
    }
    else
    {
        printf("최대 관리 학생 수:");
        max_student = getnum();
        stues = (Student **)malloc(sizeof(Student *)*max_student);
        memset(stues,0, sizeof(Student *)*max_student);
    }
}

int SelectMenu();
void AddStudent();
void AddScore();
void RemoveStudent();
void FindStudent();
void ViewAll();
void Run()
{
    int key = 0;
    while ((key = SelectMenu()) != 0)
    {
        switch (key)
        {
        case 1: AddStudent(); break;
        case 2: AddScore(); break;
        case 3: RemoveStudent(); break;
        case 4: FindStudent(); break;
        case 5: ViewAll(); break;
        default: printf("잘못 선택하였습니다.\n"); break;
        }
    }
}

int SelectMenu()
{
    printf("학생 성적 관리 프로그램 0:종료\n");
    printf("1:학생 추가 2:성적 입력 3: 삭제 4: 검색 5: 전체 보기\n");
    return getnum();
}
int getnum()
{
    int num = 0;
    if (scanf_s("%d", &num) == 0)
    {
        char buf[256];
        gets_s(buf, sizeof(buf));
    }
    return num;
}

void InitScore(Student *stu);
void AddStudent()
{
    int num = 0;
    Student *stu = 0;

    printf("추가할 학생 번호(1~%d):", max_student);
    num = getnum();
    if ((num < 1) || (num > max_student))
    {
        printf("범위를 벗어났습니다.\n");
        return;
    }

    stu = stues[num - 1];
    if (stu)
    {
        printf("이미 자료가 있습니다.\n");
        return;
    }
    stu = (Student *)malloc(sizeof(Student));
    stu->num = num;
    printf("이름:");
    scanf_s("%s", stu->name, MAX_NAME_LEN);
    InitScore(stu);
    stues[num - 1] = stu;
}
void InitScore(Student *stu)
{
    int s = 0;
    for (s = 0; s < MAX_SUBJECT; s++)
    {
        stu->scores[s] = -1;
    }
}
void InputScore(Student *stu);
void AddScore()
{
    int num = 0;
    Student *stu = 0;

    printf("성적 입력할 학생 번호(1~%d):", max_student);
    num = getnum();
    if ((num < 1) || (num > max_student))
    {
        printf("범위를 벗어났습니다.\n");
        return;
    }

    stu = stues[num - 1];
    if (stu == 0)
    {
        printf("추가하지 않은 학생 자료입니다. 먼저 학생 자료를 추가하세요.\n");
        return;
    }
    InputScore(stu);
}
void InputScore(Student *stu)
{
    int s = 0;
    int score = 0;
    for (s = 0; s<MAX_SUBJECT; s++)
    {
        printf("%s :", stitle[s]);
        score = getnum();
        if ((score < 0) || (score > 100))
        {
            score = -1;
        }
        stu->scores[s] = score;
    }
}

void RemoveStudent()
{
    int num = 0;
    Student *stu = 0;

    printf("삭제할 학생 번호(1~%d):", max_student);
    num = getnum();
    if ((num < 1) || (num > max_student))
    {
        printf("범위를 벗어났습니다.\n");
        return;
    }

    stu = stues[num - 1];
    if (stu == 0)
    {
        printf("추가하지 않은 학생 자료입니다. 먼저 학생 자료를 추가하세요.\n");
        return;
    }
    free(stu);
    stues[num - 1] = 0;
}

void ViewStudent(Student *stu);
void FindStudent()
{
    int num = 0;
    Student *stu = 0;

    printf("검색할 학생 번호(1~%d):", max_student);
    num = getnum();
    if ((num < 1) || (num > max_student))
    {
        printf("범위를 벗어났습니다.\n");
        return;
    }

    stu = stues[num - 1];
    if (stu == 0)
    {
        printf("추가하지 않은 학생 자료입니다. 먼저 학생 자료를 추가하세요.\n");
        return;
    }
    ViewStudent(stu);
}

void ViewScore(Student *stu);
void ViewStudent(Student *stu)
{
    printf("=== 번호:%d 이름:%s\n", stu->num, stu->name);
    ViewScore(stu);
}
void ViewScore(Student *stu)
{
    int s = 0;
    for (s = 0; s<MAX_SUBJECT; s++)
    {
        if (stu->scores[s] == -1)
        {
            printf("%s : 미입력\n", stitle[s]);
        }
        else
        {
            printf("%s :%d\n", stitle[s], stu->scores[s]);
        }
    }
}

void ViewAll()
{
    int i = 0;
    for (i = 0; i < max_student; i++)
    {
        if (stues[i])
        {
            ViewStudent(stues[i]);
        }
    }
}
void Exit()
{
    FILE *fp = fopen(DEF_FNAME, "w");
    if (fp)
    {
        int i = 0;
        fwrite(&max_student, sizeof(int), 1, fp);
        for (i = 0; i < max_student; i++)
        {
            if (stues[i])
            {
                fwrite(&i, sizeof(int), 1, fp);
                fwrite(stues[i], sizeof(Student), 1, fp);
                free(stues[i]);
            }
        }
        fclose(fp);
    }
    free(stues);
}