1、C语言课程设计说明书西安科技大学高新学院课程设计说明书设计名称:C语言课程设计题目:学生成绩管理系统姓名:XXX专业:自动化班级:08级1班学号:XXXXXXX指导老师:黄旭日期:2010年6月9日课程设计任务书 专业 年级 班 一、 设计题目二、 学生成绩管理系统三、 主要内容数据库的数据项主要数据包括:学号、姓名、年级、专业、成绩1、成绩2、成绩3、平均成绩、总成绩。要求具有以下功能:(1)系统以菜单方式工作。 (2)显示、保存记录;添加、删除、修改任意个记录。 (3)排序功能:打开学生数据库,计算每个学生的平均成绩和总成绩,用冒泡法或选择排序法将平均成绩和总成绩排序后生成两个新文件(从大
2、到小),存盘并显示这两个文件的全部记录。(4)查询功能:打开总成绩排序文件,用折半查找法统计出给定分数的人数并显示。并能按学号或姓名查找并显示某个学生的各科成绩。(5)统计功能:对各科成绩统计分析(平均分、最高分、最低分、及格率等);统计各科各分数段人数。 四、 具体要求围绕课程设计的目的和意义,基本要求如下:1、认真阅读C语言课程设计指导书,明确课程设计的目的、意义和要求;2、快速总结C程序设计语言的精髓,如:函数的概念、函数的设计和函数的调用;3、快速熟悉Tuber C 或C+的上机环境。能熟练进行高级编辑操作(特别是字块操作);熟悉步进式、断点跟踪的程序调试方法,提高工作效率。4、根据“
3、课程设计题目”,采用结构化的程序设计思想,确定系统的总体设计方案、确定时间进度。如果是多人共一题,则要首先完成小组内的人员分工及安排,不允许重题现象。5学习并了解良好的程序设计风格。按质、按量、并按时间完成课程设计的任务。6提供可运行的课程设计系统,参加上机面试答辩。本次课程设计的重点是:学会设计并编写函数,掌握好各函数之间的调用关系;利用文件操作函数,建立数据库并完成对数据库的各种操作;掌握几种典型算法的应用(如:冒泡法、选择排序法和折半查找法)。同时锻炼学生根据题目进行分析、设计、编码、调试程序和书写必要文档的综合处理能力,从实践中学习并体会程序设计的结构化思想和设计方法。五、 进度安排依
4、照教学计划,课程设计时间为3周。按照软件工程的思想,软件系统的分析设计至关重要,并要充分重视书写“文档”。避免甚至杜绝“拿到题目就编码”的现象。建议将时间分为三个阶段:第一阶段,根据题目要求,拿出系统的总体设计方案:即构思各程序模块的算法,并画出相应的N-S图,同时编写相应的文档;第二阶段,根据N-S图编写程序代码并单独调试,再将调试通过的各个子模块进行集成调试;第三阶段,归纳文档资料,按要求填写在课程设计说明书上,并参加答辩。三个阶段时间分配的大概比例是: 35:45:20。六、 完成后应上交的材料1课程设计的题目、系统的总功能和各子模块的功能;2题目的设计思想(或算法)简述;3主要程序的框
5、图(要求用N-S图);4源程序代码(要求在关键的位置有注释,从而增加程序的可读性);5课程设计的总结报告,主要包括以下内容:(1)课程设计中遇到的主要问题和解决方法;(2)你的创新和得意之处;(3)设计中存在的不足及改进的设想;(4)本次课程设计的感想和心得体会。以上完成的源程序及相关文档,填写在课程设计说明书上,要求干净整洁,符合课程设计的要求和规范。七、 总评成绩指导教师 签名日期 年 月 日系 主 任 审核日期 年 月 日C语言程序设计目录一、系统功能 1、系统需求分析学生的成绩是一个庞大的数量,人工处理起来是一件吃力,繁琐的工作。本系统的设计只要是为了减轻教师们的负担,使其能方面,快捷
6、地对学生的成绩进行查找,修改,分析处理。2、系统功能分析 本系统的功能包括了密码验证功能,录入、输出学生成绩功能,对成绩进行增、删、改的功能,保存进文件、读取文件的功能,根据平均分排序,根据总成绩查找人数的功能,对各科成绩进行分析统计的功能。 3、系统总框架主程序密码进入菜单判断数据输入显示信息添加信息删除信息修改信息冒泡排序选择排序人数查找统计分拆退出二、功能模块的描述1.数据结构学生信息包括学号、姓名、年级、专业、成绩1、成绩2、成绩3、平均成绩、总成绩。所以将其定义为结构体。本系统使用链表对数据进行添、删、改,然后把数据赋给结构体,以结构体的形式保存进文件。结构体说的定义如下:struc
7、t student long num;/记录学号 char name10;/记录姓名 char grade10;/记录年级 char specialty10;/记录专业 float score3;/记录三科成绩分数 float avg;/记录平均分 float sum;/记录总成绩 struct student *next;/指向下一结点的指针stud100; 2.main()主函数程序采用模块化设计,主函数是程序的入口,各模块独立,可分块调整,均由主函数控制。采用do-while死循环和switch分支语句编写菜单选择控制各个模块的功能,每个模块的功能由简单的基本函数构成。直接利用输出函数p
8、rintf输出字符串,在屏幕上显示一个菜单,并显示一个提示输入选项,输入09之间的数字,将此数字作为菜单函数的返回值返回主函数,主函数根据这个数字调用相应的功能函数,制作简便,操作简单。用printf显示菜单输入菜单选项序号赋给C 判断数否输入有错误 是 否提示输入超出范围进行菜单功能的选择当C超出菜单范围返回C值3. Pwd();/密码验证函数 本系统提供密码功能,密码初始化为“000000”,并提供密码屏蔽功能。密码验证函数的具体做法是,先接收一段字符,然后看与系统预先设定的密码字符串是否相同,如果相同则返回1,不相同则重新接收一串字符,重复三次,自动返回0. For i=0 to 2 F
9、or i=0 to 6 pwdPuti = getch()单个输入密码输出“*”判断密码是否正确否 是返回1 返回04 student *creat(void)创建动态链表为了输入时不出错,输入方法使用一个数据一行的方式输入,用回车确定。考虑到学生的学号不可能为0,所以当输入的学号数为0时,把表尾结点的指针变量置NULL。由于记录并不是一次性全部输入,而是随时添加和删除的,而预先开辟的空间数往往大于实际的记录数,所以程序设定全局变量n,随时记录所输入学生个数。当输入结束后,调用save()函数保存数据。开辟一个新结点,并使p1p2指向它读入一个学生数据给p1所指向的结点head = null,
10、n = 0n= n + 1 n等于1?真 假把p1所指的结点作为第一个结点把p1所指的结占连接到表尾 p2移到表尾再开辟一个新结点,使p1指向它读入一个学生数据给p1所指结点 当读入的p1- num 不是零表尾结点的指针变量置NULL 调用save()函数保存5print(struct student *head)输出链表 传进去head的地址,然后设一个指针变量p,先指向第一个结点,输出p所指的结点,然后使p后移一个结点,再输出,直到链表的尾结点。为了保存数据,在输出的同时把该链表的值赋给结构体变量stud,其中,字符串用strcpy()来赋值。再使用Avg()和Sum()函数来计算学生的平
11、均分和总分。P = head,使p指向第一个结点 P指向的不是尾结点 真 假输出p所指向的结点P指向下一个结点把链表的值赋给stud当p指向的不是表尾使用Avg()和Sum()计算学生的平均分和总分6DelMain(struct student *head)/删除判断函数 此函数用一个循环来判断是否继续删除结点,当输入学号为0时,循环结束,保存数据。输入要删除的学号学号不等于0调用del()删除结点,并输出继续输入要删除的学号调用Save()保存7student *del(struct student *head,long num)删除记录 输入要删除记录的学号,从p指向的第一个结点开始,检查
12、结点中的num值是否等于输入的要求删除的那个学号。如果相等就将该结点删除,如果不相等,就将p后移一个结点,再如此进行下去,直到遇到表尾为止。若遇到空链表或找不到要删除的结点,输出信息。YES 链表是一个空表 NO输出“空表”p1 = head 当num 不等于p1-num以及p1所指的结点不是表表尾结点p2后移一个位置p1后移一个位置 p1是要删除的结点 是 否 p1所指是头结点是 否输出“找不到”的信息head = p1-next删除头结点n = n - 1P2-next = p1-next删除一个结点n = n - 18InputMain(struct student *head)/插入判
13、断函数 此函数用一个循环来判断是否继续插入结点,当输入学号为0时,循环结束,保存数据。输入要插入的学号学号不等于0调用insert()插入结点,并输出继续输入要插入的学号调用Save()保存9student *insert(struct student *head,struct student *stud)插入记录 输入要删除记录的学号,从p指向的第一个结点开始,检查结点中的num值是否等于输入的要求删除的那个学号。如果相等就将该结点删除,如果不相等,就将p后移一个结点,再如此进行下去,直到遇到表尾为止。若遇到空链表或找不到要删除的结点,输出信息。p1 = head,p0 = stud原来的链
14、表是一个空表YES NO将p0所指的结点作为唯一结点当p0-num p1-num以及p1所指的不是表尾结点 p2后移一个位置p1后移一个位置 p0-num num 是 否 p1所指是头结点是 否插到表尾之后Head = p0p0-next = p1插到表头之前p2-next = p0p0-next = p1插到表中间 n = n + 110. Correct(struct student *head);/继续修改判断函数 此函数以调用删除函数和插入函数来对学生信息进行修改。首先输入要修改的学号,用del()函数来删除些学号的信息,再用insert()来重新输入刚才那学号对应的信息。输入要修改的
15、学号学号不等于0调用del(head)删除结点,并输出调用insert(head,stu)为刚才的学号插入新数据继续输入要修改的学号调用Save()保存11Save()保存记录到文件函数: 在程序中的数据输入和输出是以终端为对象的,当程序关闭后,数据也就丢失了,所以为了能随时查阅数据,必须将数据输出到磁盘文件上保存起来,使用时人磁盘中读入到内存中,这就用到了磁盘文件的读写操作。按照文件的读写要求,先定义一个指向文件的指针,按W写的方式打开stuAll.dat文件,保存进文件中,如果文件不存在则系统自动创建文件。如果文件不能正常打开,则输出信息;否则,先写入数n,然后用循环语句,用文件格式输出语
16、句fwrite(&studi,sizeof(struct student),1,fp);逐条写入记录,提示保存成功,最后关闭文件。 fp=fopen(“stuAll.dat”,”w”)为输出打开一个文件 打开是否成功否 是输出提示不能打开文件返回将数据写入stuAll.dat文件For i=0 to n-1格式写入记录fwrite(&studi,sizeof(struct student),1,fp) 提示保存成功fclose(fp);关闭文件12Read()从文件中读取记录函数: 数据一但写出保存到磁盘中后,更多的操作是将数据从文件读入内存,进行显示、查找等各项操作。 按照文件的读写要求,先
17、定义一个指向文件的指针,按照r的方式打开已经保存好的文件,输入要打开文件的路径和文件名,fp=open(filename,”r”),同时判断是否正常打开,如果文件打不开,则输出输出信息;否则,利用格式输入函数,先读入记录数,然后利用循环语句,用函数fread(&studi,sizeof(struct student),1,fp);将记录逐条读入,读入的记录保存在结构体数组中。 fp=fopen(“stuAll.dat”,”rb”)为输出打开一个文件 打开是否成功否 是输出提示不能打开文件返回从stuAll.dat文件中读取数据For i=0 to n-1读取数据fwrite(&studi,si
18、zeof(struct student),1,fp)输出学生信息fclose(fp);关闭文件13. ReadStuAllToPao()读取保存的数据,冒泡排序后输出到屏幕并放到stuPao.dat文件先用Read()函数从stuAll.dat文件中读取学生数据到结构体,然后使用冒泡排序法对学生的平均分从大到小排序并输出到屏幕,最后保存到stuPao.dat文件中。 调用Read()读取学生数据For j = 0 to n 1For i = 0 to n 1 j 如果studi.avg studi+1.avg真 假studi.avg 和 studi+1.avg进行交换fwrite(&studi
19、,sizeof(struct student),1,fp)保存数据fclose(fp)关闭文件14. ReadStuAllToSel()读取保存的数据,选择排序后输出到屏幕并放到stuSel.dat文件先用Read()函数从stuAll.dat文件中读取学生数据到结构体,然后使用选择排序法对学生的平均分从大到小排序并输出到屏幕,最后保存到stuSel.dat文件中。 调用Read()读取学生数据For i = 0 to n 1For j = i + 1 to n 1 如果studi.avg studi+1.avg真 假studi.avg 和 studi+1.avg进行交换fwrite(&stu
20、di,sizeof(struct student),1,fp)保存数据fclose(fp)关闭文件15ReadPao(),ReadSel(),分别从stuPao.dat和stuSel文件中读取记录函数 ReadPao()和ReadSel()基本相同,不同的只是分别从不同文件中读取学生数据。和Read()函数不同的是它能读取保存的学生平均分和总分。 fp=fopen(“stuPao.dat”,”rb”)为输出打开一个文件 打开是否成功否 是输出提示不能打开文件返回从stuPao.dat文件中读取数据For i=0 to n-1读取数据fwrite(&studi,sizeof(struct stu
21、dent),1,fp)输出学生信息fclose(fp);关闭文件16. Binsrch()二分法查找总分人数 排序是一种较为费时的运算,所以经过了排序,而不加以利用未免可惜,为此设计了一种在排序基础上实现的快速查找算法二分查找法。 二分查找法,首先确定要找的数据是在一个已经从大到小排序好的数组当中,然后检索中间的分数值,如果此分值比要查找的分数值大,就从该数组的后面一半的中间值再开始找,否则则从前面一半开始找,一直到找到该数所在的位置为止。然后从位置向上检索,找出第一个和此数值相等的数的位置,再从该位置向下检索,找到所有总分为该分数的学生人数。从stuPao.dat文件中读入学生的数据Whil
22、e low studmid.sum给出的分值是否大于中间值是 否High = mid 1修改右边界Scorestudmid.sum是 否Low = mid +1修改左边界记录位置人数记录+1While score = studnumber-1.sumNumber - 找到第一个总成绩为此分值的位置While score = studnumber + 1.sumCount+ 人数记录+1Number+ 记录位置关闭文件17StaScore()分析统计函数:除了对学生成绩的总分进行分析外,对各科成绩的分析也是不可或缺的。此函数遍历每个科目的所有成绩,找出其中的最高分,最低分和平均分,并对各科成绩的
23、各个分数段统计出来,算出其合格率。For j = 0 to 2把最高分,最低分,平均分及各分数段的人数都置0For i=0 to n-1 maxScore studi.scorej?是 否把此值赋给minScoreavgScore+=studi.scorej计算平均值用if判断统计各科成绩在各分数段的人数循环输出上述所有数据三、源程序#include#include#include#include #include #define null 0#define LEN sizeof(struct student)struct student long num;/记录学号 char name10;
24、/记录姓名 char grade10;/记录年级 char specialty10;/记录专业 float score3;/记录三科成绩分数 float avg;/记录平均分 float sum;/记录总成绩 struct student *next;/指向下一结点的指针stud100;int n;/全局变量表示学生人数/*下面是各函数声明*/int Pwd();/密码验证函数int Menu();struct student *creat(void);void print(struct student *head);void DelMain(struct student *head);/继续
25、删除判断函数struct student *del(struct student *head,long num);/删除结点void InputMain(struct student *head);/继续插入判断函数struct student *insert(struct student *head,struct student *stud);/插入结点void Correct(struct student *head);/继续修改判断函数void Save();/把学生数据保存到stuAll.dat文件中void Read();/从stuAll.dat中读取数据void ReadStuAl
26、lToPao();/从stuAll.dat中读取数据,冒泡排序后输出到屏幕并放到stuPao.dat文件void ReadStuAllToSel();/从stuAll.dat中读取数据,选择排序后输出到屏幕并放到stuSel.dat文件void ReadPao();/从stuPao.dat中读取数据void ReadSel();/从stuSel.dat中读取数据void printStu(struct student stud100);/输出全部学生结构体void Avg(struct student stud100);/计算平均分void Sum(struct student stud100
27、);/计算总分void Binsrch();/折半查找法void StaScore();/对各科成绩进行统计/主函数void main() int menuNum = 0; /记录选择的菜单功能 int contunue;/记录密码是否正确 struct student *head; printf(nnnn); printf(ttt*n); printf(ttt* *n); printf(ttt* 学生成绩管理系统 *n); printf(ttt* (口令为000000) *n); printf(ttt*n); contunue = Pwd();/验证密码 if(contunue = 1) for(;) switch(Menu() case 0:printf(感谢您的使用,退出程序!n); exit(0); break; case 1:head = creat();/创建列表 print(head); break; case 2:Read();/输出学生的数据 break; case 3:DelMain(head);/删除学生的数据 break; case 4:InputMain(head);/插入学生的数据 break; case 5:Correct(head);/修改学生的数据
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1