学生成绩管理是高校教务工作中最基础也最繁琐的环节。一个班级四十余人,每学期涉及十余门课程,平时成绩、期末成绩、总评折算、排名统计,手工处理不仅效率低下,还极易出错。用C语言编写一个成绩管理系统,能够在命令行环境下完成数据的录入、查询、排序与统计,并且不依赖任何第三方库,适合作为课程设计或期末项目。
系统的核心数据结构采用结构体数组。定义学生信息字段包括学号(13位整数)、姓名(20字节字符数组)、平时成绩(浮点数)、期末成绩(浮点数)、总评成绩(浮点数)。课程门数设定为五门,对应结构体中的五个成绩数组。总评成绩按照平时成绩占百分之三十、期末成绩占百分之七十的权重计算,这是多数高校采用的折算标准。系统支持的最大学生容量设为一百人,由预处理器宏定义,方便修改。
功能模块划分为五个部分。数据录入模块提供逐条添加学生信息的交互界面,输入时自动检查学号重复与非数字字符,录入完成后立即计算总评。数据查询模块支持按学号精确查询和按姓名模糊查询,模糊查询通过遍历姓名数组并调用strstr函数实现。排序模块提供三种排序依据:学号升序、总评成绩降序、单科成绩降序,排序算法采用冒泡排序或快速排序均可,考虑到系统规模在一百人以内,冒泡排序的耗时完全可接受。统计模块计算全班各科平均分、最高分、最低分、及格率与优秀率。数据持久化通过文件读写实现,使用fwrite与fread函数将结构体数组整体写入二进制文件,每次程序启动时尝试加载已有数据文件,退出时自动保存。
文件存储格式需仔细设计。成绩单文件名为score.dat,文件头存放一个整数表示当前学生总数,随后紧跟结构体数组的二进制内容。使用二进制而非文本格式,读取速度快且数据精度不丢失。为防止误操作导致数据损坏,系统在写入前先备份原文件为score.bak,写入成功后删除备份,这是工程实践中常用的安全策略。
排序功能的细节需要注意。按总评成绩排序时,若成绩相同则按学号升序排列,保证排序稳定性。按单科成绩排序需要用户输入课程编号,例如数字1至5代表五门课程。每完成一次排序,立即将排序后的数组重新写回文件,保持文件与内存数据的一致性。排序完成后显示前三名与后三名的学号、姓名、成绩,便于快速了解整体情况。

统计模块的输出格式采用表格对齐。使用printf的%-13s、%-20s、%8.1f等格式控制符,保证学号左对齐、姓名左对齐、成绩右对齐,表格线用减号和竖线字符绘制。平均分保留一位小数,及格率与优秀率保留两位小数并带百分号。及格分数线设为六十分,优秀分数线设为八十五分,这两个阈值也是高校普遍采用的标准。
边界情况的处理是系统健壮性的体现。当试图删除或修改不存在的学号时,给出明确的错误提示并返回主菜单。当文件读取时发现文件不存在,不报错而是初始化空系统。当成绩录入值超出零到一百分范围,拒绝接收并要求重新输入。菜单交互采用死循环加switch语句结构,用户输入零退出系统,退出前检查数据是否未保存,如果有未保存修改则提示确认。
测试数据验证系统的正确性。录入十名学生的五门课程成绩,模拟两次期末考试数据。例如某学生学号2023001001001,姓名张伟,高数平时成绩88分,期末76分,总评为88乘以零点三加76乘以零点七,计算结果为79.6分,系统输出的数值与手算结果完全一致。排序后检查数组首元素为最高分学生,尾元素为最低分学生,均符合预期。统计模块输出的平均分与使用计算器逐项求和取平均的结果误差不超过零点零一分。文件保存后重新启动程序,数据完整加载,无乱码或丢失。
该系统的开发过程也反映出C语言教学的实际情况。内存管理是难点,结构体数组的静态分配简单但不够灵活,动态链表更能体现C语言的指针特性。文件操作容易遗漏fclose调用导致数据写不完整,需要反复检查。命令行界面的字符画与制表符在不同终端宽度下的显示效果差异需要适配。整个系统代码规模约一千二百行,编译无警告,测试覆盖所有功能分支,这类系统在高校课程设计中属于中等偏上水平,具有良好的扩展价值。