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

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

이번 게시글은 학생 성적 관리 프로그램입니다.

학생 50명의 데이터를 관리할 수 있고 학생 데이터를 추가할 때 동적 메모리 할당 함수를 이용하여 메모리를 할당받습니다.

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

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

#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.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"

#define MAX_STUDENT	50
Student *stues[MAX_STUDENT];

void Init();
void Run();
void Exit();
int main()
{
    Init();
    Run();
    Exit();
    return 0;
}
void Init()
{
    FILE *fp = fopen(DEF_FNAME, "r");
    if (fp)
    {
        int i = 0;
        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);
    }
}

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 getnum();
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;
        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);
    }
}