数据结构课设——成绩分析问题

一、实验题目

【问题描述】

录入、保存一个班级学生多门课程的成绩,并对成绩进行分析。

【基本要求】

(1)通过键盘输入各学生的多门课程的成绩,建立相应的文件 input.dat。

(2)对文件 input.dat 中的数据进行处理,要求具有如下功能:

        1) 按各门课程成绩排序,并生成相应的文件输出。

        2) 计算每人的平均成绩,按平均成绩排序,并生成文件。

        3) 求出各门课程的平均成绩、最高分、最低分、不及格人数、60~69 分人数、70~79分         人数、80~89 分人数、90 分以上人数。

        4) 根据姓名或学号查询某人的各门课成绩,重名情况也能处理。

  • 参考成绩表如下:

二、需求分析

  1. 设计“学生成绩分析系统”,使其完成对学生成绩的建立,遍历,查询,排序,成绩分析等操作。
  2. 数据包括:学生学号,姓名,数学成绩,英语成绩,计算机成绩,平均成绩等。
  3. 通过程序建立dat文件,存储学生成绩信息。

三、模块功能

  1. 学生成绩建立:主要完成进入系统后的学生信息录入及在操作过程中需要的学生信息添加,将学生信息加进input.dat文件。
  2. 排序:按照不同的课程(数学、英语、计算机)或者平均成绩,输出在控制台的同时,对其排序生成不同的dat文件。
  3. 成绩分析:输出各门课程的平均成绩、最高分、最低分、不及格人数、60~69分人数、70~79分人数、80~89分人数、90分以上人数。
  4. 查询:按照不同信息(学号、姓名)进行查询。姓名查询时解决重名问题。

四、概要设计

1.流程图

 2.存储结构:使用顺序表的线性结构存储学生成绩。

typedef struct {
    char number[20];
    char name[20];
    double mathscore;
    double englishscore;
    double computerscore;
    double averscore;
}student;
typedef struct{
    student *elem;//指向数据元素的基地址
    int length;//线性表的当前长度
}SqList;

五、详细设计

//顺序表
typedef struct {
    char number[20];
    char name[20];
    double mathscore;
    double englishscore;
    double computerscore;
    double averscore;
}student;
typedef struct{
    student *elem;//指向数据元素的基地址
    int length;//线性表的当前长度
}SqList;

// 构造空的顺序表 L,顺序表初始化
int InitList(SqList *L)  
{ 
    L->elem=(student *)malloc(sizeof(student)*MAX);; //malloc 函数开辟存储空间
    if(!L->elem)
        exit(OVERFLOW); 
    L->length=0; 
    return OK; 
} 
//录入
void luru(SqList &s){
    printf("请输入学生人数:");
    int n;
    scanf("%d", &n);
    s.length+=n;//方便后续数据直接插入,顺序表长度直接增加
    for (int i = 0; i < n; i++)
    {
        printf("输入第%d个学生的信息:\n",i+1);
        printf("学号:");
        scanf("%s", &s.elem[i].number);
        printf("姓名: ");
        scanf("%s", &s.elem[i].name);
        printf("数学成绩为:");
        scanf("%lf",&s.elem[i].mathscore);
        printf("英语成绩为:");
        scanf("%lf",&s.elem[i].englishscore);
        printf("计算机成绩为:");
        scanf("%lf",&s.elem[i].computerscore);
        printf("---------------------------------------\n");
    }
}
//定义函数向文件输入学生的数据
void shuchu(SqList &s,FILE *fp){
    int i;
    if((fp=fopen("input.dat","w"))==NULL){
        printf("不能打开文件!\n");
        return ; 
    } 
    //挨个遍历加入文件
    for(i=0;i<s.length;i++){
        fprintf(fp,"学号:%s\t姓名:%s\t数学成绩:%.1lf\t英语成绩:%.1lf\t计算机成绩:%.1lf\t平均分:%.1lf\n",
            s.elem[i].number,s.elem[i].name,s.elem[i].mathscore,
            s.elem[i].englishscore, s.elem[i].computerscore, s.elem[i].averscore);
    }    
    fclose(fp);//关闭文件,释放缓存
}
//对每个科目的成绩进行排序 ,从大到小
//数学
void mathsort(SqList &s,FILE *fp11){
    student temp;
    int i,j; 
    if((fp11=fopen("数学成绩排序.dat","w"))==NULL){
        printf("不能打开文件!\n");
        return ; 
    } 
    for(i=0;i<s.length;i++){
        s.elem[i].averscore=(s.elem[i].computerscore+s.elem[i].englishscore+s.elem[i].mathscore)/3;
    }
    for(i=0;i<s.length-1;i++){
        for(j=0;j<s.length-1-i;j++){
            if(s.elem[j].mathscore<s.elem[j+1].mathscore){
                temp=s.elem[j];
                s.elem[j]=s.elem[j+1];
                s.elem[j+1]=temp;
            }
        }
    }
    printf("数学排序:\n");
    fprintf(fp11,"数学排序:\n");
    for(i=0;i<s.length;i++){
        fprintf(fp11,"学号:%s\t姓名:%s\t数学成绩:%.1lf\t\n",
            s.elem[i].number,s.elem[i].name,s.elem[i].mathscore);
        printf("学号:%s\t姓名:%s\t数学成绩:%.1lf\t\n",
            s.elem[i].number,s.elem[i].name,s.elem[i].mathscore);
    }
    fclose(fp11);
}
//英语
void englishsort(SqList &s,FILE *fp12){
    student temp;
    int i,j; 
    if((fp12=fopen("英语成绩排序.dat","w"))==NULL){
        printf("不能打开文件!\n");
        return ; 
    } 
    for(i=0;i<s.length;i++){
        s.elem[i].averscore=(s.elem[i].computerscore+s.elem[i].englishscore+s.elem[i].mathscore)/3;
    }
    for(i=0;i<s.length-1;i++){
        for(j=0;j<s.length-1-i;j++){
            if(s.elem[j].englishscore<s.elem[j+1].englishscore){
                temp=s.elem[j];
                s.elem[j]=s.elem[j+1];
                s.elem[j+1]=temp;
            }
        }
    }
    printf("英语排序:\n");
    fprintf(fp12,"英语排序\n");
    for(i=0;i<s.length;i++){
        fprintf(fp12,"学号:%s\t姓名:%s\t英语成绩:%.1lf\t\n",
            s.elem[i].number,s.elem[i].name,s.elem[i].englishscore);
        printf("学号:%s\t姓名:%s\t数学成绩:%.1lf\t英语成绩:%.1lf\t\n",
            s.elem[i].number,s.elem[i].name,s.elem[i].mathscore,
            s.elem[i].englishscore, s.elem[i].computerscore, s.elem[i].averscore);
    }
    fclose(fp12);
}
//计算机
void computersort(SqList &s,FILE *fp13){
    student temp;
    int i,j; 
    if((fp13=fopen("计算机成绩排序.dat","w"))==NULL){
        printf("不能打开文件!\n");
        return ; 
    } 
    for(i=0;i<s.length;i++){
        s.elem[i].averscore=(s.elem[i].computerscore+s.elem[i].englishscore+s.elem[i].mathscore)/3;
    }    
    for(i=0;i<s.length-1;i++){
        for(j=0;j<s.length-1-i;j++){
            if(s.elem[j].computerscore<s.elem[j+1].computerscore){
                temp=s.elem[j];
                s.elem[j]=s.elem[j+1];
                s.elem[j+1]=temp;
            }
        }
    }
    printf("计算机排序:\n");
    fprintf(fp13,"计算机排序:\n");
    for(i=0;i<s.length;i++){
        fprintf(fp13,"学号:%s\t姓名:%s\t计算机成绩:%.1lf\t\n",
            s.elem[i].number,s.elem[i].name, s.elem[i].computerscore);
        printf("学号:%s\t姓名:%s\t计算机成绩:%.1lf\n",
            s.elem[i].number,s.elem[i].name, s.elem[i].computerscore);
    }
    fclose(fp13);
} 
//定义函数average,向文件输入学生的各科平均成绩
void average(SqList s,FILE *fp2)  
{
    int i,j;
    student temp;
    if((fp2=fopen("平均成绩排序.dat","w"))==NULL){
        printf("不能打开文件!");
        return ; 
    } 
    for(i=0;i<s.length;i++){
        s.elem[i].averscore=(s.elem[i].computerscore+s.elem[i].englishscore+s.elem[i].mathscore)/3;
    }
    for(i=0;i<s.length-1;i++){
        for(j=0;j<s.length-1-i;j++){
            if(s.elem[j].averscore<s.elem[j+1].averscore){
                temp=s.elem[j];
                s.elem[j]=s.elem[j+1];
                s.elem[j+1]=temp;
            }
        }
    }
    printf("按平均分排序:\n");
    fprintf(fp2,"按平均分排序:\n");
    for(i=0;i<s.length;i++){
        fprintf(fp2,"学号:%s\t姓名:%s\t数学成绩:%.1lf\t英语成绩:%.1lf\t计算机成绩:%.1lf\t平均分:%.1lf\n",
            s.elem[i].number,s.elem[i].name,s.elem[i].mathscore,
            s.elem[i].englishscore, s.elem[i].computerscore, s.elem[i].averscore);
        printf("学号:%s\t姓名:%s\t数学成绩:%.1lf\t英语成绩:%.1lf\t计算机成绩:%.1lf\t平均分:%.1lf\n",
            s.elem[i].number,s.elem[i].name,s.elem[i].mathscore,
            s.elem[i].englishscore, s.elem[i].computerscore, s.elem[i].averscore);
    }        
    fclose(fp2);
} 
//成绩分段
int fenduan(double x){
    if(x<60) return 0;
    else if(60<=x&&x<70) return 1;
    else if(70<=x&&x<80) return 2;
    else if(80<=x&&x<90) return 3;
    else if(90<=x&&x<=100) return 4;
}
//成绩分析,输出求出各门课程的平均成绩、最高分、最低分、不及格人数、
//60~69 分人数、70~79 分人数、80~89 分人数、90 分以上人数
void fenxi(SqList &s){
    double math_result[10],english_result[10],computer_result[10];
    for(int i=0;i<=9;i++){
        math_result[i]=0;
        english_result[i]=0;
        computer_result[i]=0;
    }
    math_result[6]=s.elem[0].mathscore;
    english_result[6]=s.elem[0].englishscore;
    computer_result[6]=s.elem[0].computerscore;
    math_result[7]=s.elem[0].mathscore;
    english_result[7]=s.elem[0].englishscore;
    computer_result[7]=s.elem[0].computerscore;
    for ( int i = 0; i < s.length; i++)
    {
        //每科总成绩
        math_result[0]+=s.elem[i].mathscore;
        english_result[0]+=s.elem[i].englishscore;
        computer_result[0]+=s.elem[i].computerscore;
        //分数段统计
        //数学
        int q1=fenduan(s.elem[i].mathscore);
        switch (q1)
        {
        case 0:
            math_result[1]=math_result[1]+1;
            break;
        case 1:
            math_result[2]=math_result[2]+1;
            break;
        case 2:
            math_result[3]=math_result[3]+1;
            break;
        case 3:
            math_result[4]=math_result[4]+1;
            break;
        case 4:
            math_result[5]=math_result[5]+1;
        }
        
        //英语
        int q2=fenduan(s.elem[i].englishscore);
        switch (q2)
        {
        case 0:
            english_result[1]=english_result[1]+1;
            break;
        case 1:
            english_result[2]=english_result[2]+1;
            break;
        case 2:
            english_result[3]=english_result[3]+1;
            break;
        case 3:
            english_result[4]=english_result[4]+1;
            break;
        case 4:
            english_result[5]=english_result[5]+1;
            break;
        }
        //计算机
        int q3=fenduan(s.elem[i].computerscore);
        switch (q3)
        {
        case 0:
            computer_result[1]=computer_result[1]+1;
            break;
        case 1:
            computer_result[2]=computer_result[2]+1;
            break;
        case 2:
            computer_result[3]=computer_result[3]+1;
            break;
        case 3:
            computer_result[4]=computer_result[4]+1;
            break;
        case 4:
            computer_result[5]=computer_result[5]+1;
            break;
        }
        //最大最小值
        if(s.elem[i].mathscore>math_result[6]){
            math_result[6]=s.elem[i].mathscore;
        }
        if(s.elem[i].englishscore>english_result[6]){
            english_result[6]=s.elem[i].englishscore;
        }
        if(s.elem[i].computerscore>computer_result[6]){
            computer_result[6]=s.elem[i].computerscore;
        }
        if(s.elem[i].mathscore<math_result[7]){
            math_result[7]=s.elem[i].mathscore;
        }
        if(s.elem[i].englishscore<english_result[6]){
            english_result[7]=s.elem[i].englishscore;
        }
        if(s.elem[i].computerscore<computer_result[7]){
            computer_result[7]=s.elem[i].computerscore;
        }
    }
    //平均分
    math_result[0] = math_result[0] / s.length;
    english_result[0] = english_result[0] / s.length;
    computer_result[0] = computer_result[0] / s.length;
    
    printf("数学课的平均分为:%.1lf\n",math_result[0]);
    printf("数学课分数不及格人数为:%.lf\n",math_result[1]);
    printf("数学课分数在60~69的人数为:%.lf\n",math_result[2]);
    printf("数学课分数在70~79的人数为:%.lf\n",math_result[3]);
    printf("数学课分数在80~89的人数为:%.lf\n",math_result[4]);
    printf("数学课分数在90~100的人数为:%.lf\n",math_result[5]);
    printf("数学课分数最高为:%.1lf\n",math_result[6]);
    printf("数学课分数最低为:%.1lf\n",math_result[7]);
    printf("英语课的平均分为:%.1lf\n",english_result[0]);
    printf("英语课分数不及格人数为:%.lf\n",english_result[1]);
    printf("英语课分数在60~69的人数为:%.lf\n",english_result[2]);
    printf("英语课分数在70~79的人数为:%.lf\n",english_result[3]);
    printf("英语课分数在80~89的人数为:%.lf\n",english_result[4]);
    printf("英语课分数在90~100的人数为:%.lf\n",english_result[5]);
    printf("英语课分数最高为:%.1lf\n",english_result[6]);
    printf("英语课分数最低为:%.1lf\n",english_result[7]);
    printf("计算机课的平均分为:%.1lf\n",computer_result[0]);
    printf("计算机课分数不及格人数为:%.lf\n",computer_result[1]);
    printf("计算机课分数在60~69的人数为:%.lf\n",computer_result[2]);
    printf("计算机课分数在70~79的人数为:%.lf\n",computer_result[3]);
    printf("计算机课分数在80~89的人数为:%.lf\n",computer_result[4]);
    printf("计算机课分数在90~100的人数为:%.lf\n",computer_result[5]);
    printf("计算机课分数最高为:%.1f\n",computer_result[6]);
    printf("计算机课分数最低为:%.1f\n",computer_result[7]);
}
//学号查找
void xuehao(SqList &s,char key[]){
    int count=0;
    for(int i=0;i<s.length;i++){
        s.elem[i].averscore=(s.elem[i].computerscore+s.elem[i].englishscore+s.elem[i].mathscore)/3;
    }
    for ( int i = 0; i < s.length; i++)
    {//是否匹配
        if (strcmp(s.elem[i].number,key) == 0)
        {
            printf("第%d个学生:\n学号:%s\n姓名:%s\n数学成绩:%.1lf\n英语成绩:%.1lf\n计算机成绩:%.1lf\n平均分:%.1lf\n",
                i+1,s.elem[i].number,s.elem[i].name,s.elem[i].mathscore,
                s.elem[i].englishscore, s.elem[i].computerscore, s.elem[i].averscore);
            count=1;
        }
    }
    if(count==0){
        printf("查找的学生不存在\n");
    }
}
//姓名查找
void xingming(SqList &s,char ch[]){
    int flag=0,count;
    char num[20];
    for(int i=0;i<s.length;i++){
        s.elem[i].averscore=(s.elem[i].computerscore+s.elem[i].englishscore+s.elem[i].mathscore)/3;
    }
    for ( int i = 0; i < s.length; i++)
    {
        if (strcmp(s.elem[i].name,ch) == 0)
        {
            flag = flag+1;
            count=i;
        }
    }
    //避免重名,学号不会重复
    if(flag>1){
        printf("出现重名,请输入待查找同学学号:\n");
        scanf("%s",&num);
        xuehao(s,num);
    }
    else if(flag==1){
        printf("第%d个学生:\n学号:%s\n姓名:%s\n数学成绩:%.1lf\n英语成绩:%.1lf\n计算机成绩:%.1lf\n平均分:%.1lf\n",
            count+1,s.elem[count].number,s.elem[count].name,s.elem[count].mathscore,
            s.elem[count].englishscore, s.elem[count].computerscore, s.elem[count].averscore);
    }
    else{
        printf("查找的学生不存在!\n");
    }
}

六、调试分析

        编写程序之前,首先要对如何设计程序有一个清晰的思路,清楚怎么去设计,然后系统分析与系统设计,最后是代码设计与调试。设计过程中,我们根据以往学过的数据结构的概念、理论和方法,设计程序的基本步骤,来完成这个应用,同时也加深了我们对数据结构的掌握程度。这个过程中我是用了顺序存储的方法,并通过switch语句进行任务选择。

        同时,还得注意要把程序编写得易懂,让界面清楚。调试过程中会遇到输入超出范围等容易因为手误犯的错误,然后导致程序debug好久才发现问题。同时调试过程中也会出现一些粗心的小问题,但都一一解决。

1.录入,有一些因为粗心问题很难debug的错误,比如一个scanf输入中,忘写&,导致部分数据一直为空,检查了一晚上都没有解决问题,终于在第二天检查的过程中发现问题所在,在录入过程中调试出现的主要问题就是定义函数把数据传到input.dat文件,通过查询资料了解到传入文件的方法,以及打开dat文件的方式,然后通过键盘把数据传进去。时间复杂度都为O(n)。

2.根据不同的课程进行成绩排序,使用冒泡排序的算法,分别对三门课程进行排序,输出所有人的成绩,。按顺序输出,时间复杂度为O(n2)。

 

 

 

 3.个人平均成绩及排序

4.各科成绩统计,在这个模块因为数据较多,我思考了很多到底怎么样才能把所有的分析结果存入,终于想到引用三个新的数组代表不同课程,数组的0,1,2,3,4,5,6,7分别代表不同的数据,结果与下面截图一一对应。

 

 5.查找,查找的过程中,在调试过程中会遇到输入超出范围等容易因为手误犯的错误,然后导致程序debug好久才发现问题。这个过程遇到的一个问题是有时查询的时候发现不能显示学生姓名,通过网上查找资料方式我明白了是因为存储空间不足,造成数据溢出,是我在输入学号时数字过长,导致不必要的程序错误甚至崩溃。

(1)按学号查找

 (2)按姓名查找,如果重名则要求重新输入学号,因为学号查找结果唯一。

 

课程设计总结

        本次课程设计,我学会了如何用数据结构的知识编写一个简单的应用程序,受益匪浅。我选取的题目是《成绩分析问题》。选取的数据结构类型为顺序表,我建立一个顺序表并在其中添加数据,分析数据,排序数据,查找数据等功能,通过实践深刻理解了顺序表的概念,并巩固顺序表的各种操作。也回顾了数据结构课程所学的知识,比如排序用到的冒泡排序等,将新知识与旧知识结合起来,在温习旧知识的同时学习新知识。同时,我还学习了dat文件的传入,如何通过键盘输入数据到.dat文件中。  

        实验中也遇到了很多问题,通过上网查询相关资料等方式来解决自己在实验过程中遇到的困惑和难题。程序编写完成后,我并没有得到意想的结果,而是一遍又一遍地调试和完善它。比如有时查询的时候发现不能显示学生姓名,通过网上查找的方式我明白了是因为存储空间不足,造成数据溢出,是我在输入学号时数字过长,导致不必要的程序错误甚至崩溃。还有一些因为粗心问题很难debug的错误,比如一个scanf输入中,忘写&,导致部分数据一直为空,检查了一晚上都没有解决问题,终于在第二天检查的过程中发现问题所在。

        当然也有由于本课题中的许多知识点都没有学过都要靠自己到课外的资料中去查找,dat文件的写入方式我不是很熟悉,通过网上查找资料了解到了dat文件并不是一种标准文件。许多文件都使用这个扩展名,但文件含义不同。而许多数据分析软件也用这个扩展名保存数据。所以这要看具体的软件情况来定。dat文件,可以按照扩展名来看就是data的意思,即数据文件,这类文件并没有进行绝对化的定义,可以使视频文件也可以是纯文本文件。我也不是很熟悉dat文件的打开方式,通过百度发现,纯文本文件可以用记事本打开,正好本次程序设计存储的信息就是纯文本文件,所以我找到了解决办法。

        在调试的时候难免出现这样那样的错误,幸运的是,通过一次次修改都一一解决。这次编程后,我也体会到编程是不容易的。但是无论过程多难,看到自己编写出来的程序,得到最终的结果,心里也是快乐的,幸福的这也使我在编写过程中,为把程序写好而努力着。

        通过这次课程设计,增加了我对软件技术的了解,虽然还不明确软件技术包含的具体内容,但从学习数据结构这门课程开始,已发现程序设计的好处,它对我们数学的学习也有很大的帮助。在学习数据结构的过程中也学到和巩固了许多计算机应用基础知识,对计算机的机体也有了一个较为详细的了解。在具体操作中对这学期所学的数据结构理论知识得到巩固加强,达到实训的目的,也发现自己的不足之处,为我们以后的数据结构学习奠定了基础,同时体会到数据结构具有的语句简洁,使用灵活,执行效率高等特点。发现上机操作的重要作用,特别是对数组和循环有了深刻的理解。通过实际操作,学会 数据结构程序编程的基本步骤、基本方法,开发了自己的逻辑思维能力,培养了分析问题、解决问题的能力。 

  • 30
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 41
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值