西南交通大学高级语言程序设计(SCAI000812)第2次实验报告-学生成绩管理系统(链表版)

背景描述:

因为苦于网上到处都找不到答案,仅有的链表版还要收费,我就自己写了一个低配版链表,将就着用,想的是帮助明年以及后年的学弟学妹们。

题目描述:

实验目的:

  1. 掌握程序设计的基本算法和简单数据结构基础,能够综合运用基本控制语句、算法和数据结构,以及自顶向下、逐步求精的模块化设计方法,能够设计具有一定规模的系统级C语言程序,提高系统编程能力;
  2. 针对计算相关的复杂工程问题,能够使用恰当的算法和数据结构,完成计算、统计、排序、检索、匹配等相关的软件系统的构造、测试与实现。

实验要求:

  1. 掌握常用的程序调试和测试方法。
  2. 采用自顶向下、逐步求精的模块化设计思想设计一个简单的成绩管理系统。
  3. 报告要求解释说明采用了什么数据结构和算法,为什么选择这种数据结构或算法(系统设计描述),系统实现过程中遇到了哪些问题,这些问题是如何解决的,还有什么问题尚未解决,今后打算从哪几个方面进行改进,本设计的亮点和难点在哪里,实验结果如何,有哪些收获和学习体会(大作业反思)
  4. 编写程序完成以下实验(大作业)内容并完成实验报告。

实验内容:

某班有最多不超过30人(具体人数由实际输入决定)参加期末考试,最多不超过6门(具体门数由实际输入决定)。学生成绩管理系统是一个非常实用的程序,如果能够提前学习字符文件读写操作,把用户输入的数据存盘为字符文件,下次运行时读出,就更有用了。即编程实现如下菜单驱动的学生成绩管理系统:

1)录入学生的学号、姓名和各科考试成绩;

2)计算每门课程的总分和平均分;

3)计算每个学生的总分和平均分;

4)按每个学生的总分由高到低排出名次表;

5)按每个学生的总分由低到高排出名次表;

6)按学号由小到大排出成绩表;

7)按姓名的字典顺序排出成绩表;

8)按学号查询学生排名及其考试成绩;

9)按姓名查询学生排名及其考试成绩;

10)按优秀(90~100)、良好(80~89)、中等(70~79)、及格(60~69)、不及格(0~595个类别,对每门课程分别统计每个类别的人数以及所占的百分比;

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;
}