美文网首页
C语言实现简单的学生成绩管理系统

C语言实现简单的学生成绩管理系统

作者: miki2miki | 来源:发表于2020-06-22 08:53 被阅读0次

  最近在问答上帮提问者回答问题,有遇到求C语言实现学生管理成绩系统,需求非常简单,就顺手码了下代码。我觉得这种比较小的系统,可以收录起来,做一个C语言基础学习目录也是不错的主意。
  因为当时的问题已经找不到了,我就回想着把问题的大致说一下。

一 题目

  简单实现一个学生成绩系统,一个学生包含学号,姓名,年龄,数学成绩,计算机成绩,总成绩六项信息,学号唯一,姓名可以重名。
  数据格式如下:

学号 姓名 年龄 数学 计算机 总分
int char[20] int int int int

  需实现以下功能:
    (1) 添加学生信息
    (2) 浏览学生信息
    (3) 查询学生信息
    (4) 删除学生信息
    (5) 按总分排序
    (6) 退出系统
  使用过程需要有简单的描述性语句,便于操作者使用。

总体来说,回忆题目大致是如此,不影响对后续代码的实现和阅读。

二 设计

1.单个学生信息

  这个就按照数据格式表格要求来即可,使用C语言结构体定义学生信息,C语言中的结构体可以存储复杂的数据。

typedef struct Student{
    int id; //学号
    char name[20]; //名字
    int age;        //年龄
    int math;       //数学成绩
    int computer;   //计算机成绩
    int total;      //总分
}Stu;
2.存放学生信息

  因为不知道有多少学生信息,而且学生信息支持增删改查,这里采用单链表的形式来存放学生数据,以下是链表的数据结构

typedef struct StudentData{
    Stu student;
    struct StudentData * next;
}StuData, *PStuData;
3.定义布尔型数据

  将是和否值1,0定义为宏,对一些常用的数值定义为宏,不失为一个好的编码习惯。这个是给后面判断语句和循环语句使用。

//定义布尔
#define TRUE 1
#define FALSE 0
typedef short BOOL;
4.函数设计
//选择主菜单
int EnterMainMenu();

//申请数据内存
PStuData GetPStuData();

//释放数据内存
void FreePStuData(PStuData pData);

//添加学生
void AddStudent(PStuData pHead);

//删除学生
void RemoveStudent(PStuData pHead);

//浏览学生信息
void DisplayStudents(PStuData pHead);

//查询学生信息
void QueryStudent(PStuData pHead);

//排序并显示
void SortStudents(PStuData pHead);

//Student数据复制
void CopyStudent(Stu * st1, Stu * st2);

//返回主菜单
void BackMain();

//清屏操作
void ClearScreen();

//清空输入缓冲
void ClearStdin();

后面会着重说明和实现这些函数的作用和功能

三 代码实现

1.主菜单选择

  使用puts输出字符串打印菜单信息,通过scanf接收屏幕上输入的选择信息。getchar函数是接收一个字符,在scanf使用中换行代表输入结束,但是这个换行会停留在输入缓存区里面,这里接收掉是为了不干扰后续的输入和显示。

int EnterMainMenu(){
    int menu;
    //打印菜单
    puts("请选择系统功能(按对应数字,回车执行)");
    puts("(1) 添加学生信息");
    puts("(2) 浏览学生信息");
    puts("(3) 查询学生信息");
    puts("(4) 删除学生信息");
    puts("(5) 按总分排序");
    puts("(6) 退出系统");

    scanf("%d", &menu);
    //接收多余的回车键
    getchar();
    return menu;
}
2.返回主菜单

  封装函数功能,getchar()函数获取一个任意字符,返回主菜单。

void BackMain(){
    ClearStdin();//清理输入缓存区,后续展示该函数功能
    printf("输入任何字符返回主菜单");
    getchar();
    ClearScreen();//清理屏幕信息,后续展示该函数功能
}
3.主函数main实现

  使用switch(开关语句)对菜单输入进行控制流程。

int main(){
    int menu;
    BOOL doing = TRUE;
    PStuData pData = NULL;

    pData = GetPStuData();//申请数据内存,后续会解释此函数
    if(pData == NULL){
        doing = FALSE;
    }

    while(doing){

        menu = EnterMainMenu();
        switch(menu){
            case 1:
                AddStudent(pData);
                break;
            case 2:
                DisplayStudents(pData);
                break;
            case 3:
                QueryStudent(pData);
                break;
            case 4:
                RemoveStudent(pData);
                break;
            case 5:
                SortStudents(pData);
                break;
            case 6:
                doing = FALSE;
                puts("退出系统");
                break;
            default:
                puts("输入错误!");
                break;
        }

    }
    return 0;
}
4.内存申请和释放

  因为不知道具体学生信息的数量,而且还需要支持增、删功能。那么我们就需要动态的分配内存来存储学生信息数据, 使用stdlib.h库中的malloc函数动态申请内存和free函数释放内存。

PStuData GetPStuData(){
    PStuData pData = NULL;
    pData = (PStuData)malloc(sizeof(StuData));
    if(pData){
        pData->next = NULL;
    }
    return pData;
}

void FreePStuData(PStuData pData){
    if(pData != NULL){
        free(pData);
    }
}
5.添加学生信息

  获取屏幕录入的学生信息,按学号升序添加到学生信息单链表中。

void AddStudent(PStuData pHead){
    BOOL bUpdate = FALSE;
    int id, age, math, computer;
    char name[20];
    char loop[20];
    PStuData pVisit = NULL;
    PStuData pLast = NULL;
    PStuData pNew = NULL;


    ClearScreen();//清屏,后续展示该函数功能

    puts("===录入学生信息===");

    printf("请输入学生学号:");
    scanf("%d", &id);

    printf("请输入学生姓名:");
    scanf("%s", name);

    printf("请输入学生年龄:");
    scanf("%d", &age);

    printf("请输入学生数学成绩:");
    scanf("%d", &math);

    printf("请输入学生计算机成绩:");
    scanf("%d", &computer);

    pNew = GetPStuData();
    if(!pNew){
        puts("内存空间不足,无法添加学生信息");
        BackMain();
        return;
    }

    pNew->student.id = id;
    strcpy(pNew->student.name, name);
    pNew->student.age = age;
    pNew->student.math = math;
    pNew->student.computer = computer;
    pNew->student.total = math + computer;

    pVisit = pHead->next;
    pLast = NULL;
    while(pVisit){
        //仅更新数据
        if(pVisit->student.id == id){
            CopyStudent(&pVisit->student, &pNew->student);//封装,相当于student的数据赋值
            //清理申请的内存
            FreePStuData(pNew);
            bUpdate = TRUE;
            break;
        }
        if(pVisit->student.id > id){
            break;
        }
        pLast = pVisit;
        pVisit = pLast->next;
    }

    //找到插入节点
    if(pLast){
        pNew->next = pLast->next;
        pLast->next = pNew;
    }
    else if(!bUpdate){//添加的首个元素
        pHead->next = pNew;
    }

    if(bUpdate){
        puts("更新学生信息完成");
    }
    else{
        puts("添加学生信息完成");
    }

    //清理
    pNew = NULL;
    pVisit = NULL;
    bUpdate = FALSE;
    
    BackMain();
}
6.学生信息拷贝赋值

  封装函数功能,拷贝赋值学生信息,其中学生名字不能直接赋值,需要string.h库中的strcpy函数进行操作。

void CopyStudent(Stu * st1, Stu * st2){
    st1->id = st2->id;
    strcpy(st1->name, st2->name);//字符串不能直接赋值,需要string.h库中的strcpy函数进行操作
    st1->age = st2->age;
    st1->math = st2->math;
    st1->computer = st2->computer;
    st1->total = st2->total;
}
7.查询学生信息

  获取录入的学号,顺序迭代访问单链表,查询显示该学号的学生信息。

void QueryStudent(PStuData pHead){
    PStuData pVisit = NULL;
    int id;

    ClearScreen();//清屏,后续展示该函数功能
    printf("请输入要查询学生信息的学号:");
    scanf("%d", &id);

    pVisit = pHead->next;
    while(pVisit){
        if(pVisit->student.id ==  id){
            printf("查询信息 学号:%d 姓名:%s 年龄:%d 数学:%d 计算机:%d 总分:%d\n", 
                pVisit->student.id, pVisit->student.name, pVisit->student.age, pVisit->student.math,
                pVisit->student.computer, pVisit->student.total);
            break;
        }
        pVisit = pVisit->next;
    }
    
    if(!pVisit){
        printf("查询id无效");
    }
    
    BackMain();
}
8.展示学生信息

   顺序迭代访问单链表,显示所有学生信息。

void DisplayStudents(PStuData pHead){
    PStuData pData = NULL;
    ClearScreen();//清屏,后续展示该函数
    if(pHead){
        pData = pHead->next;
    }

    if(!pData){
        puts("没有学生数据信息");
    }
    else{
        printf("%-10s| %-20s| %-5s| %-5s| %-6s| %-5s|\n", "学号", "姓名", "年龄", "数学", "计算机", "总分");
    }


    while(pData){
        printf("%-10d| %-20s| %-5d| %-5d| %-6d| %-5d|\n", pData->student.id, pData->student.name, 
            pData->student.age, pData->student.math, pData->student.computer, pData->student.total);
        pData = pData->next;
    }

    BackMain();
}
9.删除学生信息

  获取输入学号,删除单链表中匹配的学生信息。

void RemoveStudent(PStuData pHead){
    PStuData pVisit = NULL;
    PStuData pLast = NULL;
    int id;

    ClearScreen();//清屏
    printf("请输入要删除学生信息的学号:");
    scanf("%d", &id);

    pVisit = pHead->next;
    pLast = pHead;
    while(pVisit){
        if(pVisit->student.id == id){
            break;
        }
        pLast = pVisit;
        pVisit = pLast->next;
    }

    if(pVisit){
        pLast->next = pVisit->next;
        FreePStuData(pVisit);
        printf("删除学号为%d的信息成功\n", id);
    }
    else{
        printf("删除学号为%d的信息失败,学生不存在\n", id);
    }
    
    BackMain();
}
10.升序排序学生总成绩并显示出来

  这里的做法是创建新的单链表,使用插入法排序。

void SortStudents(PStuData pHead){
    PStuData pVisit = NULL;
    PStuData pSortHead = NULL;
    PStuData pSortVisit = NULL;
    PStuData pSortLast = NULL;
    PStuData pNew = NULL;

    pVisit = pHead->next;
    pSortHead = GetPStuData();

    while(pVisit){
        pSortVisit = pSortHead->next;
        pSortLast = pSortHead;
        while(pSortVisit){
            if(pSortVisit->student.total >= pVisit->student.total){
                break;
            }
            pSortLast = pSortVisit;
            pSortVisit = pSortVisit->next;
        }

        pNew = GetPStuData();
        CopyStudent(&pNew->student, &pVisit->student);
        pNew->next = pSortVisit;
        pSortLast->next = pNew;
        pVisit = pVisit->next;
    }
    DisplayStudents(pSortHead);
    pSortVisit = NULL;
    while(pSortHead){
        pSortVisit = pSortHead->next;
        FreePStuData(pSortHead);
        pSortHead = pSortVisit;
    }

}
11.其他函数
void ClearScreen(){
    system("cls");
}

void ClearStdin(){
    setbuf(stdin, NULL);
}

四 整体代码

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

//定义布尔
#define TRUE 1
#define FALSE 0
typedef short BOOL;

//学生数据
typedef struct Student{
    int id; //学号
    char name[20]; //名字
    int age;        //年龄
    int math;       //数学成绩
    int computer;   //计算机成绩
    int total;      //总分
}Stu;

typedef struct StudentData{
    Stu student;
    struct StudentData * next;
}StuData, *PStuData;

//选择主菜单
int EnterMainMenu();

//申请数据内存
PStuData GetPStuData();

//释放数据内存
void FreePStuData(PStuData pData);

//添加学生
void AddStudent(PStuData pHead);

//删除学生
void RemoveStudent(PStuData pHead);

//浏览学生信息
void DisplayStudents(PStuData pHead);

//查询学生信息
void QueryStudent(PStuData pHead);

//排序并显示
void SortStudents(PStuData pHead);

//Student数据复制
void CopyStudent(Stu * st1, Stu * st2);

//返回主菜单
void BackMain();

//清屏操作
void ClearScreen();

//清空输入缓冲
void ClearStdin();

int main(){
    int menu;
    BOOL doing = TRUE;
    PStuData pData = NULL;

    pData = GetPStuData();
    if(pData == NULL){
        doing = FALSE;
    }

    while(doing){

        menu = EnterMainMenu();
        switch(menu){
            case 1:
                AddStudent(pData);
                break;
            case 2:
                DisplayStudents(pData);
                break;
            case 3:
                QueryStudent(pData);
                break;
            case 4:
                RemoveStudent(pData);
                break;
            case 5:
                SortStudents(pData);
                break;
            case 6:
                doing = FALSE;
                puts("退出系统");
                break;
            default:
                puts("输入错误!");
                break;
        }

    }
    return 0;
}

PStuData GetPStuData(){
    PStuData pData = NULL;
    pData = (PStuData)malloc(sizeof(StuData));
    if(pData){
        pData->next = NULL;
    }
    return pData;
}

void FreePStuData(PStuData pData){
    if(pData != NULL){
        free(pData);
    }
}

int EnterMainMenu(){
    int menu;
    //打印菜单
    puts("请选择系统功能(按对应数字,回车执行)");
    puts("(1) 添加学生信息");
    puts("(2) 浏览学生信息");
    puts("(3) 查询学生信息");
    puts("(4) 删除学生信息");
    puts("(5) 按总分排序");
    puts("(6) 退出系统");

    scanf("%d", &menu);
    //接收多余的回车键
    getchar();
    return menu;
}

void AddStudent(PStuData pHead){
    BOOL bUpdate = FALSE;
    int id, age, math, computer;
    char name[20];
    char loop[20];
    PStuData pVisit = NULL;
    PStuData pLast = NULL;
    PStuData pNew = NULL;


    ClearScreen();

    puts("===录入学生信息===");

    printf("请输入学生学号:");
    scanf("%d", &id);

    printf("请输入学生姓名:");
    scanf("%s", name);

    printf("请输入学生年龄:");
    scanf("%d", &age);

    printf("请输入学生数学成绩:");
    scanf("%d", &math);

    printf("请输入学生计算机成绩:");
    scanf("%d", &computer);

    pNew = GetPStuData();
    if(!pNew){
        puts("内存空间不足,无法添加学生信息");
        BackMain();
        return;
    }

    pNew->student.id = id;
    strcpy(pNew->student.name, name);
    pNew->student.age = age;
    pNew->student.math = math;
    pNew->student.computer = computer;
    pNew->student.total = math + computer;

    pVisit = pHead->next;
    pLast = NULL;
    while(pVisit){
        //仅更新数据
        if(pVisit->student.id == id){
            CopyStudent(&pVisit->student, &pNew->student);
            //清理申请的内存
            FreePStuData(pNew);
            bUpdate = TRUE;
            break;
        }
        if(pVisit->student.id > id){
            break;
        }
        pLast = pVisit;
        pVisit = pLast->next;
    }

    //找到插入节点
    if(pLast){
        pNew->next = pLast->next;
        pLast->next = pNew;
    }
    else if(!bUpdate){//添加的首个元素
        pHead->next = pNew;
    }

    if(bUpdate){
        puts("更新学生信息完成");
    }
    else{
        puts("添加学生信息完成");
    }

    //清理
    pNew = NULL;
    pVisit = NULL;
    bUpdate = FALSE;
    
    BackMain();
}

void DisplayStudents(PStuData pHead){
    PStuData pData = NULL;
    ClearScreen();
    if(pHead){
        pData = pHead->next;
    }

    if(!pData){
        puts("没有学生数据信息");
    }
    else{
        printf("%-10s| %-20s| %-5s| %-5s| %-6s| %-5s|\n", "学号", "姓名", "年龄", "数学", "计算机", "总分");
    }


    while(pData){
        printf("%-10d| %-20s| %-5d| %-5d| %-6d| %-5d|\n", pData->student.id, pData->student.name, 
            pData->student.age, pData->student.math, pData->student.computer, pData->student.total);
        pData = pData->next;
    }

    BackMain();
}

void QueryStudent(PStuData pHead){
    PStuData pVisit = NULL;
    int id;

    ClearScreen();
    printf("请输入要查询学生信息的学号:");
    scanf("%d", &id);

    pVisit = pHead->next;
    while(pVisit){
        if(pVisit->student.id ==  id){
            printf("查询信息 学号:%d 姓名:%s 年龄:%d 数学:%d 计算机:%d 总分:%d\n", 
                pVisit->student.id, pVisit->student.name, pVisit->student.age, pVisit->student.math,
                pVisit->student.computer, pVisit->student.total);
            break;
        }
        pVisit = pVisit->next;
    }
    
    if(!pVisit){
        printf("查询id无效");
    }
    
    BackMain();
}

void RemoveStudent(PStuData pHead){
    PStuData pVisit = NULL;
    PStuData pLast = NULL;
    int id;

    ClearScreen();
    printf("请输入要删除学生信息的学号:");
    scanf("%d", &id);

    pVisit = pHead->next;
    pLast = pHead;
    while(pVisit){
        if(pVisit->student.id == id){
            break;
        }
        pLast = pVisit;
        pVisit = pLast->next;
    }

    if(pVisit){
        pLast->next = pVisit->next;
        FreePStuData(pVisit);
        printf("删除学号为%d的信息成功\n", id);
    }
    else{
        printf("删除学号为%d的信息失败,学生不存在\n", id);
    }
    
    BackMain();
}

void SortStudents(PStuData pHead){
    PStuData pVisit = NULL;
    PStuData pSortHead = NULL;
    PStuData pSortVisit = NULL;
    PStuData pSortLast = NULL;
    PStuData pNew = NULL;

    pVisit = pHead->next;
    pSortHead = GetPStuData();

    while(pVisit){
        pSortVisit = pSortHead->next;
        pSortLast = pSortHead;
        while(pSortVisit){
            if(pSortVisit->student.total >= pVisit->student.total){
                break;
            }
            pSortLast = pSortVisit;
            pSortVisit = pSortVisit->next;
        }

        pNew = GetPStuData();
        CopyStudent(&pNew->student, &pVisit->student);
        pNew->next = pSortVisit;
        pSortLast->next = pNew;
        pVisit = pVisit->next;
    }
    DisplayStudents(pSortHead);
    pSortVisit = NULL;
    while(pSortHead){
        pSortVisit = pSortHead->next;
        FreePStuData(pSortHead);
        pSortHead = pSortVisit;
    }

}

void CopyStudent(Stu * st1, Stu * st2){
    st1->id = st2->id;
    strcpy(st1->name, st2->name);
    st1->age = st2->age;
    st1->math = st2->math;
    st1->computer = st2->computer;
    st1->total = st2->total;
}

void BackMain(){
    ClearStdin();
    printf("输入任何字符返回主菜单");
    getchar();
    ClearScreen();
}

void ClearScreen(){
    system("cls");
}

void ClearStdin(){
    setbuf(stdin, NULL);
}



演示:

演示.gif



  至此,该学生成绩管理系统介绍完毕,其中都是采用比较简单的做法。当然这里可以进一步优化,比如数据可以存储到文件而不用每次都重新输入等等,但不影响此系统的小全的功能,我就不上文件存储功能的代码了。

相关文章

网友评论

      本文标题:C语言实现简单的学生成绩管理系统

      本文链接:https://www.haomeiwen.com/subject/dkbtfktx.html