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