C语言学生信息管理系统报告附有完整代码.docx
- 文档编号:10912652
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:49
- 大小:93.31KB
C语言学生信息管理系统报告附有完整代码.docx
《C语言学生信息管理系统报告附有完整代码.docx》由会员分享,可在线阅读,更多相关《C语言学生信息管理系统报告附有完整代码.docx(49页珍藏版)》请在冰豆网上搜索。
C语言学生信息管理系统报告附有完整代码
程序设计报告
(2009/2010学年第二学期)
题目:
简单学生信息管理
专业软件工程,NIIT,
学生姓名******
班级学号******
指导教师******
指导单位软件学院
日期2010-4-23
1-
评分项成绩评遵守机房规章制度(5分)
上机时的表现(5分)
学习态度(5分)
程序准备情况(5分)分
程序设计能力(10分)
团队合作精神(5分)
课题功能实现情况(10分)细
算法设计合理性(10分)
用户界面设计(10分)
报告书写认真程度(5分)则
内容详实程度(10分)
文字表达熟练程度(10分)
回答问题准确度(10分)
简
短
教师签名:
评
语年月日评
分
等
级
备评分等级有五种:
优秀、良好、中等、及格、不及格注
2-
学生管理系统一、课题内容和要求
1、系统的基本功能
实现学生信息的录入、查询和更新。
2、要求
(1)从键盘上录入学生资料,并保存到文件中。
学生资料文件中的数据记录不得少于
30条。
相关数据要求格式如下:
学生资料存放了学号、姓名、性别、出生日期、A课程成绩、B课程成绩、C
文件课程成绩格式如下:
B051001张三女19870201808277
B051002李四女19870301808080
B051003王二男19870401858080
。
。
。
。
。
。
(2)可以随时补录学生资料。
(3)能够按照不同的条件查询学生信息,并显示在屏幕上。
a)按学号排序
b)按姓名排序
c)按单科总分排序
d)按学号查找学生各门课成绩和平均分数
e)按姓名查找学生各门课成绩和平均分数
f)按学生总分排序
g)查询各门课程的平均分数
3-
二、需求分析
需要设计并实现一个综合的学生信息管理系统,要求系统能实现以下功能:
录入、查询和更新学生信息,并保存到文件中;学生资料文件中的数据记录不得少于30条;可以随时补录学生资料;可以按学号排序、按姓名排序、按单科总分排序、按学号查找学生各门课成绩和平均分数、按姓名查找各门课成绩和平均分数、按学生总分排序、实现各门课程的平均分数。
根据题目要求的功能,用结构化程序设计的思想,将系统分成5大功能模块:
显示基本信息、基本信息管理、学生成绩管理、根据条件排序、根据条件查询。
“显示基本信息”模块实现了学生基本信息的显示;“基本信息管理”模块实现了“插入学生记录”、“删除学生记录”以及“修改学生记录”功能;“学生成绩管理”模块实现了“计算学生总分”、“计算学生名次”、“计算三门课程平均分”以及“计算各门课程的平均分数”功能;“根据条件排序”模块实现了“按学号排序”、“按姓名排序”、“按A课程成绩排序”、“按B课程成绩排序”、“按C课程成绩排序”以及“按学生总分排序”功能;“根据条件查询”模块实现了“按学号查找学生各门课成绩和平均分数”和“按姓名查找学生各门课成绩和平均分数”功能。
为此需要设计一个比较综合的系统来体现“自顶向下、逐步细化、模块化”的思想。
而为了在学生管理系统中体现结构化的程序设计思想,需要在系统采用多个文件多个函数来实现功能,通过对功能的逐步细化使得最终的每一个函数都完成一个非常具体又简单的功能。
而且每一个函数在设计时要充分考虑好入口(形参)与出口的设置(函数返回值),这是保证每个模块相对独立又能为其他模块合理使用的前提。
系统应通过流程控制组织,分层调用各个函数,完成整个系统预期的任务。
4-
三、概要设计
学生管理系统
基根显学根
本据示生据
信条基成条
息件本绩件管查信管排理询息理序
按按按BCA插修删按按按按按课课课入改除学姓总姓学程程程学学学号名分名号成成生成生生查查排排排绩绩绩记记记询询序序序排排排录录录序序序
计计算算各计计三门算算门课学学课程生生程的总名平平分次均均分分数数
5-
设计流程图如下:
开始
输入学生信息
编辑学生信息查询信息
保存信息
是否
保存文件
退出
6-
根据题目要求,一个学生信息包含:
学号、姓名、性别、3门课的成绩、总分、各科成绩平均分、所有学生单科平均分以及名次。
显然,将不同类型的成员作为同一个变量的不同成分来存储,必须用结构类型来定义。
而管理系统显然要处理一批学生的信息,鉴于书本定义了以Type类型为数据域成分的结点类型,学生信息在内存中以单链表形式存放。
完整定义如下:
structStudent
{
charnum[10];
charname[20];
charsex[10];
charbirthday[10];
intscore[3];
inttotal,rank;
doubleaver,average;
};
typedefstructStudentType;
constintsizeStu=sizeof(Type);
structnode
{
Typedata;
structnode*next;
};
constintsize=sizeof(structnode);
由以上定义,结点含有两个域,即数据域data,其所属类型为Type,指针域next。
这里的Type类型是structStudent类型的别名,是一个结构体类型。
这样定义的好处是对于各种关于单链表的操作此时同样适用。
当数据成员的类型发生变化时,只需要到该文件中进行相应的修改,使Type成为新的数据成员类型的别名,结点类型structnode类型的定义都无需修改。
对链表而言,其结点永远只含有两个成员:
Type类型的data成员和
7-
structnode*类型的next成员。
四、详细设计
学生管理系统采用了两级菜单四层函数实现,充分考虑模板的合理划分,代码的可重用性,完整的程序由5个文件组成:
(1)node.h
(2)Prepare.h(3)file.h(4)list.h
(5)B09050329.c。
而文件(5)B09050329.c是系统实现的最主要的文件。
所有的菜单都是通过定义函数,并被其他函数调用后实现的。
根据操作时显示的顺序,5个菜单分为两级。
两级菜单的使用提高了人机交互性,而且同一菜单可多次选择在结束,操作更便捷灵活。
系统中各个菜单的具体信息
菜单一级菜单二级菜单
(1)二级菜单
(2)二级菜单(3)三级菜单(4)函数名menu();menuBase();menuScore();menuSort();menuSearch();对应功学生信息基本信息管理学生成绩管理根据条件根据条件能模块管理系统排序查询调用mainbaseManagescoreManagesortManagesearchManage函数函数函数函数函数函数
1、首先执行文件打开操作,调用函数readFile(),如果原始文件不存在,则调用函数createFile()创建文件,输入初始的学生信息:
其中包括学生的姓名、学号和性别以及学生的三门课程成绩等相关信息;其中调用函数Insert()函数。
判断原始文件不存在的关键代码如下:
if((fp=fopen("student.txt","rb"))==NULL)
{
printf("cannotopenfile!
\n");
exit(0);
}
如果原始文件存在,则读出文件中第一条记录,并在文件未结束时按学号顺序循环将
8-
学生记录插入链表,在读出下一条记录,其关键代码如下:
fread(&data,sizeStu,1,fp);
while(!
feof(fp))
{
head=Insert(head,data,1);
printf("\n");
fread(&data,sizeStu,1,fp);
}
如果原始文件不存在,则调用函数createFile()创建文件并循环将读入的记录写入文
件,部分关键代码如下:
readNode(&data);
while(!
endWith(data))
{
fwrite(&data,sizeStu,1,fp);
readNode(&data);
}
fclose(fp);
2、进入一级菜单,调用do~while语句可以实现多次进入一级菜单,调用一级菜单函数menu()显示一级菜单,输入一级菜单选择项,如果输入的数据在可能选项内,调用runMain()函数完成系统功能。
runMain()函数采用switch~case语句根据选择执行各个模板功能(显示基本信息模块、基本信息管理模块、学生成绩管理模块、根据条件排序模块、根据条件查询模块),此时要充分考虑好入口(形参)与出口的设置(函数返回值),保证其相对独立又能为其他模块合理使用。
3、显示基本信息模块:
先调用表头函数printHead()输出表头,调用printList(head)函数来执行链表的遍历,并在其中调用printNode(p->data);来输出学生信息,包括总分和平均分。
其关键代码如下:
for(p=head;p;p=p->next)//p从头指针开始,每循环一次向后移动1节点的位置
{
printNode(p->data);//p非空时执行循环体,调用printNode函数输出节点的元
9-
素值,最后换行
printf("\n");
}
3、基本信息管理模块:
可用baseManage(head)函数来实现,并调用menuBase();显示二级菜单。
do~while语句和switch~case语句的嵌套使用,使程序逐步细化,且更人性化,便于终端用户使用。
readNode(&data);和Insert(head,data,1);的使用执行了学生信息的插入功能。
Delete(head,data);函数执行了学生信息的删除,SearchNode(head,data,1);函数执行了学生信息的修改。
此时充分体现了单链表的优越性。
Insert(head,data,1);函数的关键代码如下:
structnode*p,*p2;
p2=head;
p=(structnode*)malloc(size);//利用指针p申请结点动态空间
p->data=data;//数据域赋值
p->next=NULL;//指针域直接赋值为空,以后根据插入位置再修改
if(head==NULL)//原链表为空时的插入
{
head=p;//新插入的结点为头结点
p2=p;
returnhead;
}
p2->next=p;//p2作为p的后继结点,即p插在p1和p2之间
returnp2;
Delete(head,data);函数的关键代码如下:
if(p)//如果找到要删除的结点p
{
if(q)//如果删除的不是第一个结点
q->next=p->next;//修改q的next域,使p的后继成为q的后继
else//如果删除的不是第一个结点
10-
head=head->next;//修改head指针
free(p);//释放指针p所指向的结点空间
}
SearchNode(head,data,1);函数关键代码如下
while(p&&!
equal(p->data,data,condition))//equal用来判断两个参数是否相等
{//当p非空且当前结点的数据值不等于要搜索的值data时
p=p->next;//指针p顺着链向后移动一个位置
}
if(p)returnp;//循环停止时p非空,表示找到了结点,返回指针P
4、学生成绩管理模块:
通过调用scoreManage()函数来实现,仍然使用do~while语
句和switch~case语句,调用menuScore();显示二级菜单。
表头函数printHead();输出
表头,执行了“计算学生总分”的关键代码如下:
for(p=head;p;p=p->next)
(p->data).total=0;
for(i=0;i<3;i++)
(p->data).total+=(p->data).score[i];
printNode(p->data);,
“计算学生名次”调用了rankCalculate(head);函数的关键代码如下:
for(p=head;p;p=p->next,count++)//head链是按学号排序的,逐个读出学生记录
head2=InsertOrder(head2,p->data,2);//依次将学生记录依总分由低到高建链表head2
rankprintHead();//输出表头
for(p=head2;p;p=p->next)//再依次访问head2链中的结点
{
current++;//每扫描到一个结点计算器current加1
q=SearchNode(head,p->data,1);//对head2中当前结点依学号在head链中找到
(q->data).rank=count-current+1;//对head链中名次进行修改
rankprintNode(p->data);//输出记录
printf("\n\n");
11-
}
returnhead;
“计算三门课程平均分”调用averMark(head);函数,其关键代码如下:
for(p=head;p;p=p->next)
{
doublem=0;
for(i=0;i<3;i++)
m+=(p->data).score[i];
(p->data).aver=m/3.0;
averprintNode(p->data);//输出记录
printf("\n");
}
“计算各门课程的平均分数”调用average(head,aver);函数,其关键代码如下:
inti,count=0;
for(p=head;p;p=p->next)
{
count++;//count用来统计总人数
for(i=0;i<3;i++)
aver[i]+=(p->data).score[i];//aver[i]中存放的是某门课的和
}
for(i=0;i<3;i++)
aver[i]/=count;//利用前面得到的总分和总人数求平均分
5、根据条件排序模块:
此模块主函数sortManage();采用不断调用函数,通过分级调用实现实现了“按学号排序”、“按姓名排序”、“按A课程成绩排序”、“按B课程成绩排序”、“按C课程成绩排序”以及“按学生总分排序”功能,同样函数名menuSort();输出二级菜单,
numberSort(head);nameSort(head);AscoreSort(head);BscoreSort(head);CscoreSort(
head);rankCalculate(head);这些函数执行功能的代码部分相似,从中通过调用InsertOrder(head2,p->data,2);执行函数功能。
12-
部分关键代码如下:
intcount=0,current=0;//count统计学生总人数,即单链表的结点个数for(p=head;p;p=p->next,count++)//head链是按学号排序的,逐个读出学生记录head2=InsertOrder(head2,p->data,2);//依次将学生记录依总分由低到高建链表head2rankprintHead();
for(p=head2;p;p=p->next)//再依次访问head2链中的结点{
current++;//每扫描到一个结点计算器current加1
q=SearchNode(head,p->data,1);//对head2中当前结点依学号在head链中找到
(q->data).rank=count-current+1;//对head链中名次进行修改
rankprintNode(p->data);//输出记录
printf("\n\n");
}
InsertOrder(head2,p->data,2);的部分关键代码如下:
structnode*p,*p1,*p2;
p2=head;
p=(structnode*)malloc(size);//利用指针p申请结点动态空间
p->data=data;//数据域赋值
p->next=NULL;//指针域直接赋值为空,以后根据插入位置再修改
if(head==NULL)//原链表为空时的插入
{
head=p;//新插入的结点为头结点
returnhead;
}
while(p2&&larger(p->data,p2->data,condition))//第一参数大于第二参数,返回真
{
p1=p2;//p1是p2的前趋结点,二者同时后移
p2=p2->next;
13-
}
if(head==p2)//前插入,修改head指针
head=p;
else//否则p插在p1的后面
p1->next=p;
p->next=p2;
在函数InsertOrder(head2,p->data,2);中又调用了调用了函数
larger(p->data,p2->data,condition),这是通过比较确定参数的函数,关键代码如下:
if(condition==1)
if(strcmp(data1.num,data2.num)>=0)//比较学号
return1;
elsereturn0;
if(condition==2)
if(strcmp(data1.name,data2.name)>=0)//比较姓名
return1;
elsereturn0;
elseif(condition==3)
returndata1.score[1]>data2.score[1];
elseif(condition==4)
returndata1.score[2]>data2.score[2];
elseif(condition==5)
returndata1.score[3]>data2.score[3];
elseif(condition==6)
returndata1.total>data2.total;
return1;
6、根据条件查询模块:
通过函数searchManage();分级调用函数,函数menuSearch();
显示二级菜单,通过输入项选择调用函数来完成根据姓名查询与根据学号查询。
关键代码:
if(choice>=1&&choice<=2)
14-
if(p=SearchNode(head,data,choice))//如果找到匹配的记录
{
printf("\n");
sort_printHead();//输出表头
sort_printNode(p->data);//输出记录
printf("\n\n");
}
else
printf("\nitisnotinthelist\n\n");//如果没有找到,输出提示信息函数sort_printHead();执行输出表头的功能,函数sort_printNode();实现了输出记录的功能。
而最主要的是函数SearchNode();其关键代码:
if(head==NULL)//如果链表原来就为空,输出提示信息并返回空指针
{
printf("\nNoRecords\n");
return0;
}
while(p&&!
equal(p->data,data,condition))//equal函数用来判断两个参数是否相等
{//当p非空且当前结点的数据值不等于要搜索的值data时
p=p->next;//指针p顺着链向后移动一个位置
}
if(p)returnp;//循环停止时p非空,表示找到了结点,返回指针P其代码简单,主要比较是否找到匹配项,如果找到就输出。
判断是否找到匹配项用了函数equal(p->data,data,condition),其关键代码如下:
if(condition==1)
if(strcmp(data1.num,data2.num)==0)//如果condition的值为1,比较学号
return1;
elsereturn0;
elseif(condition==2)//如果参数condition的值为2,比较姓名
15-
if(strcmp(data1.name,data2.name)==0)
return1;
elsereturn0;
elsereturn1;
分级调用函数,每个函数功能简单,自顶向下,便于理解。
7、保存文件,采用函数saveFile();关键代码如下:
if(head==NULL)
{
printf("\nNoRecords\n");
return;
}
while(p)
{
fwrite(&p->data,sizeStu,1,fp);
p=p->next;
}
fclose(fp);
16-
五、测试数据及其结果分析
进入界面数据显示如下:
显示学生基本信息数据如下:
插入学生信息数据如下:
计算学生总分和名次数据显示如下:
17-
求三门课程平均分数数据显示如下:
求每科平均分数数据显示如下:
按学号查询数据显示如下:
按姓名查询数据显示如下:
18-
六、调试过程中的问题
问题一、系统报错:
undeclareedidentifier(i是没有声明的变量)解决办法及步骤:
查看定义的变量,增加变量i的定义,再使用该变量。
问题二、系统报错:
missing';'before'Type'解决办法及步骤:
将变量集中在语句快处开始处定义,变量定义不能放在可执行语句中间问题三、系统报错:
missing';'before'a'解决办法及步骤:
找到出错位置,添加分号。
问题四、程序不能执行
解决办法及步骤:
关闭可执行文件。
问题五、函数功能无法实现
解决办法及步骤:
分析函数代码,改变部分代码,使之执行函数功能。
问题六、输出信息为一段乱码
解决办法及步骤:
一个个检查格式转换说明符,最后发现格式转换说明符错误,以及部分变量类型错误。
问题七、学生信息未分行显示
解决办法及步骤:
在输出函数中增加代码:
printf("\n");问题八、学生平均分数明显偏大
解决办法及步骤:
查看变量,发现本应该定义为局部变量的m定义为全局变量,改变变量m的定义位置。
问题九、
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 学生 信息管理 系统 报告 附有 完整 代码