嵌入式课程设计 学生信息管理系统Word格式文档下载.docx
《嵌入式课程设计 学生信息管理系统Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《嵌入式课程设计 学生信息管理系统Word格式文档下载.docx(23页珍藏版)》请在冰点文库上搜索。
7、按照班级统计学生的总成绩
8、按照学号查询学生成绩
9、按照班级输出不及格学生名单及科目
10、按照班级输出学生成绩单
0、退出系统
二.功能模块图:
图1系统功能模块图
三、主要功能的实现
程序设计一般由两部分组成算法和数据结构,合理地选择和实现一个数据结构和处理这些数据结构具有同样的重要性,在学生信息管理程序中由于预计记录数比较大能够、删除、保存等外更多的情况是查询。
所以选用动态链表保存数据。
1、学生信息管理
由于信息输入量比较大,需要的存储空间大,所以需要采用树的双亲表示法进行信息存储,为了方便采用以下定义。
structstudent
{
intnum;
charname[20];
charsex[5];
charclass[30];
intsemester;
charcourse[30];
intscore[3];
structstudent*next;
};
structlist
intclass;
structstudent*head;
2.main()主函数
程序采用模块化设计,主函数是程序的入口各模块独立。
可分块调试均由主函数控制调用控制功能的实现通过循环执行一个开关语句,该语句的条件值是通过调用主菜单函数得到的返回值,根据该值调用相应的各功能函数。
同时设置一个断点。
即当返回值为一定条件时运行break0;
函数结束程序,以免造成死循环。
根据菜单的提示进行需要的操作。
图2主函数输出界面
图3程序总体流程图
(1)主菜单
直接利用输出函数printf输出字符串在屏幕上显示一个菜单并显示一个提示输入选项输入数字,将此数字作为菜单函数的返回值返回主函数,主函数根据这个数字调用相应的功能函数,制作简便,操作简单界面如图10-2所示:
图4主菜单界面
由于程序中很多地方用到了字符串输入语句会造成下一个字符不能正确读入为了在程序调用执行了各个函数后能够清晰地看到菜单并输入新的选项。
按照所见即所得的方式直接设计输出函数输出字符串达到菜单效果将精力主要放在程序功能的实现上利用while循环语句一直执行scanf("
%d"
,t)语句。
让用户输入数按照整形数据形式输入然后字符串转化为数字返回主函数。
既然是数字选项为什么不用整数格式输入而要按字符串输入。
再将其转换呢,如果按照整数格式输入,当用户输入了非数字字符。
例如a和b等由于类型不同将导致程序出错。
所以对于不参与运算的数据表面上看是数字也应将其设为字符处理。
例如电话号码,千万不要设为整数类型,程序设计技巧很多。
所以读者在编程调试中应注意并仔细体会。
(2)创建班级
输入记录时按照一条一行的格式输入,每个数据之间用空格分隔,较为清晰且能直接反映数据之间的关系,但由于scanf函数的特性,在输入时数据用回车分隔也是可以的,但与界面设计不吻合界面.由于记录并不是一次性全部输入而是随时填加和删除的,而预先开辟的空间数往往大于实际的记录数。
所以程序设计为首先输入准备输入的记录数n,然后用while循环语句循环输信息。
图5创建列表页面
输出学生信息
该功能的实现主要是是通过结构体数组中的链表指针进行输出
图6输出全部信息
按照学号录入学生成绩
通过头指针查找到需要录入成绩的节点,录入成绩。
按照班级录入学生成绩
按照学号修改学生成绩
按照班级修改学生成绩
按照班级统计学生的总成绩
按照学号查询学生成绩
按照班级输出不及格学生名单及科目
(11)按照班级输出学生成绩单
四、程序设计
(一)先进行人工检查,即静态检查。
在写好一个程序以后,不要匆匆忙忙上机,而应对程序进行人工检查。
这一步十分重要,它能发现程序设计人员由于疏忽而造成的多数错误。
这一步往往容易被人忽视,总希望把一切都推给计算机去做,但这样会多占用机器时间,作为一个程序人员应当养成严谨的作风,每一步都要严格把关,不把问题留给后面的工序。
为了更有效地进行人工检查,所编的程序应力求做到以下几点:
①应当采用结构化程序方法编程,以增加可读性;
②尽可能多加注释,以帮助理解每段程序的作用;
③在编写复杂的程序时不要将全部语句都写在main函数中,而要多利用函数,用一个函数来实现一个单独的功能。
各函数之间除用参数传递数据外,尽量少出现耦合关系,这样便于分别检查和处理。
(二)在人工检查无误后,再上机调试。
通过上机发现错误称为动态检查。
在编译时会给出语法错误的信息,调试时可以根据提示信息具体找出程序中出错之处并改正。
应当注意的是有时提示出错的地方并不是真正出错的位置,如果在提示出错的行找不到错误的话应当到上一行再找。
有时提示出错的类型并非绝对准确,由于出错的情况繁多且各种错误互有关联,因此要善于分析,找出真正的错误,而不要只从字面意义上找出错信息,钻牛角尖。
如果系统提示的出错信息很多,应当从上到下逐一改正。
有时显示出一大片出错信息往往使人感到问题严重,无从下手。
其实可能只有一二个错误。
例如,对使用的变量未定义,编译时就会对所有含该变量的语句发出出错信息。
这时只要加上一个变量定义,就所有错误都消除了。
(三)在改正语法错误(包括“错误(error)”和“警告(warning)”)后,程序经过连接(link)就得到可执行的目标程序。
运行程序,输入程序所需数据,就可得到运行结果。
应当对运行结果作分析,看它是否符合要求。
有的初学者看到运行结果就认为没问题了,不作认真分析,这是危险的。
有时,数据比较复杂,难以立即判断结果是否正确。
可以事先考虑好一批“试验数据”,输入这些数据可以很容易判断结果正确与否。
例如解方程。
事实上,当程序复杂时很难把所有的可能情况全部都试到,选择典型的临界数据作试验即可。
(四)运行结果不对,大多属于逻辑错误。
对这类错误往往需要仔细检查和分析才能发现。
可以采用以下办法:
1.将程序与流程图仔细对照,如果流程图是正确的,程序写错了,是很容易发现的。
例如,复合语句忘记写花括弧,只要一对照流程图就能很快发现。
2.如果实在找不到错误,可以采用“分段检查”的方法。
在程序不同的位置设几个printf函数语句,输出有关变量的值,逐段往下检查。
直到找到在某一段中数据不对为止。
这时就已经把错误局限在这一段中了。
不断减小“查错区”,就能发现错误所在。
3.也可以用“条件编译”命令进行程序调试(在程序调试阶段,若干printf函数语句就要进行编译并执行。
当调试完毕,这些语句不用再编译了,也不再被执行了)。
这种方法可以不必一一去掉printf函数语句,以提高效率。
4.如果在程序中没有发现问题,就要检查流程图有无错误,即算法有无问题。
如有则改正之,接着修改程序。
5.有的系统还提供debug(调试)工具,跟踪程序并给出相应信息,使用更为方便,请查阅有关手册。
总之,程序调试是一项细致深入的工作,需要下功夫,动脑子,善于积累经验。
在程序调试过程中往往反映出一个人的水平,经验和态度。
希望大家给以足够的重视。
上机调试程序的目的决不是为了“验证程序的正确”,而是“掌握调试的方法和技术”,要学会自己找问题,这样慢慢自己就会写出错误较少的实用程序。
五、代码的实现
#include<
stdio.h>
stdlib.h>
#defineMAXSIZE100
voidCreatClassStudent(structlistClass[],intn)//创建班级
charch;
inti;
i=1;
structstudent*head,*p,*q;
head=(structstudent*)malloc(sizeof(structstudent));
q=p=head;
while(i<
=n)
{
printf("
输入第%d个班级的信息:
\n"
i);
structstudent*head,*p,*q;
head=(structstudent*)malloc(sizeof(structstudent));
Class[i].head=p=head;
while
(1)
{
printf("
输入学号:
);
scanf("
&
head->
num);
输入姓名:
%s"
head->
name);
head->
score[0]=0;
score[1]=0;
score[2]=0;
getchar();
是否继续?
%c"
ch);
if(ch=='
n'
)
break;
p=(structstudent*)malloc(sizeof(structstudent));
next=p;
head=p;
}
head->
next=NULL;
i++;
}
}
voidprint(structlistClass[],intn)//输出学生信息按照班级输出
structstudent*p;
inti=1;
=n)
p=Class[i].head;
移动%d班学生信息\n"
while(p!
=NULL)
printf("
%d\t"
p->
%s\t"
%d\t%d\t%d"
score[0],p->
score[1],p->
score[2]);
p=p->
next;
voidStudentId(structlistClass[],intn)//按照学号输入成绩
intscore1,score2,score3;
intt;
intkey;
printf("
"
scanf("
key);
if(p->
num==key)
{
输入3门成绩:
scanf("
%d%d%d"
score1,&
score2,&
score3);
p->
score[0]=score1;
score[1]=score2;
score[2]=score3;
t=0;
}
p=p->
if(t!
=0)
该学号不存在!
voidClassId(structlistClass[],intn)
inti=1;
录入%d班级的成绩\n"
输入学号为%d的学生成绩:
p->
score[0],&
score[1],&
成绩录入结束\n"
voidStudentNumberChange(structlistClass[],intn)
请输入学号:
请输入新的成绩:
voidClassNumChange(structlistClass[],intn)
输入需要修改信息的班级号%d----%d:
1,n);
class);
p=Class[class].head;
是否要修改%d的成绩:
continue;
输入新的成绩:
p->
voidTotalGrade(structlistClass[],intn)
intsum=0;
intaverage;
intk;
输入班级号%d------%d\n"
p=Class[class].head;
while(p!
sum=p->
score[0]+p->
score[1]+p->
score[2];
average=sum/3;
%d的总成绩是%d平均成绩是%d\n"
num,sum,average);
p=p->
}
voidQueryResults(structlistClass[],intn)
学号为%d的学生[移动%d班]"
num,i);
%d\t%d\t%d\n"
if(t!
该学生不存在于%d班\n"
voidNotPass(structlistClass[],intn)
请输入班级号%d---%d:
%d班不及格名单\n"
class);
if(p->
score[0]<
60||p->
score[1]<
score[2]<
60)
%d\t%s\t"
num,p->
语文\t%d\t不及格\t"
score[0]);
线性代数\t%d\t不及格\t"
score[1]);
score[2]<
60)
英语\t%d\t不及格\t"
voidTranscript(structlistClass[],intn)
请输入班级号:
%d\t%s\t%d\t%d\t%d\n"
name,p->
voidmenu()
0、退出系统\n"
1、创建班级\n"
2、输出学生信息\n"
3、按照学号录入学生成绩\n"
4、按照班级录入学生成绩\n"
5、按照学号修改学生成绩\n"
6、按照班级修改学生成绩\n"
7、按照班级统计学生的总成绩\n"
8、按照学号查询学生成绩\n"
9、按照班级输出不及格学生名单及科目\n"
10、按照班级输出学生成绩单\n"
intmain()
intn;
intoperation;
structlistClass[MAXSIZE];
Class[0].head=NULL;
Class[0].class=-1;
输入班级数量:
n);
while
(1)
menu();
请选择操作:
scanf("
operation);
switch(operation)
case1:
CreatClassStudent(Class,n);
break;
case2:
print(Class,n);
case3:
StudentId(Class,n);
case4:
ClassId(Class,n);
case5:
StudentNumberChange(Class,n);
case6:
ClassNumChange(Class,n);
case7:
TotalGrade(Class,n);
case