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"
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。