C语言课程设计(基于结构体数组的学生成绩管理系统)
in 大学生活C笔记课程设计 with 0 comment

C语言课程设计(基于结构体数组的学生成绩管理系统)

in 大学生活C笔记课程设计 with 0 comment

任务要求

这是学校布置的一个 c 语言课题设计作业,任务要求如下:
用一个结构体数组存放5个学生3门课的成绩。要求建立5个子函数分别实现题目的5步。

  1. 输入5个学生3门课的成绩存入结构体数组中;
  2. 输出学生信息;
  3. 求每个学生的平均分;
  4. 按平均分从高到低排列;
  5. 按平均分求每个学生的名次。
    要求:用结构体数组存放学生信息,每个功能都用函数实现。

报告书可能用得到的

前言

在考试后老师通常有记录学生成绩、计算学生平均分并按照平均分给学生排名次的需求,对于学生来说也需要查看自己的平均分排名综合估计自己在班上的水平,进而改善学习方法和态度,努力取得更好的成绩。我们组发现现在大多数老师还在采用笔纸手工统计学生成绩后使用计算器把学生成绩相加,继而得出平均分,然后还要手工排名,非常的麻烦,因此我们小组准备使用c语言编写一个基于结构体的学生成绩管理系统,方便老师和同学们。

分析和设计

该课题要求使用结构体来保存学生相关成绩,并没有要求操作文件,因此不考虑文件存储问题。
我组用一个结构体存储姓名、三科科目、三科成绩、平均。
全系统共采用13个函数(包含1个main()函数、2个修饰函数、5个辅助函数、5个功能函数组成)。
对于任务1,我组使用scanf() 函数和for循环将用户输入的信息存储在struct StuGrade结构体中。
对于任务2,我组自定义了一个PrintData() 函数用以减少重复代码,规范输出格式。
对于任务3,我组自定义了一个CalTheAveScore() 函数用以计算学生平均分,并使用NoSortTheAveScore() 函数输出未经排序的平均分。
对于任务4,我组自定义了一个SortTheAveScore() 函数用冒泡排序排序学生平均分,并用TheAveScore() 函数输出排序后的平均分。
对于任务5,我组调用上述CalTheAveScore() 函数和SortTheAveScore() 函数后,在输出语句中添加一个变量i,用以输出当前输出的次数(实际上等于学生平均分排名)。

课程设计体会

本课题涉及结构体相关知识,我在校学习时恰好对于这一节并没有完全掌握,因此选择此课题来挑战和提升自己。经过不断的翻阅资料和询问大佬,终于按时按质完成了课题设计的程序,在完成过程中不但加深了我对结构体的认识,也促进了同学间的交流和友谊,一举多得。当然,过程不是一帆风顺的,对于函数的返回值、函数的概念、结构体和多维数组的选用等多方面遇到了不少问题,好在一一解决。总的来说,本次课题设计对我来说有莫大的帮助和提升。
对于程序,存在以下优点和缺点:

优点:

  1. 本课题采用结构体数组存储学生成绩,可以降低编码复杂度,比使用二维数组更加理想。
  2. 在添加学生成绩之前加入一个操作确认函数,避免手滑误点进学生成绩录入模块。
  3. 学生成绩录入模块系统提示更改颜色,方便区分,提升视觉效果。
  4. 变量名、函数名均采用标准命名法,方便理解。

缺点:

  1. 没有实现文件存储,关闭程序即丢失数据。
  2. 程序过于冗长,还应该可以精简代码。

源码及程序

移动端可能显示异常(显示不全),请使用电脑版访问
或移步 GitHub:传送门

#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include <windows.h>
#include <ctype.h>

#define N 20

/*
 * 函数列表
 * void Run(void);                         进入系统函数(装饰用)
 * void Color(short x);                    字体颜色函数(装饰用)
 * void MakeSure(void);                    操作确认函数
 * void PrintData(SG sg);                  数据流输出函数
 * void SortStuName(void);                 姓名排序函数
 * void SortTheAveScore(void);             平均分排序函数
 * void CalTheAveScore(void);              平均分计算函数
 * int MainMenu(void);                     主菜单模块
 * void AddStuGrade(void);                 录入学生成绩模块
 * void ShowStuGrade(void);                浏览学生成绩模块
 * void NoSortTheAveScore(void);           没有排序的平均分输出模块
 * void TheAveScore(void);                 有排序的平均分输出模块
 * void StuGradeRank(void);                带名次的平均分输出模块
*/

typedef struct StuGrade {
    char name[N];     //学生姓名
    char sub[3][N];      //科目
    int score[3];       //成绩
    double avg;            //平均分
} SG;
SG sg[N];

void Run(void);

void Color(short x);

void MakeSure(void);

void PrintData(SG sg);

void SortStuName(void);

void SortTheAveScore(void);

void CalTheAveScore(void);

int MainMenu(void);

void AddStuGrade(void);

void ShowStuGrade(void);

void NoSortTheAveScore(void);

void TheAveScore(void);

void StuGradeRank(void);

void Run(void){
    printf("学生成绩管理系统正在启动中……\n");
    char arr[102] = {'\0'};
    int n = 100, i = 0;
    while (i <= n){
        arr[i] = '=';
        printf("[%1s]\r%d%% ", arr, i);
        i++;
        Sleep(10);
    }
    printf("\n");
    MainMenu();
}

void Color(short x) //自定义函根据参数改变颜色
{
    if (x >= 0 && x <= 15)//参数在0-15的范围颜色
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);    //只有一个参数,改变字体颜色
    else//默认的颜色白色
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}

//防止不小心点入学生成绩录入模块,加入一个确认模块
void MakeSure(void) {
    printf("确认开始录入学生成绩请按下【Y】,返回主菜单请按下【N】\n");
    int choiceIn;
    do
        choiceIn = getch();
    while ((choiceIn = toupper(choiceIn)) != 'Y' && choiceIn != 'N');
    choiceIn == 'Y' ? AddStuGrade() : MainMenu();
}

//这里的变量“sg”会覆盖全局变量“sg”,不影响程序运行,要分清调用
void PrintData(SG sg) {
    printf("学生姓名:%5s\n", sg.name);
    for (int j = 0; j < 3; ++j) {
        printf("科目:%8s 成绩:%6d\n", sg.sub[j], sg.score[j]);
    }
    printf("\n");
}

void SortStuName(void) {
    SG TempSG;

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N - i - 1; j++) {
            if (strcmp(sg[j].name, sg[j + 1].name) > 0) {
                TempSG = sg[j];
                sg[j] = sg[j + 1];
                sg[j + 1] = TempSG;
            }
        }
    }
}

void SortTheAveScore(void){
    SG TempSg;

    for (int i = 0; i < N - 1; ++i) {
        for (int j = 0; j < N - i; ++j) {
            if (sg[j].avg < sg[j + 1].avg) {
                TempSg = sg[j];
                sg[j] = sg[j + 1];
                sg[j + 1] = TempSg;
            }
        }
    }
}

void CalTheAveScore(void) {
    int sum = 0;

    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < 3; ++j) {
            sum += sg[i].score[j];
            sg[i].avg = sum / 3.0;
        }
        sum = 0;
    }
}

int MainMenu(void) {
    while (1) {
        system("cls");
        int MainMenuButton;

        printf("---功能菜单---\n");
        printf("1.录入学生成绩\n");
        printf("2.浏览学生成绩\n");
        printf("3.查看学生成绩平均分\n");
        printf("4.排序学生成绩\n");
        printf("5.带排名排序学生成绩\n");
        printf("6.退出管理系统\n");
        printf("-------------\n");
        printf("请选择:\n");

        MainMenuButton = getch() - '0';
        system("cls");
        if (MainMenuButton == 0) break;
        else {
            switch (MainMenuButton) {
                case 1:
                    MakeSure();
                    break;
                case 2:
                    ShowStuGrade();
                    break;
                case 3:
                    NoSortTheAveScore();
                    break;
                case 4:
                    TheAveScore();
                    break;
                case 5:
                    StuGradeRank();
                    break;
                case 6:
                    exit(1);
                default:
                    printf("请输入0-5之间的数字!\n");
                    system("pause");
                    break;
            }
        }
    }
}

void AddStuGrade(void) {
    for (int i = 0; i < 10; ++i) {
        system("cls");
        printf("请输入学生姓名:\n");
        scanf("%s", sg[i].name);
        printf("\n");
        for (int j = 0; j < 3; j++) {
            printf("请输入科目 %d:\n", j + 1);
            scanf("%s", sg[i].sub[j]);
            printf("请输入科目 %d 的成绩:\n", j + 1);
            scanf("%d", &sg[i].score[j]);
            printf("\n");
            Color(1);
            printf("系统:第 %d 条信息已录入\n\n", j + 1);
            Color(15);
        }
        printf("输入【Y】以继续录入,输入【N】返回主菜单\n");
        int choiceIn;
        do
            choiceIn = getch();
        while ((choiceIn = toupper(choiceIn)) != 'Y' && choiceIn != 'N');
        choiceIn == 'Y' ? i = i : MainMenu();
    }
}

void ShowStuGrade(void) {
    system("cls");

    SortStuName();
    printf("查询到的结果为:\n");
    for (int i = 0; i < N; ++i) {
        if (0 < strlen(sg[i].name)) {
            PrintData(sg[i]);
        }
    }
    printf("\n");
    printf("请按下【任意按键】返回主菜单……");
    if (getch()) MainMenu();
}

void NoSortTheAveScore(void) {
    system("cls");

    CalTheAveScore();
    printf("查询到的结果为:\n");
    for (int i = 0; i < N; ++i) {
        if (0 < strlen(sg[i].name)) {
            printf("%5s 的平均成绩:%.2lf\n", sg[i].name, sg[i].avg);
        }
    }
    printf("\n");
    printf("请按下【任意按键】返回主菜单……");
    if (getch()) MainMenu();
}

void TheAveScore(void) {
    system("cls");

    CalTheAveScore();
    SortTheAveScore();

    printf("查询到的结果为:\n");
    for (int i = 0; i < N; ++i) {
        if (0 < strlen(sg[i].name)) {
            printf("%5s 的平均成绩:%.2lf\n", sg[i].name, sg[i].avg);
        }
    }
    printf("\n");
    printf("请按下【任意按键】返回主菜单……");
    if (getch()) MainMenu();
}

void StuGradeRank(void) {
    system("cls");
    SG TempSg;

    CalTheAveScore();
    SortTheAveScore();

    printf("查询到的结果为:\n");
    for (int i = 0; i < N; ++i) {
        if (0 < strlen(sg[i].name)) {
            printf("%5s 的平均成绩:%10.2lf 名次:%5d\n", sg[i].name, sg[i].avg, i + 1);
        }
    }
    printf("\n");
    printf("请按下【任意按键】返回主菜单……");
    if (getch()) MainMenu();
}

int main(void) {
    Run();
    return -1;
}
本文写作于 1年前,文章内容可能已经与事实不符,如有疑问,请咨询作者。

留言: