经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C 语言 » 查看文章
C语言链表实现学生成绩管理系统
来源:jb51  时间:2022/7/25 17:16:04  对本文有异议

本文实例为大家分享了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变量代表一组学生信息

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

2. studentNode类型定义

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

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

3. studentList类型定义

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

  1. typedef struct {
  2. ?? ?studentNode *head;?? ?//头指针
  3. ?? ?studentNode *tail;?? ?//尾指针
  4. ?? ?int count;?? ??? ??? ?//学生节点总数
  5. } studentList;?? ??? ??? ?//学生链表

(3)函数原型

  1. void initialize(studentList *L);//初始化链表,创建头节点
  2. void enter(studentList *L);?? ??? ?//录入链表
  3. void display(studentList *L);?? ?//输出链表
  4. void find(studentList *L);?? ??? ?//查找某节点
  5. void modify(studentList *L);?? ?//修改某节点
  6. void sort(studentList *L);?? ??? ?//降序重新建表并输出
  7. void write(studentList *L);?? ??? ?//写入文件,边写边释放空间
  8. void read(studentList *L);?? ??? ?//读取文件,边读边建表

(4)main函数定义

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

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

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

  1. int main() {
  2. ?? ?//互动界面
  3. ?? ?printf("?? ??? ?**************学生成绩管理系统**************\n");
  4. ?? ?printf("?? ??? ?* ?1.录入新的学生成绩 ? ? ? ? ? ? ? ? ? ? ?*\n");
  5. ?? ?printf("?? ??? ?* ?2.按姓名修改学生成绩 ? ? ? ? ? ? ? ? ? ?*\n");
  6. ?? ?printf("?? ??? ?* ?3.按姓名查询学生成绩 ? ? ? ? ? ? ? ? ? ?*\n");
  7. ?? ?printf("?? ??? ?* ?4.输出全部学生的成绩 ? ? ? ? ? ? ? ? ? ?*\n");
  8. ?? ?printf("?? ??? ?* ?5.按平均分输出学生成绩 ? ? ? ? ? ? ? ? ?*\n");
  9. ?? ?printf("?? ??? ?* ?6.退出学生成绩管理系统 ? ? ? ? ? ? ? ? ?*\n");
  10. ?? ?printf("?? ??? ?********************************************\n");
  11. ?? ?printf(" ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\n");
  12. ?? ?//创建学生链表
  13. ?? ?studentList *L = (studentList *)malloc(sizeof(studentList));
  14. ?? ?//初始化学生链表
  15. ?? ?initialize(L);
  16. ?? ?//从文件里读取数据到链表
  17. ?? ?read(L);
  18. ?? ?//互动界面是用一个无限循环和一个switch写的
  19. ?? ?while (1) {
  20. ?? ??? ?int code;
  21. ?? ??? ?printf("请输入你想进行的操作对应的数字: ");
  22. ?? ??? ?scanf("%d", &code);
  23. ?? ??? ?switch (code) {
  24. ?? ??? ??? ?case 1:
  25. ?? ??? ??? ??? ?enter(L);
  26. ?? ??? ??? ??? ?break;
  27. ?? ??? ??? ?case 2:
  28. ?? ??? ??? ??? ?modify(L);
  29. ?? ??? ??? ??? ?break;
  30. ?? ??? ??? ?case 3:
  31. ?? ??? ??? ??? ?find(L);
  32. ?? ??? ??? ??? ?break;
  33. ?? ??? ??? ?case 4:
  34. ?? ??? ??? ??? ?display(L);
  35. ?? ??? ??? ??? ?break;
  36. ?? ??? ??? ?case 5:
  37. ?? ??? ??? ??? ?sort(L);
  38. ?? ??? ??? ??? ?break;
  39. ?? ??? ??? ?case 6:
  40. ?? ??? ??? ??? ?write(L);
  41. ?? ??? ??? ??? ?free(L->head);?? ?//头节点被销毁
  42. ?? ??? ??? ??? ?free(L);?? ??? ?//链表被销毁
  43. ?? ??? ??? ??? ?return 0;
  44. ?? ??? ??? ?default:
  45. ?? ??? ??? ??? ?printf("%d是无效的数字,请重新输入!\n\n", code);
  46. ?? ??? ??? ??? ?break;
  47. ?? ??? ?}
  48. ?? ?}
  49. ?? ?return 0;
  50. }

(5)其他函数定义 

1.initialize函数定义

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

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

链表的初始长度设为0

  1. void initialize(studentList *L) {
  2. ?? ?//创建头节点
  3. ?? ?studentNode *s = (studentNode *)malloc(sizeof(studentNode));
  4. ?? ?s->next = NULL;
  5. ?? ?//初始化链表:
  6. ?? ?//头尾指针均指向头节点,初始长度为零
  7. ?? ?L->head = s;
  8. ?? ?L->tail = s;
  9. ?? ?L->count = 0;
  10. }

2.enter函数定义

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

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

把新节点插进链表中

  1. void enter(studentList *L) {
  2. ?? ?//创建新节点
  3. ?? ?studentNode *s = (studentNode *)malloc(sizeof(studentNode));
  4. ?? ?//键入信息并存到新节点中
  5. ?? ?printf("请输入学生姓名:");
  6. ?? ?scanf("%s", s->stu.name);
  7. ?? ?printf("请输入学生学号:");
  8. ?? ?scanf("%d", &s->stu.number);
  9. ?? ?printf("请输入语文成绩:");
  10. ?? ?scanf("%d", &s->stu.chinese);
  11. ?? ?printf("请输入数学成绩:");
  12. ?? ?scanf("%d", &s->stu.math);
  13. ?? ?printf("请输入英语成绩:");
  14. ?? ?scanf("%d", &s->stu.english);
  15. ?? ?s->stu.sum = s->stu.chinese + s->stu.math + s->stu.english;
  16. ?? ?s->stu.average = s->stu.sum / 3;
  17. ?? ?//若链表为空,将尾指针指向新节点
  18. ?? ?if (L->head == L->tail) {
  19. ?? ??? ?L->tail = s;
  20. ?? ?}
  21. ?? ?//将新节点插进链表头部(头插法)
  22. ?? ?s->next = L->head->next;
  23. ?? ?L->head->next = s;
  24. ?? ?L->count++;
  25. ?? ?//输出互动信息
  26. ?? ?printf("信息录入成功!\n\n");
  27. }

3.display函数定义

遍历链表输出就完事儿了

  1. void display(studentList *L) {
  2. ?? ?printf("共有%d组学生数据:\n", L->count);
  3. ?? ?printf("姓名\t\t学号\t\t语文\t\t数学\t\t英语\t\t总分\t\t平均分\n");
  4. ?? ?//创建一节点指针指向头节点
  5. ?? ?studentNode *p;
  6. ?? ?p = L->head;
  7. ?? ?//遍历链表输出
  8. ?? ?while (p->next) {
  9. ?? ??? ?p = p->next;
  10. ?? ??? ?printf("%s", p->stu.name);
  11. ?? ??? ?printf("\t\t%d", p->stu.number);
  12. ?? ??? ?printf("\t\t%d", p->stu.chinese);
  13. ?? ??? ?printf("\t\t%d", p->stu.math);
  14. ?? ??? ?printf("\t\t%d", p->stu.english);
  15. ?? ??? ?printf("\t\t%d", p->stu.sum);
  16. ?? ??? ?printf("\t\t%d", p->stu.average);
  17. ?? ??? ?printf("\n");
  18. ?? ?}
  19. ?? ?printf("\n");
  20. }

4.find函数定义

  1. void find(studentList *L) {
  2. ?? ?//让用户输入要查找的学生
  3. ?? ?printf("请输入学生姓名:");
  4. ?? ?char name[NAME_LEN + 1];
  5. ?? ?scanf("%s", name);
  6. ?? ?//遍历链表对比名字
  7. ?? ?studentNode *p = L->head->next;
  8. ?? ?while (p) {
  9. ?? ??? ?//符合了就输出并结束函数
  10. ?? ??? ?if (strcmp(p->stu.name, name) == 0) {
  11. ?? ??? ??? ?printf("姓名\t\t学号\t\t语文\t\t数学\t\t英语\t\t总分\t\t平均分\n");
  12. ?? ??? ??? ?printf("%s", p->stu.name);
  13. ?? ??? ??? ?printf("\t\t%d", p->stu.number);
  14. ?? ??? ??? ?printf("\t\t%d", p->stu.chinese);
  15. ?? ??? ??? ?printf("\t\t%d", p->stu.math);
  16. ?? ??? ??? ?printf("\t\t%d", p->stu.english);
  17. ?? ??? ??? ?printf("\t\t%d", p->stu.sum);
  18. ?? ??? ??? ?printf("\t\t%d", p->stu.average);
  19. ?? ??? ??? ?printf("\n\n");
  20. ?? ??? ??? ?return;
  21. ?? ??? ?}
  22. ?? ??? ?//名字不符合就下一个
  23. ?? ??? ?p = p->next;
  24. ?? ?}
  25. ?? ?//遍历完里都没找到这个名字
  26. ?? ?printf("没找到这个%s的信息!\n\n", name);
  27. }

5.modify函数定义 

  1. void modify(studentList *L) {
  2. ?? ?//让用户输入要修改的学生
  3. ?? ?printf("请输入学生姓名:");
  4. ?? ?char name[NAME_LEN + 1];
  5. ?? ?scanf("%s", name);
  6. ?? ?//遍历链表对比名字
  7. ?? ?studentNode *p = L->head->next;
  8. ?? ?while (p) {
  9. ?? ??? ?//符合了就让用户重新键入并结束函数
  10. ?? ??? ?if (strcmp(p->stu.name, name) == 0) {
  11. ?? ??? ??? ?printf("请重新输入信息:\n");
  12. ?? ??? ??? ?printf("请输入学生学号:");
  13. ?? ??? ??? ?scanf("%d", &p->stu.number);
  14. ?? ??? ??? ?printf("请输入语文成绩:");
  15. ?? ??? ??? ?scanf("%d", &p->stu.chinese);
  16. ?? ??? ??? ?printf("请输入数学成绩:");
  17. ?? ??? ??? ?scanf("%d", &p->stu.math);
  18. ?? ??? ??? ?printf("请输入英语成绩:");
  19. ?? ??? ??? ?scanf("%d", &p->stu.english);
  20. ?? ??? ??? ?p->stu.sum = p->stu.chinese + p->stu.math + p->stu.english;
  21. ?? ??? ??? ?p->stu.average = p->stu.sum / 3;
  22. ?? ??? ??? ?printf("信息修改成功!\n\n");
  23. ?? ??? ??? ?return;
  24. ?? ??? ?}
  25. ?? ??? ?//名字不符合就下一个
  26. ?? ??? ?p = p->next;
  27. ?? ?}
  28. ?? ?//遍历完里都没找到这个名字
  29. ?? ?printf("没找到这个%s的信息!\n\n", name);
  30. }

6.sort函数定义

  1. void sort(studentList *L) {
  2. ?? ?//两个节点都没有排个屁序
  3. ?? ?if (L->count < 2) {
  4. ?? ??? ?printf("链表排序完成!\n");
  5. ?? ??? ?display(L);
  6. ?? ??? ?return;
  7. ?? ?}
  8. ?? ?//插入排序
  9. ?? ?studentNode *p, *pre, *tmp;
  10. ?? ?//p指向第二个学生节点
  11. ?? ?p = L->head->next;
  12. ?? ?//链表从头节点和第一个学生节点处断开
  13. ?? ?L->head->next = NULL;
  14. ?? ?//从第一个学生节点开始一直往后循环
  15. ?? ?while (p) {
  16. ?? ??? ?//存好下一个节点的指针
  17. ?? ??? ?tmp = p->next;
  18. ?? ??? ?//找到插入位置
  19. ?? ??? ?pre = L->head;
  20. ?? ??? ?while (pre->next != NULL && pre->next->stu.average > p->stu.average)
  21. ?? ??? ??? ?pre = pre->next;
  22. ?? ??? ?//更新尾指针
  23. ?? ??? ?if (pre->next == NULL) {
  24. ?? ??? ??? ?L->tail = p;
  25. ?? ??? ?}
  26. ?? ??? ?//插入
  27. ?? ??? ?p->next = pre->next;
  28. ?? ??? ?pre->next = p;
  29. ?? ??? ?//跳到下一个
  30. ?? ??? ?p = tmp;
  31. ?? ?}
  32. ?? ?printf("链表排序完成!\n");
  33. ?? ?display(L);
  34. }

7.write函数定义

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

  1. void write(studentList *L) {
  2. ?? ?//打开文件流
  3. ?? ?FILE *fp = fopen(FILE_NAME, "w");
  4. ?? ?if (fp == NULL) {
  5. ?? ??? ?printf("文件%s打开失败\n", FILE_NAME);
  6. ?? ??? ?exit(EXIT_FAILURE);
  7. ?? ?}
  8. ?? ?//将学生节点总数输出在第一行
  9. ?? ?fprintf(fp, "%d\n", L->count);
  10. ?? ?//创建一节点指针指向头节点
  11. ?? ?studentNode *p;
  12. ?? ?p = L->head->next;
  13. ?? ?//遍历链表,一组数据作为一行输出
  14. ?? ?while (p) {
  15. ?? ??? ?fprintf(fp, "%s ", p->stu.name);
  16. ?? ??? ?fprintf(fp, "%d ", p->stu.number);
  17. ?? ??? ?fprintf(fp, "%d ", p->stu.chinese);
  18. ?? ??? ?fprintf(fp, "%d ", p->stu.math);
  19. ?? ??? ?fprintf(fp, "%d ", p->stu.english);
  20. ?? ??? ?fprintf(fp, "%d ", p->stu.sum);
  21. ?? ??? ?fprintf(fp, "%d ", p->stu.average);
  22. ?? ??? ?fprintf(fp, "\n");
  23. ?? ??? ?//输出完成之后释放节点空间
  24. ?? ??? ?studentNode *next = p->next;
  25. ?? ??? ?free(p);
  26. ?? ??? ?p = next;
  27. ?? ?}
  28. ?? ?//关闭文件流
  29. ?? ?fclose(fp);
  30. ?? ?//互动信息
  31. ?? ?printf("数据已保存!谢谢使用,再见!\n");
  32. }

8.read函数定义

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

  1. void read(studentList *L) {
  2. ?? ?//打开文件流
  3. ?? ?FILE *fp = fopen(FILE_NAME, "r");
  4. ?? ?if (fp == NULL) {
  5. ?? ??? ?printf("文件%s打开失败\n", FILE_NAME);
  6. ?? ??? ?exit(EXIT_FAILURE);
  7. ?? ?}
  8. ?? ?//读取第一行的学生节点总数
  9. ?? ?fscanf(fp, "%d", &L->count);
  10. ?? ?//循环读取数据,循环次数为count
  11. ?? ?for (int i = 1; i <= L->count; i++) {
  12. ?? ??? ?//创建新节点
  13. ?? ??? ?studentNode *s = (studentNode *)malloc(sizeof(studentNode));
  14. ?? ??? ?//读取数据
  15. ?? ??? ?fscanf(fp, "%s ", s->stu.name);
  16. ?? ??? ?fscanf(fp, "%d ", &s->stu.number);
  17. ?? ??? ?fscanf(fp, "%d ", &s->stu.chinese);
  18. ?? ??? ?fscanf(fp, "%d ", &s->stu.math);
  19. ?? ??? ?fscanf(fp, "%d ", &s->stu.english);
  20. ?? ??? ?fscanf(fp, "%d ", &s->stu.sum);
  21. ?? ??? ?fscanf(fp, "%d ", &s->stu.average);
  22. ?? ??? ?//将新节点插进链表尾部(尾插法)
  23. ?? ??? ?s->next = NULL;
  24. ?? ??? ?L->tail->next = s;
  25. ?? ??? ?L->tail = s;
  26. ?? ?}
  27. ?? ?//关闭文件流
  28. ?? ?fclose(fp);
  29. }

四、运行示例

输出全部学生成绩

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

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

五、注意事项 

文件得和源码在同一目录

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号