一、设计要求
1. 主菜单显示与选择功能
- 功能描述:显示主菜单,并根据用户输入选择不同功能模块。
- 代码实现:
display_main_menu
函数用于显示主菜单,main
函数实现菜单选择和功能调用。
2. 成绩录入功能
- 功能描述:录入学生的学号、姓名及五门课程的成绩。
- 代码实现:
input_grades
函数实现成绩录入,通过用户输入学生数量和各个学生的详细信息存入students
数组。
3. 成绩排序功能
3.1 按学号排序
- 功能描述:按学生学号进行排序,并将排序结果写入文件
std.dat
。 - 代码实现:
sort_by_id
函数调用qsort
函数和compare_by_id
比较函数实现排序,并将结果写入文件。
// 按学号排序 void sort_by_id() { // 使用qsort函数进行排序 qsort(students, student_count, sizeof(Student), compare_by_id); // 打开文件std.dat写入排序结果 FILE *file = fopen("std.dat", "w"); if (file == NULL) { printf("无法打开文件 std.dat 进行写入。\n"); return; } // 将排序后的结果写入文件 for (int i = 0; i < student_count; i++) { fprintf(file, "%s %s %d %d %d %d %d\n", students[i].id, students[i].name, students[i].math, students[i].english, students[i].physics, students[i].programming, students[i].philosophy); } fclose(file); printf("学生成绩已按学号排序并存入文件 std.dat。\n"); }
3.2 计算平均分并排序
- 功能描述:计算每个学生的平均分,按平均分排序,并将排序结果写入文件
sort.dat
。 sort_by_average
函数调用qsort
函数和compare_by_average
比较函数实现排序,并将结果写入文件。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 学籍 ” 获取。👈👈👈
4. 成绩统计功能
4.1 计算平均分
- 功能描述:计算每个学生的平均分,并输出结果。
- 代码实现:
calculate_average
函数遍历students
数组,计算并输出每个学生的平均分。
4.2 统计分数段
- 功能描述:统计每门课程各个分数段的人数,并输出统计结果。
- 代码实现:
count_grade_sections
函数统计每门课程的分数段人数,并输出结果。
5. 学籍处理功能
5.1 生成并打印补考通知单
- 功能描述:根据用户输入的课程名称、时间和地点,生成并打印需要补考的学生通知单。
- 代码实现:
print_reexam_notice
函数根据输入的信息,遍历students
数组,生成并输出补考通知单。
5.2 生成并打印退学通知单
- 功能描述:统计超过两门课不及格的学生,生成并打印退学通知单。
- 代码实现:
print_dropout_notice
函数遍历students
数组,统计并输出退学通知单。
5.3 生成并打印新名册
- 功能描述:生成新的学生名册,包含至多两门课不及格的学生,并写入文件
next.dat
。 - 代码实现:
print_new_roster
函数遍历students
数组,将符合条件的学生信息写入文件。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 学籍 ” 获取。👈👈👈
6. 自定义功能
- 功能描述:提供按学号或姓名查询学生信息的功能。
- 代码实现:
handle_custom_feature
函数根据用户选择的查询方式,查询并输出对应的学生信息。
7. 系统退出功能
- 功能描述:退出系统。
- 代码实现:
exit_system
函数用于退出系统,并在退出前提示用户按任意键结束程序。
8. 菜单显示功能
8.1 显示成绩统计子菜单
- 功能描述:显示成绩统计子菜单,并根据用户选择执行相应的统计功能。
- 代码实现:
display_stat_menu
函数显示子菜单,并根据用户输入调用相应的统计函数。
// 显示成绩统计子菜单 void display_stat_menu() { int choice; do { printf("------------------------\n"); printf("请输入选项编号(0-4):\n"); printf("------------------------\n"); printf("1————按学号排序\n"); printf("2————计算平均分并排序\n"); printf("3————统计分数段\n"); printf("4————返回\n"); printf("0————退出系统\n"); printf("请输入选项编号(0-4):"); scanf("%d", &choice);
8.2 显示学籍处理子菜单
- 功能描述:显示学籍处理子菜单,并根据用户选择执行相应的学籍处理功能。
- 代码实现:
display_mgmt_menu
函数显示子菜单,并根据用户输入调用相应的学籍处理函数。
9. 文件操作功能
9.1 写入按学号排序后的结果
- 功能描述:将按学号排序后的学生成绩写入文件
std.dat
。 - 代码实现:
sort_by_id
函数实现。
9.2 写入按平均分排序后的结果
- 功能描述:将按平均分排序后的学生成绩写入文件
sort.dat
。 - 代码实现:
sort_by_average
函数实现。
9.3 写入新名册
- 功能描述:将符合条件的学生信息写入文件
next.dat
。 - 代码实现:
print_new_roster
函数实现。
二、设计思路
代码设计思路
一、总体结构设计
本程序的设计目标是实现一个学生成绩管理系统,提供成绩录入、成绩统计、学籍处理以及其他自定义功能。整体设计思路如下:
- 数据结构设计:采用结构体
Student
来表示学生的相关信息,包括学号、姓名、五门课程成绩及平均分。 - 菜单系统设计:通过主菜单和子菜单的设计,使用户能够方便地进行不同功能的选择和操作。
- 功能模块设计:根据功能需求,将系统功能模块化,分别实现成绩录入、成绩排序、成绩统计、学籍处理及自定义查询等功能。
二、数据结构设计
程序中使用结构体 Student
来存储单个学生的详细信息:
typedef struct { char id[11]; // 学号 char name[20]; // 姓名 int math; // 高数成绩 int english; // 英语成绩 int physics; // 物理成绩 int programming; // 编程成绩 int philosophy; // 马哲成绩 float average; // 平均分 } Student;
另外,定义了一个全局数组 students
存储所有学生的数据,并使用 student_count
记录当前学生数量。
三、菜单系统设计
- 主菜单:显示系统的主要功能选项,包括成绩录入、成绩统计、学籍处理、自定义功能及退出系统。
- 成绩统计子菜单:提供按学号排序、计算平均分并排序、统计分数段等功能的选项。
- 学籍处理子菜单:提供生成并打印补考通知单、退学通知单、新名册等功能的选项。
四、功能模块设计
1. 成绩录入
通过 input_grades
函数实现成绩录入功能。用户输入学生数量后,逐个输入每个学生的详细信息,包括学号、姓名及五门课程成绩。
// 输入学生成绩 void input_grades() { printf("请输入学生的数量:"); scanf("%d", &student_count); for (int i = 0; i < student_count; i++) { printf("请输入第%d个学生的学号、姓名、高数、英语、物理、编程、马哲成绩:\n", i+1); scanf("%s %s %d %d %d %d %d", students[i].id, students[i].name, &students[i].math, &students[i].english, &students[i].physics, &students[i].programming, &students[i].philosophy); } }
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 学籍 ” 获取。👈👈👈
2. 成绩排序
- 按学号排序:使用
qsort
函数和比较函数compare_by_id
实现按学号排序,并将排序结果写入文件std.dat
。 - 按平均分排序:先通过
calculate_averages
函数计算每个学生的平均分,再使用qsort
函数和比较函数compare_by_average
实现按平均分排序,并将排序结果写入文件sort.dat
。
// 比较函数,用于按平均分排序(从高到低) int compare_by_average(const void *a, const void *b) { float avg_a = ((Student *)a)->average; float avg_b = ((Student *)b)->average; if (avg_b > avg_a) return 1; else if (avg_b < avg_a) return -1; else return 0; }
3. 成绩统计
通过 calculate_average
函数计算每个学生的平均分,并输出结果。通过 count_grade_sections
函数统计每门课程的分数段人数,并输出统计结果。
void calculate_averages() { for (int i = 0; i < student_count; i++) { students[i].average = (students[i].math + students[i].english + students[i].physics + students[i].programming + students[i].philosophy) / 5.0; } }
4. 学籍处理
- 生成并打印补考通知单:通过
print_reexam_notice
函数,根据用户输入的课程名称、时间及地点,生成并打印需要补考的学生通知单。 - 生成并打印退学通知单:通过
print_dropout_notice
函数,统计超过两门课不及格的学生,并生成并打印退学通知单。 - 生成并打印新名册:通过
print_new_roster
函数,生成新的学生名册并写入文件next.dat
。
5. 自定义查询功能
通过 handle_custom_feature
函数实现按学号或姓名查询学生信息功能。用户可选择查询方式并输入相应信息,程序会查找并输出对应的学生信息。
五、代码逻辑实现
主程序通过 main
函数调用 display_main_menu
显示主菜单,并根据用户输入调用相应的功能模块。各功能模块在实现时注重用户体验和错误处理,确保程序的健壮性和易用性。
void display_main_menu() { printf("------------------------\n"); printf("请输入选项编号(0-4):\n"); printf("------------------------\n"); printf("1————入录成绩\n"); printf("2————统计成绩\n"); printf("3————处理学籍\n"); printf("4————创新功能\n"); printf("0————退出系统\n"); }
六、文件操作
在成绩排序和学籍处理过程中,程序涉及多个文件的读写操作:
std.dat
:用于存储按学号排序后的学生成绩。sort.dat
:用于存储按平均分排序后的学生成绩。next.dat
:用于存储新名册。
文件操作部分注意了错误处理,确保文件能正常打开和写入数据。
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 学籍 ” 获取。👈👈👈
三、可视化分析
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 学籍 ” 获取。👈👈👈
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 学籍 ” 获取。👈👈👈
👉👉👉 源码获取 关注【测试开发自动化】公众号,回复 “ 学籍 ” 获取。👈👈👈