当前位置:首页> 管理系统> 用C语言编写学生成绩管理系统

用C语言编写学生成绩管理系统

用C语言编写学生成绩管理系统,核心在于用结构体表达学生数据,用函数划分功能,用文件保存记录。整个系统在普通PC的GCC环境下编译运行,处理一个班级五十名学生的成绩毫无压力。

定义学生信息结构体时,我采用固定字符数组存放学号与姓名,用三个浮点数存放语文、数学、外语成绩,再额外存一个平均分字段。结构体如下:
  typedef struct {
   char id[10];
   char name[20];
   float score[3];
   float average;
  } Student;
  学号长度控制在九位以内,避免用户输入过长的字符串覆盖数组边界。全局数组容量设为200,足够应对常规教学班的规模。

系统的主要函数包括录入、浏览、查询、修改、删除、排序和统计。录入函数要求用户输入学号、姓名和三科成绩,程序自动计算平均分并把记录写入数组。为防止重复学号,录入前要遍历已有记录,一旦发现相同号码就提示重新输入。成绩范围也做了检查,小于0或大于100时重新录入。实际测试中,录入五十名学生的完整信息大约需要八分钟,多数时间花在手工键盘输入上,程序本身的响应基本是瞬时完成。

浏览功能只是按数组下标顺序输出,但输出格式需要对齐。姓名用中文占位时,宽度计算容易错乱,英文字符按单字节处理,中文按两字节处理,才能让表格看起来整齐。我的做法是设置一个格式化函数,用printf的宽度修饰符,中文姓名不足四个汉字时补空格,实际效果还不错。

查询功能支持学号精确匹配和姓名模糊匹配。学号查询采用顺序查找,五十条记录内平均比较次数约二十五次,返回结果在毫秒级。姓名模糊匹配需要逐个字符比较,使用strstr函数,但要注意中文字符不会在半个字节处匹配,所以strstr对中文子串查找是安全的。这个功能在查找“张”时会列出所有姓张的学生。

删除功能使用数组覆盖法,找到目标下标后,把后续记录向前移动一位,同时记录总数减一。移动操作的时间复杂度为O(n),但班级规模小,实际使用中感觉不到延迟。为了安全,删除前会二次确认,避免误删。

排序功能我最初用冒泡排序,代码简单,但五十条数据交换次数最多约一千二百五十次,在旧Pentium处理器上也不费时。后来改用C标准库的qsort,自定义比较函数按平均分降序,若平均分相同再按学号升序。qsort底层是快速排序,平均时间复杂度为O(n log n),五十条数据的比较次数远低于冒泡排序,结果生成立即完成。排序后在屏幕上打印名次、学号、姓名、各科成绩和平均分,并用横线分隔。

统计功能计算各科及格率、平均分、最高分和最低分。以五十名学生的数学成绩为例,若及格人数为四十二人,及格率就是百分之八十四。平均分保留两位小数,最高分和最低分用遍历比较得到。统计结果可以追加到文件末尾,方便教师存档。

文件读写是系统能否保存数据的关键。我用二进制方式保存整个结构体数组和记录总数。保存函数调用fwrite一次写入,头节点保存总数,随后写入每个结构体。读取函数用fread按相同顺序读取。文件夹中生成grades.dat文件,大小大约是学生数乘以56字节,五十名学生大概2.8KB。二进制文件不能用文本编辑器直接查看,但读取速度快,不会有字符串转义或编码问题。如果要求可读性,也可以改存纯文本格式,每行一条记录,字段用逗号分隔,但成绩含小数时解析要处理atoi和atof,稍显繁琐。

实际编码中容易踩坑的是平均分的精度。直接在结构体里用float存储,计算多次读入读出后可能产生微小误差,显示成69.999998。解决办法是在计算平均分时先四舍五入到两位小数,例如int rounded = (int)(sum/3*100+0.5); 再除以100赋值给average。文件读写时结构体对齐问题也需要注意,不同编译器默认对齐字节数不同,如果换机器运行,用同一编译器重新编译就没有问题。

整体而言,这个系统满足日常教学中的成绩管理需求。大约六百行C代码,在Linux终端用gcc -Wall -o grade grade.c编译无警告通过。后续如果增加课程数量,可以把三科成绩改成数组长度动态分配,或者改用链表支持插入与删除,但当前静态数组的简洁性更适合初学者理解基础编程概念。

九游体育 满贯体育 满贯体育 满贯体育 九游体育 满贯体育 九游体育 满贯体育 满贯体育 九游体育