《数据结构课程设计(学生成绩管理系统)(22页).doc》由会员分享,可在线阅读,更多相关《数据结构课程设计(学生成绩管理系统)(22页).doc(22页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、-数据结构课程设计(学生成绩管理系统)-第 20 页目 录一、运行环境1一、运行环境1二、设计目的和意义2设计目的2设计意义2三、算法思想2四、模块划分5五、数据结构5六、程序流程图6七、程序源代码7八、程序调试过程分析17九、测试数据17十、测试结果及分析19十一、小结21参考文献22一、运行环境硬件环境:电脑二、设计目的和意义此次课程设计的目的是让学生在学习完C、数据结构等课程基础上,进一步掌握设计、实现较大系统的完整过程,包括系统分析、编码设计、系统集成、以及调试分析,熟练掌握数据结构的选择、设计、实现以及操作方法,为进一步的应用开发打好基础。此次设计意义在于让我们更好的去掌握C的基本语
2、法、函数以及Visual C+集成编译环境。掌握树、图、链表等基本数据结构及其应用。掌握程序流程以及基本应用方法。应用软件工程方面的知识,熟悉软件开发的流程。通过本课程设计,培养学生进行软件设计能力。首先进行需求分析,针对目标对象完成程序结构设计、对象设计、主要数据结构设计、输入输出设计、人机界面设计等。三、算法思想整个系统除了主函数外,另外还有12个函数,实现十大功能:菜单选择、输入功能、显示功能、查找功能、删除功能、排序功能、插入功能、保存功能、读取功能、修改。各个函数的详细设计说明分别如下:1、 主函数 main()利用无限次循环for(;)和swithch()实现各函数的调用,系统根据
3、输入的数字选项来调用相应的函数。2、 初始化函数 STUDENT *init()这是一个无参函数,里面只有一个语句,它的作用是使链表初始化,使head的值为NULL。比如:没有这个函数的话,在你没有输入任何数据的情况下,去执行显示功能的时候会显示一些乱码!3、 菜单选择函数 int menu_select();这是一个无参函数,主要实现“功能选择”的界面,在这个界面里有显示系统的九大功能,根据每个功能前面的序号进行选择,中间还显示系统当前的时间。等执行完每一个函数功能后,按任一键回到主界面也要通过这个函数来实现!4、 输入记录函数 STUDENT *create()这是一个无参函数,用来执行第
4、学生成绩记录的输入,当学生为0时停止输入,函数结束后,带回一个指向链表头的指针head。算法:先声明一个首节点head,并将head-next设为NULL。每输入一个数据就声明一个新节点p,把p-next设为NULL,并且链接到之前列表的尾端。5、 显示记录函数 void print(STUDENT *head)这是一个不返回值的有参函数,形参为“链表头的指针”,负责对全部学生成绩记录的输出,不足之处就是不能对学生成绩进行分页显示。算法:先将p结点的指针指向第一个结点,将p结点(即第一个结点)的数据输出。然后再将p结点的指针指向p指针的的指针(即下一结点),将p结点(即第一结点)的数据输出。重
5、复执行此步聚直到p指针指向NULL为止。6、 查找记录函数 void search(STUDENT *head)这是一个不返回值的有参函数,形参为“链表头的指针”,实现按姓名对某个学生进行查找,并显示所查找到的记录。算法:采用线性查找法往下一个节点查找。输入所要查找的学生的姓名s,设一个指针变量p,先指向第一个结点,当strcmp(p-name,s) & p != NULL时,使p后移一个结点,如果p!=NULL,输出p所指的结点。7、 删除记录函数 STUDENT *delete(STUDENT *head)这是一个有参函数,形参为“链表头的指针”,先输入要删除的学生记录的学号,找到后显示该
6、学生信息,等确认后便可按“Y”进行删除。算法:从p指向的第一个结点开始,检查该结点中的num值是否等于输入的要求删除的那个学号。如果相等就将该结点删除,如不相等,就将p后移一个结点,再如此进行下去,直到遇到表尾为止。8、排序函数 STUDENT *sort(STUDENT *head)这是一个有参函数,形参为“链表头的指针”,按学生成绩的平均分高低进行排序,还可以显示名次。9、修改函数 STUDENT *xiugai(STUDENT *head)这是一个有参数函数,形参为“链表头的指针”,首先按学生姓名对要修改的学生记录进行查找,然后对找到的记录进行修改。算法:采用线性查找法往下一个节点查找。
7、输入所要查找的学生的姓名s,设一个指针变量p,先指向第一个结点,当strcmp(p-name,s) & p != NULL时,使p后移一个结点,如果p!=NULL,修改p所指的结点的相关记录,修改完成后对记录进行输出,然后重新调用排序sort函数,对新修改的数据进行排序。10、 插入函数 STUDENT *insert(STUDENT *head,STUDENT *new)这是一个有参函数,形参有两个,一个是“链表头的指针”,一个是“待插入指针”,按照原来成绩平均分的高低进行插入,插入后会重新进行排序,并返回。算法:先将学生的成绩按平均分由高分到低分进行排序,再插入一个新生的结点,要求按平均分
8、的高低顺序插入。先用指针变量p0指向待插入的结点,p1指向第一个结点。如果p0-averageaverage,则待插入的结点不应插在p1所指的结点之前。此时将p1后移,并使p2指向刚才p1所指的结点。重复以上的步骤,直到p0-average=p1-average为止。这时将p0指向的结点插到p1所指结点之前。但是如果p1所指的已是表尾结点,则p1就不应后移了。如果p0-average比所有结点的average都小,则应将p0所指的结点插到链表末尾。如果插入的位置既不在第一个结点之前,又不在表尾结点之后,则将p0的值赋给p2-,使p2-next指向待插入的结点,然后将p1的值赋给p0-next,
9、使得p0-next指向p1指向的变量。如果插入位置为第一个结点之前,则将p0赋给head,将p1赋给p0-next。如果要插到表尾之后,应将p0赋给p1-next,NULL赋给p0-next。最后再调用排序的函数,将学生成绩重新排序.11、保存数据到文件函数 void save(STUDENT *head)这是一个不返回值的有参函数,形参为“链表头的指针”,可以把学生记录保存在电脑上由自己任意命名的二进制文件。12、从文件读数据函数 STUDENT *load()这是一个不返回值的有参函数,形参为“链表头的指针”,根据输入的文件地址进行读取。四、模块划分 学生成绩管理的设计,除了主函数和初始化
10、函数外,主要还设计了十个功能函数:菜单选择、输入功能、输出功能、查找功能、删除功能、排序功能、插入功能、保存功能、读取功能、修改函数。通过分组设计现实现部分功能函数说明如下:1、菜单选择:int menu_select(); 提供十种可以选择的操作,在main函数中通过switch语句调用菜单menu_select()函数,进入不同的功能函数中完成相关操作。2、输入功能:STUDENT *create(); 通过一个for循环语句的控制,可以一次完成无数条记录的输入。并将其存入链表。 3、输出功能:void print(STUDENT *head); 通过一个while的循环控制语句,在指针p
11、!=0时,完成全部学生记录的显示。知道不满足循环语句,程序再次回到菜单选择功能界面。4、查找功能:void search(STUDENT *head); 通过strcmp来判断是否找到所需查找的学生记录,在不满足该条件时,通过while语句完成结点的下移,最后若查找成功则完成显示。返回主菜单界面。5、删除功能: STUDENT *Delete(STUDENT *head); 按想要删除的学生的学号首先进行查找,通过指针所指向结点的下移来完成,如果找到该记录,则完成前后结点的连接,同时对以查找到的结点进行空间的释放,最后完成对某个学生记录进行删除,并重新存储。6、修改功能:STUDENT *xi
12、ugai(STUDENT *head);首先通过想核对想要修改的学生姓名进行查到,相当于调用一次查找函数search,如果查找成功则对数据进行修改,最后计算其总分和平均分,调用一次排序函数sort,重新进行排序,并重新存储记录。五、数据结构定义了一个typedef struct stu 的结构体数组,相关描述如下:#define LEN sizeof(STUDENT)typedef struct stu /*定义结构体数组用于缓存数据*/char num6;char name20;int score3;int sum;float average;int order;struct stu *ne
13、xt;STUDENT;六、程序流程图61、程序的总体模块流程图如下:删除学生记录读写文件对学生成绩进行排序查询学生记录修改学生记录输出学生记录输入学生记录初始化主界面插入学生记录退出学生成绩管理系统图6-162、删除学生记录流程图如下:P1=P2=head输入要删除的学生的学号Strcmp(P1-sum,s),P1!=NULL输出该记录P2-next=P1-.nextFree(P1)返回主菜单是P1指向下一个结点P2=P1否图6-26.3、插入学生记录流程图如下:P2=P1=headP0指向要插入的结点向P0输入要插入的学生信息P0-averageP1-average&P1-next!=NUL
14、LP2=P1 P1=P1-nextP2-next=P0 P0-next=P1调用排序函数sort返回主菜单是否图6-3七、程序源代码#include #include#include /*其它说明*/#include /*字符串函数*/#include /*字符操作函数*/#define LEN sizeof(STUDENT)typedef struct stu /*定义结构体数组用于缓存数据*/char num6;char name20;int score3;int sum;float average;int order;struct stu *next;STUDENT;/*函数原型*/ST
15、UDENT *init(); /*初始化函数*/int menu_select(); /*菜单函数*/STUDENT *create(); /*创建链表*/void print(STUDENT *head); /* 显示全部记录*/void search(STUDENT *head); /*查找记录*/STUDENT *Delete(STUDENT *head); /*删除记录*/STUDENT *sort(STUDENT *head); /*排序*/STUDENT *insert(STUDENT *head,STUDENT *New); /*插入记录*/STUDENT *xiugai(STU
16、DENT *head); /*修改记录*/void save(STUDENT *head); /*保存文件*/STUDENT *load(); /*读文件*/*主函数界面*/void main()STUDENT *head,New;head=init(); /*链表初始化,使head的值为NULL*/for(;) /*循环无限次*/switch(menu_select() case 1:head=create();break; case 2:print(head);break; case 3:search(head);break; case 4:head=Delete(head);break;
17、 case 5:head=sort(head);break; case 6:head=insert(head,&New);break; /*&new表示返回地址*/ case 7:save(head);break; case 8:head=load(); break; case 9:xiugai(head);break; case 10:exit(0); /*如菜单返回值为9则程序结束*/*初始化函数*/STUDENT *init()return NULL; /*返回空指针*/*菜单选择函数*/menu_select()int n;printf(*n);printf(tt Welcome to
18、n);printf(ntt The student score manage systemn);printf(*MENU*n);printf(ttt1. 输入学生记录n); /*输入学生成绩记录*/printf(ttt2. 输出学生记录n); /*显示*/printf(ttt3. 查找学生记录n); /*寻找*/printf(ttt4. 删除学生记录n); /*删除*/printf(ttt5. 将学生成绩进行排序n); /*排序*/printf(ttt6. 插入一个新的学生记录n); /*插入*/printf(ttt7. 保存记录n); /*保存*/printf(ttt8. 读取记录n); /
19、*读取*/printf(ttt9. 修改记录n); /*修改*/printf(ttt10. 退出n); /*退出*/printf(ntt 夏翠玉、陈洁丽.n);printf(*n);do printf(nttt输入您的选择(110):); scanf(%d,&n);while(n10); /*如果选择项不在19之间则重输*/return(n); /*返回选择项,主函数根据该数调用相应的函数*/*输入函数*/STUDENT *create()int i,s,k;int j=0;STUDENT *head=NULL,*p; /* 定义函数.此函数带回一个指向链表头的指针*/system(cls);
20、 printf(n请输入您想输入的学生个数:);scanf(%d,&k);for(j=0;jnum);if(p-num0=0) break; /*如果学号首字符为0则结束输入*/printf(输入姓名:);scanf(%s,p-name);printf(请分别输入语文、数学、英语的分数 %d scoresn,3);/*开始输入*/s=0; /*计算每个学生的总分,初值为0*/for(i=0;iscorei);if(p-scoreiscorei100) /*确保成绩在0100之间*/printf(Data error,please enter again.n);while(p-scoreisco
21、rei100);s=s+p-scorei; /*累加各门成绩*/p-sum=s; /*将总分保存*/p-average=(float)s/3;/*先用强制类型转换将s转换成float型,再求平均值*/p-order=0; /*未排序前此值为0*/p-next=head; /*将头结点做为新输入结点的后继结点*/head=p; /*新输入结点为新的头结点*/return(head); /* 显示全部记录函数*/void print(STUDENT *head)STUDENT *p; /*移动指针*/system(cls); p=head; /*初值为头指针*/printf(n*STUDENT*n
22、);printf(-n);printf(| 学号 | 姓名 | 语文 | 数学 | 英语 | 总分 | 平均成绩 | 名次 |n);printf(-n);while(p!=NULL) printf(| %4s | %-4s | %3d | %3d | %3d | %3d | % | %-5d|n, p-num,p-name,p-score0,p-score1,p-score2,p-sum,p-average,p-order); p=p-next;printf(-n);printf(*END*n);/*查找记录函数*/void search(STUDENT *head)STUDENT *p; /
23、* 移动指针*/char s5; /*存放姓名用的字符数组*/system(cls); printf(请输入查找者姓名.n);scanf(%s,s);p=head; /*将头指针赋给p*/while(strcmp(p-name,s) & p != NULL) /*当记录的姓名不是要找的,或指针不为空时*/p=p-next; /*移动指针,指向下一结点*/if(p!=NULL) /*如果指针不为空*/printf(n*FOUND*n);printf(-n);printf(| 学号 | 姓名 | 语文 | 数学 | 英语 | 总分 | 平均成绩 | 名次 |n);printf(-n);printf
24、(| %4s | %4s | %3d | %3d | %3d | %3d | % | %-5d|n, p-num,p-name,p-score0,p-score1,p-score2,p-sum,p-average,p-order);printf(-n);printf(*END*n);elseprintf(n无此记录.n,s); /*显示没有该学生*/*删除记录函数*/STUDENT *Delete(STUDENT *head)STUDENT *p1,*p2; /*p1为查找到要删除的结点指针,p2为其前驱指针*/char c,s6; /*s6用来存放学号,c用来输入字母*/system(cls
25、); printf(请输入要删除的学生的学号: );scanf(%s,s);p1=p2=head; /*给p1和p2赋初值头指针*/while(strcmp(p1-num,s) & p1 != NULL) /*当记录的学号不是要找的,或指针不为空时*/p2=p1; /*将p1指针值赋给p2作为p1的前驱指针*/p1=p1-next; /*将p1指针指向下一条记录*/if(strcmp(p1-num,s)=0) /*学号找到了*/printf(*FOUND*n);pri-n);printf(| 学号 | 姓名 | 语文 | 数学 | 英语 | 总分 | 平均成绩 | 名次 |n);printf(
26、-n);printf(| %4s | %4s | %3d | %3d | %3d | %3d | % | %-5d|n,p1-num,p1-name,p1-score0,p1-score1,p1-score2,p1-sum,p1-average,p1-order);printf(-n);printf(*END*n);printf(您确定要删除该学生的记录吗 Y/N ?); /*提示是否要删除,输入Y删除,N则退出*/for(;)scanf(%c,&c);if(c=n|c=N) break; /*如果不删除,则跳出本循环*/if(c=y|c=Y)if(p1=head) /*若p1=head,说明
27、被删结点是首结点*/head=p1-next; /*把第二个结点地址赋予head*/elsep2-next=p1-next; free(p1);/*否则将一下结点地址赋给前一结点地址*/printf(n学号为 %s 的学生记录已被删除.n,s);printf(别忘了重新存储记录.n);break; /*删除后就跳出循环*/else printf(n找不到学号为 %s 的学生记录.n,s); /*找不到该结点*/return(head);/*修改函数*/STUDENT *xiugai(STUDENT *head)STUDENT *q; /* 移动指针*/char s5; /*存放姓名用的字符数组
28、*/system(cls); printf(请输入查找者姓名.n);scanf(%s,s);q=head; /*将头指针赋给p*/while(strcmp(q-name,s) & q != NULL) /*当记录的姓名不是要找的,或指针不为空时*/q=q-next; /*移动指针,指向下一结点*/if(q!=NULL) /*如果指针不为空*/printf(n*FOUND*n);int sum1,i;printf(n请在下面输入要修改成的学生的记录.n); /*提示输入记录信息*/printf(学号:);scanf(%s,q-num);printf(姓名:);scanf(%s,q-name);p
29、rintf(分别输入 %d 科的分数.n,3);sum1=0; /*保存新记录的总分,初值为0*/for(i=0;iscorei);if(q-scorei100|q-scoreiscorei100|q-scoreiscorei; /*累加各门成绩*/q-sum=sum1;q-average=(float)sum1/3;q-order=0;printf(-n);printf(| 学号 | 姓名 | 语文 | 数学 | 英语 | 总分 | 平均成绩 | 名次 |n);printf(-n);printf(| %4s | %4s | %3d | %3d | %3d | %3d | % | %-5d|n
30、,q-num,q-name,q-score0,q-score1,q-score2,q-sum,q-average,q-order);printf(-n);printf(*END*n);head=sort(head); /*调用排序的函数,将学生成绩重新排序*/printf(n学生 %s 已经修改成功.n,q-name); printf(请别忘了重新存储.n);elseprintf(n无此记录.n,s); /*显示没有该学生*/return(head);八、程序调试过程分析(1)刚开始没有那个初始化函数,程序运行后,没有输入任何数据就试得去执行显示功能,结果显示的是一些乱码!加入初始化函数后,这
31、种现象也随之消失。(2)刚开始执行输入函数,按学号顺序输入十个学生的成绩,输完后执行显示功能,学生成绩记录是按学号的反顺序显示的,试着在其中增加一些语句,希望能把学号按正常顺序显示,但暂时没有成功,所以在输入成绩时只能按学号反顺序输入,最后就按学号正常顺序输出了。(3)刚开始时,先把成绩按平均分排序,再插入一个学生的成绩,执行显示功能,虽然插入的学生的成绩能正常插入,但该学生的名次为0。后来,在插入成绩之后,调用排序函数,把所有成绩重新排序一次。(4)在输入函数中设了一个无限循环,可以输入无数个学生的成绩信息,当学号为0的时候则停止输入。(5)输入太多个学生的成绩时,屏幕显示不能控制为一页一页
32、显示,所以为了方便起见,不要输入太多记录,十七左右为最佳。(6)在没有输入任何信息的情况下,去执行排序功能,最后显示有一个记录,学号、姓名为空白,成绩都为0,名次为1。(7)在输入选项时不能输入字母,否则会死循环,建议不要乱输字母。(8)在编写修改函数时,发现平均成绩和总成绩没有变化,原因为循环语句之后没有进行数据的重新赋值,以至于新的数据没能插进链表。九、测试数据下面对所设计系统进行数据测试:1、在主菜单选择1、输入学生记录,分别输入三组学生记录为:学号姓名语文成绩数学成绩英语成绩1Xai4556662Cui5644563yu4566772、在主菜单选择6、插入一个新的学生记录,插入数据为:
33、学号4 姓名Gu 语文成绩45 数学成绩 44 英语成绩 333、在主菜单选择9、修改记录,修改的数据为:学号 5 姓名 ze 语文成绩45 数学成绩33 英语成绩554、在主菜单选择2、输出学生记录,得到一组如下的输出:学号姓名语文成绩数学成绩英语成绩总分平均成绩名次3yu45667718812Cui56445615625Ze45335513334Gu45443312245、在主菜单选择4、删除学生记录,删除的数据为:学号2 姓名 cui 6、在主菜单选择5、将学生成绩进行排序,然后在选择2、进行一次输出,得到最后记录:学号姓名语文成绩数学成绩英语成绩总分平均成绩名次3yu456677188
34、15Ze45335513334Gu45443312247、在主菜单分别选择7、保存记录和8、读取记录,进行一次文件的读写测试。十、测试结果及分析10.1、测试结果如下:(1)进入主菜单,界面如下:图10-1(2)输入学生记录:分别输入学生的学号、姓名和分数,结果如图。 图10-2 (3)插入学生记录:输入学生相关信息,结果如图。图10-3(4)修改学生记录:输入学生学号,结果如图。图10-3(5)输出学生记录;结果如图。图10-4(6)删除学生记录:结果如图。图10-5(7)将学生记录排序:结果如图,图10-610.2、结果分析: 在vc+6.0的环境下运行程序,所得结果与前面预先设计的测试数
35、据结果一致,分别能够实现对学生成绩管理的插入、删除、修改、排序、输入、输出、查找以及文件的读写功能,说明,在简单的运行条件下,次系统可以完成对学生成绩进行相关管理。十一、小结经过一个多星期的C语言课程设计,感觉自己收获不少!首先是:链表本来上课是没有上的,但这个课程设计里面主要都是用链表,因为要达到这样的功能,使用链表相当方便,但不容易理解,所以在这方面我很了很多的时间看课本和参考课外书,使C语言的知识强化了不少。其次,在做课程设计的过程中,发现了平时很多没有注意到的问题,例如:返回值函数和不返回值函数两者在主函数中的调用是不同的更重要的是,这次课程设计虽然花了我不少时间,但正是这些时间,让我见识到了C语言的重要性。这个学生成绩管理系统都是在自己知识范围内完成的,所以界面清晰简单,可能不是很好看,但绝对实用!从这里我也得到一个体会,做一个程序,或者开发一个软件,应该着重从它的后台制作入手,不能做出一个中看不中用的程序或者软件。相信这次的课程设计为我以后继续从事计算机工作打了一个小小的开头。参考文献1 陈元春,张亮,王勇。实用数据结构基