西南交通大学高级语言程序设计(SCAI000812)第2次实验报告-学生成绩管理系统(链表版)
背景描述:
因为苦于网上到处都找不到答案,仅有的链表版还要收费,我就自己写了一个低配版链表,将就着用,想的是帮助明年以及后年的学弟学妹们。
题目描述:
实验目的:
- 掌握程序设计的基本算法和简单数据结构基础,能够综合运用基本控制语句、算法和数据结构,以及自顶向下、逐步求精的模块化设计方法,能够设计具有一定规模的系统级C语言程序,提高系统编程能力;
- 针对计算相关的复杂工程问题,能够使用恰当的算法和数据结构,完成计算、统计、排序、检索、匹配等相关的软件系统的构造、测试与实现。
实验要求:
- 掌握常用的程序调试和测试方法。
- 采用自顶向下、逐步求精的模块化设计思想设计一个简单的成绩管理系统。
- 报告要求解释说明采用了什么数据结构和算法,为什么选择这种数据结构或算法(系统设计描述),系统实现过程中遇到了哪些问题,这些问题是如何解决的,还有什么问题尚未解决,今后打算从哪几个方面进行改进,本设计的亮点和难点在哪里,实验结果如何,有哪些收获和学习体会(大作业反思);
- 编写程序完成以下实验(大作业)内容并完成实验报告。
实验内容:
某班有最多不超过30人(具体人数由实际输入决定)参加期末考试,最多不超过6门(具体门数由实际输入决定)。学生成绩管理系统是一个非常实用的程序,如果能够提前学习字符文件读写操作,把用户输入的数据存盘为字符文件,下次运行时读出,就更有用了。即编程实现如下菜单驱动的学生成绩管理系统:
(1)录入学生的学号、姓名和各科考试成绩;
(2)计算每门课程的总分和平均分;
(3)计算每个学生的总分和平均分;
(4)按每个学生的总分由高到低排出名次表;
(5)按每个学生的总分由低到高排出名次表;
(6)按学号由小到大排出成绩表;
(7)按姓名的字典顺序排出成绩表;
(8)按学号查询学生排名及其考试成绩;
(9)按姓名查询学生排名及其考试成绩;
(10)按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~59)5个类别,对每门课程分别统计每个类别的人数以及所占的百分比;
(11)输出每个学生的学号、姓名、各科考试成绩,以及每门课程的总分和平均分;
(12)将每个学生的记录信息写入文件(可选实现);
(13)从文件中读出每个学生的记录信息并显示(可选实现)。
要求程序在输入课程门数以及所有课程名称后,先显示如下菜单,并提示用户输入选项:
代码实现:
初始化部分是当时我自己定义的(方便函数调试)
有需求的话自己改一下
另外须知,本程序可能有些地方会与题目要求略微不符(能力不够),请大家见谅。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student{ //定义学生结构体(链表模式)
char name[15];
int sum;
int number;
int Math;
int Chinese;
int Physic;
int English;
int Biology;
int Chemical;
struct Student *next;
}student;
//测试用
student S[6] = {{"NULL",0,0,0,0,0,0,0,0},
{"b",0,102,99,99,99,99,99,99},
{"c",0,103,98,98,98,98,98,98},
{"d",0,104,97,97,97,97,97,97},
{"e",0,105,96,96,96,96,96,96},
{"f",0,106,95,95,95,95,95,95}};
//初始化,方便调试,并且头节点不存放数据
void sum(student *head) { //对每个学生的成绩求总分
student *p1 = head; //总分是在链表里面
while(p1->next != NULL) {
p1->sum += p1->Math;
p1->sum += p1->Chemical;
p1->sum += p1->Biology;
p1->sum += p1->Physic;
p1->sum += p1->English;
p1->sum += p1->Chinese;
p1 = p1->next;
}
p1->sum += p1->Math;
p1->sum += p1->Chemical;
p1->sum += p1->Biology;
p1->sum += p1->Physic;
p1->sum += p1->English;
p1->sum += p1->Chinese;
}
student *initialize(student *head) { //初始化配套函数
student *p1,*p2 = S; //将数组写进链表
head = S;
p1 = head;
p1->next = (p2 + 1);
p1 = p1->next;
p1->next = (p2 + 2);
p1 = p1->next;
p1->next = (p2 + 3);
p1 = p1->next;
p1->next = (p2 + 4);
p1 = p1->next;
p1->next = (p2 + 5);
p1 = p1->next;
p1->next = NULL;
sum(head);
return head;
}
student *record(int *counter,student *head) { //录入学生函数
student *p1 = head->next;
while(p1->next != NULL) { //找到末尾节点(尾插法)
p1 = p1->next;
}
//这里有一点小bug没有解决,本来是想询问是否继续录入的,但是没有实现
(*counter)++;
student *p;
p = (student *) malloc(sizeof (student));
printf("Input name:\n");
scanf("%s",p->name);
printf("Input grade:\n");
printf("(number/Math/Chinese/Physic/English/Biology/Chemical)\n");
scanf("%d%d%d%d%d%d%d",
&p->number,&p->Math,&p->Chinese,&p->Physic,
&p->English,&p->Biology,&p->Chemical);
sum(p);
p1->next = p;
p1 = p1->next;
p1->next = NULL;
return head;
}
void average_course_sum(student *head,int counter) { //计算每门课的平均成绩
student *p1 = head;
if(head->next == NULL) { //判断链表是否为空
printf("\nNo record!\n");
exit(0);
}
float math = 0,chinese = 0,physic = 0,english = 0,biology = 0,chemical = 0;
while(p1->next != NULL) { //计算每门课的总分
math += p1->Math;
chinese += p1->Chinese;
english += p1->English;
physic += p1->Physic;
biology += p1->Biology;
chemical += p1->Chemical;
p1 = p1->next;
}
math += p1->Math;
chinese += p1->Chinese;
english += p1->English;
physic += p1->Physic;
biology += p1->Biology;
chemical += p1->Chemical;
printf("\nSum:Math/Chinese/Physic/English/Biology/Chemical\n");
printf(" %.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f",math,chinese,physic,english,biology,chemical);
math = math/counter; //计算每门课平均分
chinese = chinese/counter;
english = english/counter;
physic = physic/counter;
biology = biology/counter;
chemical = chemical/counter;
printf("\nAverage:Math/Chinese/Physic/English/Biology/Chemical\n");
printf(" %.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",math,chinese,physic,english,biology,chemical);
}
void average_student_sum(student *head,int counter) {
//计算每个学生的总分和平均分
student *p1 = head->next,*p2 = head->next;
float aver = 0;
if(head->next == NULL) { //检查是否为空
printf("\nNo record!\n");
exit(0);
}
while(p1->next != NULL) { //找平均分
aver += p1->sum;
p1 = p1->next;
}
aver += p1->sum;
aver = aver / counter;
printf("\nAverage:\n");
printf(" %.2f",aver);
printf("\nStudent(Sum):\n");
while(p2->next != NULL) {
printf("%s:%d\n",p2->name,p2->sum);
p2 = p2->next;
}
printf("%s:%d\n",p2->name,p2->sum);
}
void show_name(student *head) { //排名功能配套的输出函数(后两个函数的配套)
student *p1 = head->next;
int i = 1;
printf("\nRangeTable:\n"); //输出排名表
while(p1->next != NULL) {
printf("%d\t%s\n",i,p1->name);
i++;
p1 = p1->next;
}
printf("%d\t%s\n",i,p1->name);
}
void range_sum_high(student *head) { //按成绩由高到低排序
if(head->next == NULL) { //检查是否为空
printf("\nNo record!\n");
exit(0);
}
student *p, *q, *tail;
tail = NULL;
while((head->next->next) != tail) //冒泡排序
{
p = head;
q = head->next;
while (q->next != tail)
{
if ((q->sum) < (q->next->sum))
{
p->next = q->next;
q->next = q->next->next;
p->next->next = q;
q = p->next;
}
q = q->next;
p = p->next;
}
tail = q;
}
show_name(head); //输出排名
}
void range_sum_low(student *head) { //按成绩由低到高排序
if(head->next == NULL) { //检查是否为空
printf("\nNo record!\n");
exit(0);
}
student *p, *q, *tail;
tail = NULL;
while((head->next->next) != tail) //冒泡排序
{
p = head;
q = head->next;
while(q->next != tail)
{
if((q->sum) > (q->next->sum))
{
p->next = q->next;
q->next = q->next->next;
p->next->next = q;
q = p->next;
}
q = q->next;
p = p->next;
}
tail = q;
}
show_name(head); //输出排名
}
void show_grade(student *head) { //与后两个函数配置的输出函数
student *p1 = head->next;
printf("\nGradeTable:\n"); //输出成绩表
printf("Number\tMath/Chinese/Physic/English/Biology/Chemical\n");
while(p1->next != NULL) {
printf("%s:\n",p1->name);
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",p1->number,p1->Math,p1->Chinese,p1->Physic,p1->English,p1->Biology,p1->Chemical);
p1 = p1->next;
}
printf("%s:\n",p1->name);
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",p1->number,p1->Math,p1->Chinese,p1->Physic,p1->English,p1->Biology,p1->Chemical);
}
void range_num_low(student *head) { //按学号从低到高输出
student *p, *q, *tail;
if(head->next == NULL) { //检查是否为空
printf("\nNo record!\n");
exit(0);
}
tail = NULL;
while((head->next->next) != tail) //冒泡排序
{
p = head;
q = head->next;
while(q->next != tail)
{
if((q->number) > (q->next->number))
{
p->next = q->next;
q->next = q->next->next;
p->next->next = q;
q = p->next;
}
q = q->next;
p = p->next;
}
tail = q;
}
show_grade(head); //输出成绩
}
void range_name_dir(student *head) { //按姓名排序输出
student *p, *q, *tail;
if(head->next == NULL) { //检查是否为空
printf("\nNo record!\n");
exit(0);
}
tail = NULL;
while((head->next->next) != tail) //冒泡排序
{
p = head;
q = head->next;
while(q->next != tail)
{
if(strcmp(p->name,q->next->name) > 0)
{
p->next = q->next;
q->next = q->next->next;
p->next->next = q;
q = p->next;
}
q = q->next;
p = p->next;
}
tail = q;
}
show_grade(head); //输出成绩表
}
void search_num(student *head) { //按学号查找成绩并输出
int num;
student *p1 = head->next;
printf("\nInput student number:\n");
scanf("%d",&num);
while(p1->number != num && p1->next != NULL) { //查找
p1 = p1->next;
}
if(p1->number != num) { //若没找到
printf("Not found!\n");
exit(0);
}
printf("Number %d Student's Grade:\n",num);
printf("Number\tMath/Chinese/Physic/English/Biology/Chemical\n");
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",p1->number,p1->Math,p1->Chinese,p1->Physic,p1->English,p1->Biology,p1->Chemical);
}
void search_name(student *head) { //按姓名查找成绩并输出
char name[15];
student *p1 = head->next;
printf("\nInput student name:\n");
scanf("%s",name);
while(strcmp(name,p1->name) != 0 && p1->next != NULL) { //查找
p1 = p1->next;
}
if(strcmp(name,p1->name) != 0) { //若没找到
printf("Not found!\n");
exit(0);
}
printf("\n%s's grade :\n",p1->name);
printf("Number\tMath/Chinese/Physic/English/Biology/Chemical\n");
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",p1->number,p1->Math,p1->Chinese,p1->Physic,p1->English,p1->Biology,p1->Chemical);
}
void judge(int subject,int *ex,int *go,int *mid,int *pa,int *fa) {
//判断函数,与下面两个函数配套
//记录每个分段的人数
subject = subject / 10;
switch(subject) {
case 0 :
case 1 :
case 2 :
case 3 :
case 4 :
case 5 :
(*fa)++;
break;
case 6 :
(*pa)++;
break;
case 7 :
(*mid)++;
break;
case 8 :
(*go)++;
break;
case 9 :
case 10 :
(*ex)++;
break;
default: break;
}
}
void ana(char *subject,student *head) { //判断函数(与下面一个函数配套)
int counter = 0; //写得很冗余,但是目前还不知道如何改进
int ex = 0,go = 0,mid = 0,pa = 0,fa = 0;
float excellent,good,middle,pass,fail;
student *p = head->next;
if(strcmp(subject,"math") == 0) { //查找是哪一个科目
while(p->next != NULL) { //找到就累加
judge(p->Math,&ex,&go,&mid,&pa,&fa);
p = p->next;
counter++;
}
judge(p->Math,&ex,&go,&mid,&pa,&fa);
counter++;
} else if(strcmp(subject,"chinese") == 0) {
while(p->next != NULL) {
judge(p->Chinese,&ex,&go,&mid,&pa,&fa);
p = p->next;
counter++;
}
counter++;
judge(p->Chinese,&ex,&go,&mid,&pa,&fa);
} else if(strcmp(subject,"english") == 0) {
while(p->next != NULL) {
judge(p->English,&ex,&go,&mid,&pa,&fa);
p = p->next;
counter++;
}
counter++;
judge(p->English,&ex,&go,&mid,&pa,&fa);
} else if(strcmp(subject,"physic") == 0) {
while(p->next != NULL) {
judge(p->Physic,&ex,&go,&mid,&pa,&fa);
p = p->next;
counter++;
}
counter++;
judge(p->Physic,&ex,&go,&mid,&pa,&fa);
} else if(strcmp(subject,"biology") == 0) {
while(p->next != NULL) {
judge(p->Biology,&ex,&go,&mid,&pa,&fa);
p = p->next;
counter++;
}
counter++;
judge(p->Biology,&ex,&go,&mid,&pa,&fa);
} else if(strcmp(subject,"chemical") == 0) {
while(p->next != NULL) {
judge(p->Chemical,&ex,&go,&mid,&pa,&fa);
counter++;
p = p->next;
}
counter++;
judge(p->Chemical,&ex,&go,&mid,&pa,&fa);
} else { //若没有查找到
printf("subject error!\n");
exit(0);
}
excellent = ((double)ex) / counter; //输出
good = ((double)go) / counter;
middle = ((double)mid) / counter;
pass = ((double)pa) / counter;
fail = ((double)fa) / counter;
printf("%s:\n",subject);
printf("excellent\tgood\tmiddle\tpass\tfail\n");
printf("%4d\t%4d\t%4d\t%4d\t%4d\n",ex,go,mid,pa,fa);
printf("%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",excellent,good,middle,pass,fail);
}
void sta_analysis(student *head) { //数据分析函数
ana("math",head);
ana("chinese",head);
ana("physic",head);
ana("english",head);
ana("biology",head);
ana("chemical",head);
}
void list_record(student *head) { //列出成绩表函数
student *p1 = head->next;
if(head->next == NULL) { //判断空
printf("\nNo record!\n");
exit(0);
}
printf("Number\tMath/Chinese/Physic/English/Biology/Chemical/Sum\n");
while(p1->next != NULL) { //遍历
printf("%s:\n",p1->name);
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",p1->number,p1->Math,p1->Chinese,p1->Physic,p1->English,p1->Biology,p1->Chemical,p1->sum);
p1 = p1->next;
}
printf("%s:\n",p1->name);
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",p1->number,p1->Math,p1->Chinese,p1->Physic,p1->English,p1->Biology,p1->Chemical,p1->sum);
}
void menu() { //显示菜单
printf("1.Input record\n");
printf("2.Calculate total and average score of every course\n");
printf("3.Calculate total and average score of every student\n");
printf("4.Sort in descending order by total score of every student\n");
printf("5.Sort in ascending order by total score of every student\n");
printf("6.Sort in ascending order by number\n");
printf("7.Sort in dictionary order by name\n");
printf("8.Search by number\n");
printf("9.Search by name\n");
printf("10.Statistic analysis for every course\n");
printf("11.List record\n");
printf("12.Menu\n");
printf("0.Exit\n");
}
int main() { //主函数
int counter = 6;
student *head = NULL;
menu(); //显示菜单
head = initialize(head); //初始化
while(1) {
int choice;
printf("Please enter your choice:\n");
scanf("%d",&choice);
printf("\n");
switch (choice) {
case 1 :
head = record(&counter,head);
break;
case 2 :
average_course_sum(head,counter);
break;
case 3 :
average_student_sum(head,counter);
break;
case 4 :
range_sum_high(head);
break;
case 5 :
range_sum_low(head);
break;
case 6 :
range_num_low(head);
break;
case 7 :
range_name_dir(head);
break;
case 8 :
search_num(head);
break;
case 9 :
search_name(head);
break;
case 10 :
sta_analysis(head);
break;
case 11 :
list_record(head);
break;
case 12 :
menu();
break;
case 0 :
goto End;
default:
printf("\nerror!\n");
}
}
End:
return 0;
}