By DUT 电信1214
《程序设计基础》---大程序作业报告
题目:学生成绩信息管理系统
姓名:刘阳 学号:201281***
Tel:188********
email:139*******@qq.com
1.开发工具:Visual C++ 6.0
2.对问题的理解:题目要求的这个系统应该包含两个部分,一个是文件管理,一个是数据处理。文件管理就是新建学生信息文件并保存、添加或修改学生记录,对原有学生信息文件进行读取。
3.所用到的知识点:带参宏替换,全局变量与静态变量,基本语句(如if,for等),函数的定义与调用,各种指针做函数参数,结构体数组,结构体数组指针,返回指针值的函数,动态分配函数,文件的打开与关闭,文件的读写,文件的指针定位。
4. 所使用的数据结构和函数功能说明:
一共有12个函数:
① void sort_sex(struct student stu[],int n,char a)
按性别筛选列表,形参stu[]为保存数据的结构体数组指针,形参n为学生数量,形参a为主函数中输入的想要筛选的性别。
② void sort_average(struct student stu[],float x[],int n,int m)
按平均分进行排序或者求平均分最高个人,形参m控制实现哪种功能,形参stu[]为保存数据的结构体数组指针,形参n为学生数量,形参x[]为保存有每个人平均分的数组指针。
③ float * average_subject(struct student *p,int n)
按科目求平均分,形参stu[]为保存数据的结构体数组指针,形参n为学生数量。
④ float average_person(struct student *p)
按指定个人求平均分,形参为指向保存数据的结构体指针。
⑤void find_subject_max(struct student stu[],int n,int m)
查找指定科目最高分,形参stu[]为保存数据的结构体数组指针,形参n为学生数量,形参m控制所要查询的科目。
⑥ void sort_higher(struct student stu[],float x[],int n,int m)
按平均分高于指定个人筛选列表,形参stu[]为保存数据的结构体数组指针,形参x[]为保存有每个人平均分的数组指针,形参n为学生数量,形参m为作为标准的学生的序号。
⑦ void indata(struct student *p,int n)
输入数据函数,形参*p为指向用来记录学生信息的结构体数组的指针,形参n为想要保存数据的学生的个数。
⑧ void savef(struct student *p,int n)
保存数据函数,形参*p为指向用来记录学生信息的结构体数组的指针,形参n为想要保存数据的学生的个数。
⑨ void loadf(struct student *p,int n)
读取数据函数,形参*p为指向用来记录读取的数据的结构体数组的指针,形参n为所读取的文件中含有学生记录个数。
⑩void change(int n)
修改学生记录函数,形参n为所要修改的文件中含有学生记录的个数。
⑪void add()
增加学生记录函数。
⑫void quntity()
求文件中所含学生记录个数函数。
所使用数据结构主要有全局变量n,结构体数组stu[50],静态数组x[50],以及其他辅助变量。
5.结合模块化代码(进行截图),进行算法描述:
首先,先描述一下各个函数的算法,再结合main函数进行流程及主体算法描述。
在编译预处理时进行带参宏替换,方便接下来输出学生信息。
a代表所要筛选的性别,利用循环结构将与其相同的学生的信息输出。
建立一个y[50]数组,当做平均分数组元素的下标,这样便可以对下标进行交换,这样就可以知道平均分数组的大小排序而不用交换其中的元素。同时利用m的值及if条件语句控制所用功能,m=1时按输出按平均分排序的列表,m=2时输出平均分最高个人信息。
定义了一个储存各科平均分的数组,由于主函数中仍要调用该数组,所以定义为静态数组,返回一个指向该数组的指针。同时利用指针移动及循环结构将各科平均分存入静态
数组中。
求个人平均分。
利用开关语句,通过形参m的值控制所求科目,还是通过建立一个y[50]数组,当做个人单科成绩的下标,通过循环结构及if函数找出最大值的下标,最后输出。
利用循环语句,if函数将平均分高于标准的学生筛选出来,并输出他们的信息。
利用循环语句,逐次输入各个学生的信息,注意事项:序号为避免麻烦我编程时写成自动赋值,number是学号!
以写的方式打开二进制文件,对于构造类型,以数据块方式读写二进制文件,以一个
记录为单位循环写入。
以读的方式打开文件,写入结构体数组stu[50]。
先利用动态分配函数申请空间,让p和head指向这一内存,head用于指针复位,以读的方式打开文件,对于构造数据类型编程时以一个记录为单位循环读写文件,利用循环将其中数据写入申请的空间,再利用while(1)循环,只有当找到该学生循环才有出口,否则一直运行到输入正确的学号为止。再通过开关语句,控制查询的科目,而0不放在开关语句内,它控制用break跳出while(1)循环,这也是这一个while(1)的唯一出口。之后还是以写的方式重新写入文件,新数据替换原数据。
这个函数前半部分与之前类似,关键在于新增加的学生数据的序号问题,我之前说过为避免麻烦学生序号在输入时我写成了自动赋值,而在这里必须在i的基础上加上已有人数n,即p->num=i+n;
这个函数是文件管理模块的一大关键,利用指针定位函数fseek,文件打开时,指针位于文件首第一个字节,调用fseek函数把指针移到文件末尾,再调用ftell()返回指针当前所在位置,这个返回值是文件长度,再用它除以struct student类型的长度,得到学生个数。
接下来结合main()函数介绍流程及主体算法:
首先是文件管理模块菜单,通过输入a来选择你想进行的操作。
利用开关语句,调用实现功能所需函数,对于全局变量n,除一是输入外,其余都是由quntity()函数获得。
数据处理模块菜单及准备环节,如果a=2或4,那么结构体数组中并未保存学生数据,需要从文件中读取。而为了后面程序需要,须先把平均分求出存入数组x[50]。
运用一个while(1)循环,实现连续使用多个功能,而j==0放在switch外作为循
环唯一出口。剩下函数根据各自接口传递相应的形参并定义变量接收返回值。
最后的结束语。
6. 程序调试情况(进行截图):
写程序时我是写几个函数编译一次,但是那些忘记截图,这个是写完主函数后第一次编译的状况,错误包括定义错变量类型,程序格式问题,以及变量未定义,调用的函数名写错。
7. 对操作过程和结果进行截图演示:
8. 所遇到的主要难题及解决问题的过程:
主要有两个比较大的难题
第一个是在按平均分进行排序时,如果按照以前降阶排序那样,平均分数组交换顺序,那样纵然求出了平均分排序,可是计算机却已经不可能知道最大的平均分是属于第几个人
的。在百度上也没有好的解决方案,或者说根本没有解决方案,后来在一个论坛里有人讨论这个问题,受到了启发。再定义一个数组当作下标不就行了。
第二个是对于全局变量n的赋值,如果重新运行文件的话、或者对已有文件进行操作,n的值是没有的,后来查书后增加了一个quntity函数(书上287页)。
9. 总结与体会:
最大的收获还是在与调试时,调试了许多次之后,基本看见BUG就知道肯定是哪里出问题了,比如在按性别筛选时,筛选完性别全变成一样的了,就知道肯定是if函数中==写成=造成的。如果程序输入完停止工作,多半是少了&。如果提示unexpected file end,一定是少了}。
还有体会就是要相信自己能编出来,周围的人基本都是从百度上下载后改改就交了,或者互相抄,其实多看书,多思考,其实也挺简单的。百度纵然好用,我们可以从中学习,自己多思考留下的印象才深刻。
因篇幅问题不能全部显示,请点此查看更多更全内容