学生成绩管理系统
(一)使用单向链表和文件作为基本数据结构,设计一个学生成绩管理程序,管理某学校学生成绩。
(二)数据结构
⑴ 定义单向链表类型StuLink:链表结点包含num、name、sex、score、grade、rank、nxet六个数据项,分别代表学生的学号、姓名、性别、成绩、等级、名次和指向下一个结点的指针,其中:学号、姓名、性别、成绩是输入项,等级、名次是计算项。
(2)定义数据文件student.dat:必须使用数据文件来存储学生信息,每行一个学生信息,各数据项以一个空格隔开。
(三)程序功能
⑴ 设计main函数
A.开始运行程序时,从数据文件中逐行读取学生信息生成学生链表,退出程序时将学生链表中的数据逐行保存到文件。
B.建立一个至少二级菜单系统
一级菜单:包括“1-数据维护,2-数据查询,3-统计分析,4-报表输出,0-退出”几项功能。二级菜单:数据维护包括“数据插入、数据修改、数据删除、返回”几项功能。数据查询包括“学号查询、不及格学生查询、返回”几项功能。统计分析包括“成绩名次计算、成绩频度分析、返回”几项功能。报表输出包括“排序显示学生信息、分页显示学生信息、返回”几项功能。
C.开始运行程序从数据文件中逐行读取学生信息生成学生链表。
D. 退出程序时将学生链表中的数据逐行保存到文件。
(2) 设计ReadFromFile函数:从数据文件中逐行读取学生信息生成学生链表。
(3) 设计SaveToFile函数:先将学生链表按学号升序排序,再将学生链表中的数据逐行保存到数据文件。
(4)设计InsertNode函数:在链表尾插入一个新结点。新结点的学号是链表中最大学号加1,姓名和成绩从键盘输入(注意:成绩必须在[0,100]区间的整数),根据成绩计算等级。注意:插入结点会导致链表中各结点名次的变化。
(5)设计EditNode函数:修改链表中指定学号的结点(学号不能修改,成绩必须在[0,100]区间的整数)。注意:当修改成绩时会导致等级和名次的变化。
(6)设计DeleteNode函数:删除链表中指定学号的结点。注意:删除结点会导致链表中各结点名次的变化。
(7)设计QueryNode函数:查询链表中指定学号的结点,并显示查询结果。
(8)设计QueryLink函数:查询链表中不及格的所有结点,并显示查询结果。
(9)设计RankLink函数:计算链表中每个结点的名次。名次规则:按成绩降序排名,从第1名开始依次排名,若出现并列名次,则名次需要叠加。例如,若出现5个并列第1名,则没有第2名,下一个名次是第6名,依此类推。
(10) 设计AnalysisLink函数:统计并返回各等级人数。等级标准:
A:90及以上 B:80及以上 C:70及以上 D:60及以上 E:60以下
(11)设计SortLink函数:按指定数据项的顺序【学号(升序)】或者【成绩(降序)】对学生链表进行排序。
(12) 设计OutputLink_1函数:按指定数据项的顺序【学号(升序)】或者【成绩(降序)】输出学生成绩表、各等级人数。学生成绩表每行输出一个学生信息(依次为学号、姓名、性别、成绩、等级和名次,各项间以1个空格隔开),各等级人数分行输出。
(13) 设计OutputLink_2函数:分页显示全部学生的信息。分页功能:每页显示10个学生信息,有上一页、下一页、首页和最后一页的翻页功能。
(四)数据约束
⑴ 学号:整型、不能重复、从1开始依次递增、由程序自动计算产生,不能修改。
⑵ 性别:男和女,必须使用枚举类型。
⑶ 成绩:整型,取值范围为0-100。
⑷ 其他:至少有两级菜单。
.c文件
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include "list.h" //引入自己写的外部头文件
//主函数
void main()
{
int sel;
void Data_maintenance(struct Node* listHead);
void Data_query(struct Node* listHead);
void Statistical_analysis(struct Node* listHead);
void report_output(struct Node* listHead);
void clear();
readInfoFromFile("student.txt",list);
SortLinkByNumber(list);
Analysis(list);
RankLink(list);
system("cls");
while(1)
{
printf("\t\t\t\t\t 学生成绩管理系统 \n");
printf("\t\t\t\t1—数据维护 2—数据查询 \n");
printf("\t\t\t\t3—统计分析 4—报表输出 \n");
printf("\t\t\t\t0—退出系统 \n");
printf("\t\t\t\t请输入您的选项: ");
scanf("%d",&sel);
switch(sel)
{
case 1:
Data_maintenance(list); //调用子菜单一
system("cls");
break;
case 2:
Data_query(list); //调用子菜单二
system("cls");
break;
case 3:
Statistical_analysis(list); //调用子菜单三
system("cls");
break;
case 4:
report_output(list); //调用子菜单四
system("cls");
break;
case 0:
saveInfoToFile("student.txt",list);
printf("\t\t\t\t\t【已退出系统】\n\t\t\t\t");
system("pause");
exit(0);
break;
default:
printf("\t\t\t\t\t数据输入错误,请重新输入");
break;
}
}
saveInfoToFile("student.txt",list);
system("pause");
}
子菜单一
//1-数据维护
void Data_maintenance(struct Node* listHead)
{
int sel,num;
struct student data;
printf("\t\t\t\t1—数据插入 2—数据删除 \n");
printf("\t\t\t\t3—数据修改 4—返回一级菜单 \n");
printf("\t\t\t\t请输入您的选项:");
scanf("%d",&sel);
switch(sel)
{
case 1:
printf("\t\t\t\t请输入要插入的学生的姓名——性别【0表示女生,1表示男生】——成绩 \n");
printf("\t\t\t\t");
scanf("%s%d%d",data.name,&data.sex,&data.score);
insertNodeByHead(listHead,data);
SortLinkByNumber(listHead);
Analysis(listHead);
RankLink(listHead);
clear();
break;
case 2:
SortLinkByNumber(listHead);
printf("\t\t\t\t请输入要删除的信息的学生的学号:");
scanf("%d",&num);
DeleteNode(listHead,&num);
printf("\t\t\t\t删除该学生后的学生信息如下:\n");
Analysis(listHead);
RankLink(listHead);
printf("\t\t\t\t学号——姓名——性别——成绩——等级——名次:\n");
printflist(listHead);
clear();
break;
case 3:
SortLinkByNumber(listHead);
printf("\t\t\t\t请输入要修改信息的学生的学号:");
scanf("%d",&num);
EditNode(listHead,num);
clear();
break;
case 4:
system("cls");
break;
default:
printf("\t\t\t\t输入数据错误,请输入[1,4]区间的整数 \n");
clear();
break;
}
}
子菜单二
//2-数据查询
void Data_query(struct Node* listHead)
{
int sel,num;
struct Node* curNode;
printf("\t\t\t\t1—学号查询 2—不及格学生查询 \n");
printf("\t\t\t\t3—返回一级菜单 \n");
printf("\t\t\t\t请输入您的选项:");
scanf("%d",&sel);
switch(sel)
{
case 1:
printf("\t\t\t\t请输入需要查询学生的学号:");
scanf("%d",&num);
curNode=QueryNodeByNumber(listHead,num);
printfcurNode(curNode);
clear();
break;
case 2:
printf("\t\t\t\t不及格的学生如下 \n");
printf("\t\t\t\t学号 姓名 性别 成绩 等级 名次 \n");
QueryLink(listHead)