C语言链表实现学生成绩管理系统

目录

一、课程设计题目及内容

二、主要设计思路

三、程序源码及具体注释

(1)预处理指令

(2)类型定义

(3)函数原型

(4)main函数定义

(5)其他函数定义 

四、运行示例

五、注意事项 

本文实例为大家分享了C语言基于链表实现学生成绩管理系统的具体代码,供大家参考,具体内容如下

一、课程设计题目及内容

程序名称:学生成绩管理系统

功能要求:录入学生成绩,修改学生成绩,统计每个学生的总分及平均分并能根据学生的平均成绩排序,查询学生成绩,输出学生成绩单。能够保存学生成绩,实现文件的读写。界面简洁大方,易操作。

二、主要设计思路

以链表作为数据结构存储学生成绩等信息,然后围绕链表编写一堆函数来实现一堆功能

程序开始时会读取文件数据到链表,结束时会把更新后的链表中的信息重新写入到文件中,以实现数据的保存

三、程序源码及具体注释 (1)预处理指令

导入<stdlib.h>是因为会用到malloc函数和free函数

导入<string.h>是因为会用到strcmp函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_LEN 10
#define FILE_NAME "学生成绩.txt"

(2)类型定义

1.student类型定义

一个student变量代表一组学生信息

typedef struct {     char name[NAME_LEN + 1];//姓名     int number;                //学号     int chinese;            //语文     int math;                //数学     int english;            //英语     int average;            //平均分     int sum;                //总分 } student;                    //用于存储单个学生的信息

2. studentNode类型定义

一个studentNode变量代表一个学生节点

typedef struct node {     student stu;        //数据域,存储学生信息     struct node *next;    //指针域,指向下一个节点 } studentNode;            //学生节点

3. studentList类型定义

一个studentList变量代表一个学生链表

typedef struct {     studentNode *head;    //头指针     studentNode *tail;    //尾指针     int count;            //学生节点总数 } studentList;            //学生链表 (3)函数原型 void initialize(studentList *L);//初始化链表,创建头节点 void enter(studentList *L);        //录入链表 void display(studentList *L);    //输出链表 void find(studentList *L);        //查找某节点 void modify(studentList *L);    //修改某节点 void sort(studentList *L);        //降序重新建表并输出 void write(studentList *L);        //写入文件,边写边释放空间 void read(studentList *L);        //读取文件,边读边建表 (4)main函数定义

开头会创建并初始化一个链表,然后把文件的信息读到链表中

通过一个无限循环里面套一个switch来实现与用户互动

结尾会把链表中的信息写到文件中,然后销毁链表

int main() {     //互动界面     printf("        **************学生成绩管理系统**************\n");     printf("        *  1.录入新的学生成绩                      *\n");     printf("        *  2.按姓名修改学生成绩                    *\n");     printf("        *  3.按姓名查询学生成绩                    *\n");     printf("        *  4.输出全部学生的成绩                    *\n");     printf("        *  5.按平均分输出学生成绩                  *\n");     printf("        *  6.退出学生成绩管理系统                  *\n");     printf("        ********************************************\n");     printf("                                                      \n");     //创建学生链表     studentList *L = (studentList *)malloc(sizeof(studentList));     //初始化学生链表     initialize(L);     //从文件里读取数据到链表     read(L);     //互动界面是用一个无限循环和一个switch写的     while (1) {         int code;         printf("请输入你想进行的操作对应的数字: ");         scanf("%d", &code);         switch (code) {             case 1:                 enter(L);                 break;             case 2:                 modify(L);                 break;             case 3:                 find(L);                 break;             case 4:                 display(L);                 break;             case 5:                 sort(L);                 break;             case 6:                 write(L);                 free(L->head);    //头节点被销毁                 free(L);        //链表被销毁                 return 0;             default:                 printf("%d是无效的数字,请重新输入!\n\n", code);                 break;         }     }     return 0; } (5)其他函数定义 

1.initialize函数定义

接收一个链表指针作为参数

创建一个头节点,不存储任何信息,让链表的头尾指针都指向它

链表的初始长度设为0

void initialize(studentList *L) {     //创建头节点     studentNode *s = (studentNode *)malloc(sizeof(studentNode));     s->next = NULL;     //初始化链表:     //头尾指针均指向头节点,初始长度为零     L->head = s;     L->tail = s;     L->count = 0; }

2.enter函数定义

接收一个链表指针作为参数

让用户键入信息并存到新节点中

把新节点插进链表中

void enter(studentList *L) {     //创建新节点     studentNode *s = (studentNode *)malloc(sizeof(studentNode));     //键入信息并存到新节点中     printf("请输入学生姓名:");     scanf("%s", s->stu.name);     printf("请输入学生学号:");     scanf("%d", &s->stu.number);     printf("请输入语文成绩:");     scanf("%d", &s->stu.chinese);     printf("请输入数学成绩:");     scanf("%d", &s->stu.math);     printf("请输入英语成绩:");     scanf("%d", &s->stu.english);     s->stu.sum = s->stu.chinese + s->stu.math + s->stu.english;     s->stu.average = s->stu.sum / 3;     //若链表为空,将尾指针指向新节点     if (L->head == L->tail) {         L->tail = s;     }     //将新节点插进链表头部(头插法)     s->next = L->head->next;     L->head->next = s;     L->count++;     //输出互动信息     printf("信息录入成功!\n\n"); }

3.display函数定义

遍历链表输出就完事儿了

void display(studentList *L) {     printf("共有%d组学生数据:\n", L->count);     printf("姓名\t\t学号\t\t语文\t\t数学\t\t英语\t\t总分\t\t平均分\n");     //创建一节点指针指向头节点     studentNode *p;     p = L->head;     //遍历链表输出     while (p->next) {         p = p->next;         printf("%s", p->stu.name);         printf("\t\t%d", p->stu.number);         printf("\t\t%d", p->stu.chinese);         printf("\t\t%d", p->stu.math);         printf("\t\t%d", p->stu.english);         printf("\t\t%d", p->stu.sum);         printf("\t\t%d", p->stu.average);         printf("\n");     }     printf("\n"); }

4.find函数定义

void find(studentList *L) {     //让用户输入要查找的学生     printf("请输入学生姓名:");     char name[NAME_LEN + 1];     scanf("%s", name);     //遍历链表对比名字     studentNode *p = L->head->next;     while (p) {         //符合了就输出并结束函数         if (strcmp(p->stu.name, name) == 0) {             printf("姓名\t\t学号\t\t语文\t\t数学\t\t英语\t\t总分\t\t平均分\n");             printf("%s", p->stu.name);             printf("\t\t%d", p->stu.number);             printf("\t\t%d", p->stu.chinese);             printf("\t\t%d", p->stu.math);             printf("\t\t%d", p->stu.english);             printf("\t\t%d", p->stu.sum);             printf("\t\t%d", p->stu.average);             printf("\n\n");             return;         }         //名字不符合就下一个         p = p->next;     }     //遍历完里都没找到这个名字     printf("没找到这个%s的信息!\n\n", name); }

5.modify函数定义 

void modify(studentList *L) {     //让用户输入要修改的学生     printf("请输入学生姓名:");     char name[NAME_LEN + 1];     scanf("%s", name);     //遍历链表对比名字     studentNode *p = L->head->next;     while (p) {         //符合了就让用户重新键入并结束函数         if (strcmp(p->stu.name, name) == 0) {             printf("请重新输入信息:\n");             printf("请输入学生学号:");             scanf("%d", &p->stu.number);             printf("请输入语文成绩:");             scanf("%d", &p->stu.chinese);             printf("请输入数学成绩:");             scanf("%d", &p->stu.math);             printf("请输入英语成绩:");             scanf("%d", &p->stu.english);             p->stu.sum = p->stu.chinese + p->stu.math + p->stu.english;             p->stu.average = p->stu.sum / 3;             printf("信息修改成功!\n\n");             return;         }         //名字不符合就下一个         p = p->next;     }     //遍历完里都没找到这个名字     printf("没找到这个%s的信息!\n\n", name); }

6.sort函数定义

void sort(studentList *L) {     //两个节点都没有排个屁序     if (L->count < 2) {         printf("链表排序完成!\n");         display(L);         return;     }     //插入排序     studentNode *p, *pre, *tmp;     //p指向第二个学生节点     p = L->head->next;     //链表从头节点和第一个学生节点处断开     L->head->next = NULL;     //从第一个学生节点开始一直往后循环     while (p) {         //存好下一个节点的指针         tmp = p->next;         //找到插入位置         pre = L->head;         while (pre->next != NULL && pre->next->stu.average > p->stu.average)             pre = pre->next;         //更新尾指针         if (pre->next == NULL) {             L->tail = p;         }         //插入         p->next = pre->next;         pre->next = p;         //跳到下一个         p = tmp;     }     printf("链表排序完成!\n");     display(L); }

7.write函数定义

此函数用于把链表中的信息保存到文件中并且销毁所有节点(头节点除外)

void write(studentList *L) {     //打开文件流     FILE *fp = fopen(FILE_NAME, "w");     if (fp == NULL) {         printf("文件%s打开失败\n", FILE_NAME);         exit(EXIT_FAILURE);     }     //将学生节点总数输出在第一行     fprintf(fp, "%d\n", L->count);     //创建一节点指针指向头节点     studentNode *p;     p = L->head->next;     //遍历链表,一组数据作为一行输出     while (p) {         fprintf(fp, "%s ", p->stu.name);         fprintf(fp, "%d ", p->stu.number);         fprintf(fp, "%d ", p->stu.chinese);         fprintf(fp, "%d ", p->stu.math);         fprintf(fp, "%d ", p->stu.english);         fprintf(fp, "%d ", p->stu.sum);         fprintf(fp, "%d ", p->stu.average);         fprintf(fp, "\n");         //输出完成之后释放节点空间         studentNode *next = p->next;         free(p);         p = next;     }     //关闭文件流     fclose(fp);     //互动信息     printf("数据已保存!谢谢使用,再见!\n"); }

8.read函数定义

此函数用于把文件中的信息读取到链表中并且创建节点(头节点除外)

void read(studentList *L) {     //打开文件流     FILE *fp = fopen(FILE_NAME, "r");     if (fp == NULL) {         printf("文件%s打开失败\n", FILE_NAME);         exit(EXIT_FAILURE);     }     //读取第一行的学生节点总数     fscanf(fp, "%d", &L->count);     //循环读取数据,循环次数为count     for (int i = 1; i <= L->count; i++) {         //创建新节点         studentNode *s = (studentNode *)malloc(sizeof(studentNode));         //读取数据         fscanf(fp, "%s ", s->stu.name);         fscanf(fp, "%d ", &s->stu.number);         fscanf(fp, "%d ", &s->stu.chinese);         fscanf(fp, "%d ", &s->stu.math);         fscanf(fp, "%d ", &s->stu.english);         fscanf(fp, "%d ", &s->stu.sum);         fscanf(fp, "%d ", &s->stu.average);         //将新节点插进链表尾部(尾插法)         s->next = NULL;         L->tail->next = s;         L->tail = s;     }     //关闭文件流     fclose(fp); } 四、运行示例

输出全部学生成绩

录入一组新数据然后关闭程序

上次输入的信息还在,说明信息保存成功

五、注意事项 

文件得和源码在同一目录

文件名是"学生成绩.txt"

推荐阅读