项目背景

本系统是大一 C 语言课程设计的期末作品。要求在控制台环境下实现一个完整的学生成绩管理系统,涵盖数据的增删改查、排序筛选、文件持久化等功能。

项目的目标是综合运用 C 语言的核心知识:结构体、指针、链表、文件 I/O、字符串处理等。

功能设计

系统整体采用菜单驱动的交互方式,主要功能模块如下:

模块 功能描述
添加学生 录入学号、姓名、各科成绩
修改信息 按学号查找并修改学生数据
删除学生 按学号删除学生记录
查询成绩 支持按学号查询和按姓名模糊查询
成绩统计 计算总分、平均分、排名、最高/最低分
排序输出 按总分或学号排序,升序/降序可选
数据持久化 启动时从文件读取,退出时自动保存

数据结构

1
2
3
4
5
6
7
8
9
10
typedef struct Student {
char id[12]; // 学号
char name[20]; // 姓名
int score_chinese; // 语文
int score_math; // 数学
int score_english; // 英语
int score_total; // 总分
float score_avg; // 平均分
struct Student *next; // 指向下一个节点
} Student;

使用单链表管理所有学生数据,相比固定数组更加灵活,支持动态增减。

关键技术点

1. 链表操作

核心是链表的增删改查。删除节点时需要正确处理前驱节点的指针重定向;插入节点时要维持链表的有序性。

2. 文件读写

使用 fopen / fread / fwrite 实现数据的二进制存储和读取。程序启动时自动加载数据文件,若文件不存在则创建空链表。

3. 排序算法

采用冒泡排序对链表进行排序,支持按总分或学号两种排序键,以及升序/降序两种模式。排序过程中只交换节点数据域,避免修改指针结构。

4. 输入校验

对学号做去重检查,对成绩做范围校验(0-100),对菜单选择做合法性判断,避免因非法输入导致程序异常。

遇到的问题与解决

问题一:删除操作导致链表断裂

最初忘记在删除时更新前驱节点的 next 指针。修复方式是引入 prev 指针,在遍历时始终记录前一个节点。

问题二:文件读写时指针错位

写入文件时使用了文本模式而非二进制模式,导致部分数据截断。统一改为 "rb" / "wb" 模式解决。

问题三:排序效率

冒泡排序在数据量大时效率较低。考虑到本系统面向课程展示,数据量有限,暂时保留;后续若有实际使用需求可升级为快速排序。

总结收获

这个项目让我真正体会到”做中学”的意义。课堂上以为已经掌握了的指针和链表,在实际编码时才发现理解其实很浅。通过一个个 bug 的调试,才逐渐建立起对这些概念的直觉。

最大的收获是:不要害怕报错。每一个段错误背后都有一个不合理的指针操作,去理解它、修复它,这就是进步。