中南大学
C语言程序设计实践报告
题 目 学生信息管理系统
学生姓名
指导教师
学 院
专业班级
完成时间
目录
一、系统功能介绍 3
二、系统功能模块 4
2.1系统功能结构图 4
2.2模块功能介绍 4
三、数据结构设计 5
四、主要模块算法说明 6
六、问题,解决方法及注意事项 12
七、课程设计总结 13
八、部分源程序代码 14
1.录入学生信息:录入学生的基本信息,如年龄,性别学号,班级;以及该学生选修课程的基本信息,如课程编号,学分。
2.数据查询:按照姓名或者按照学号查询,查询学生基本信息,或者学生的成绩信息。
3.输出统计信息:按照平均成绩由高到低的顺序,输出学生名单;输出不及格的学生不及格的课程以及该门课程的平时、考试,综合成绩
4.删除信息:删除指定的学好的学生的所有信息。
5.修改数据:修改指定学号的学生信息,修改其基本信息或者课程信息。
6.插入数据:插入一个学生的完整信息到已有的学生信息库中。
7.退出系统:退出系统,关闭程序。
录入数据模块:录入学生的基本信息,如年龄,性别学号,班级;以及该学生选修课程的基本信息,如课程编号,学分。同时可以自动计算每门课程的综合成绩,每个学生的平均成绩。
查询数据模块:输入一个学号,或者输入一个姓名,输出该学号的基本信息以及选修课程的各种信息。
统计信息模块:输出学生平均成绩排名表,输出不及格学生列表以及不及格学生的不及格课程的考试、平时及综合成绩。
删除模块:根据输入的学号,将该学号的所有信息从学生信息库中删除。
修改模块:修改输入学号的学生的制定信息,其他信息不修改。
插入模块:插入一个学生的信息到学生信息库中。
排序模块:对所有学生爱平均成绩排序。
1. 变量类型
由于某个学生的各种信息是一个整体,不不能分别定义再引用,而且每个学生的选修课程含有编号、学分等信息,也属于一个整体,因此我采用了学生信息结构体中嵌套课程信息结构体的方式定义数据。
struct course//定义课程结构体
{
int num;/*课程编号,定义为整型数据*/
float credit; /*课程学分,定义为浮点型数据*/
float usual;//以下为成绩信息,均为浮点型数据
float exam;
float final;
};
struct student//定义学生结构体
{
int ID; /*学生编号,整形数据*/
char name[20];/*学生姓名,字符数组,大小20*/
int cla;/*班级信息,整型数据*/
char sex[2];/*性别信息,字符数组,大小2*/
int age;/*年龄,整型数据*/
struct course clanguage;//以下为三个struct course类型的课程
struct course math;
struct course pe;
float average;
}stu[30];/*定义学生结构体的大小*/
2.关于变量的作用域问题。
由于各个函数均要使用结构体数组中的所有成员或者部分成员,若采用参数传递方式对结构体成员进行调用,不简洁而且返回值容易出错,所以结构体变量及学生人数都定义为全局变量,便于使用。
1. 主函数 void main()
先调用主界面函数,打印出主界面,在调用菜单函数。
2. 菜单函数 void menu()
先打印出各个功能以及对应的数字选项,然后利用scanf语句输入选项,利用switch语句的多选择性,设置不同的case,进入相应的分功能函数。
3. 输入数据函数 void enter()
函数开始利用scanf语句确定输入的人数p,接着使用循环控制语句,分别录入学生的所有基本信息。对于学生课程信息,由于课程编号以及学分固定,因此采用直接赋值方式在循环体中初始化;每个学生的每个课程的综合成绩、每个学生的平均成绩通过在循环体中调用calculate(int i)函数实现。最后调用sort函数,对所有学生按平均成绩排序。
4. 查询信息函数 void inquire ()
此模块包含两个小的模块,一为inquire_ID()函数模块,一为inquire_name()函数模块。通过if语句,根据输入的数字进入不同查询函数。
查询过程的具体实现:先输入一个学号或者姓名,是这一个变量flag,初值为0。如果找到了该学号,flag的值变为1,同时将此时的i值赋给变量k,起到标记变量的作用。接着判断flag的值,if(flag)输出查找学生的信息,否则通过scanf语句输入选项,执行返回主菜单或者重新输入两个语句之一。
5. 信息统计函数 void census_output()
通过输入选项1、2,进入平均成绩查询或者不及格学生名单查询。
输出平均成绩:利用循环语句,依次从高到低输出各个学生的信息。
输出不及格学生名单:利用循环语句,在循环语句中判断每个学生每门课程的综合成绩是否小于60,小于60,则输出学生该门课程的平时、考试、综合成绩。并且还设置了flag变量,在循环外赋值为0,开始循环以后,每找到一门不及格成绩,flag++,循环结束以后,判断flag的值,如果不为零,不运行任何指令,否则输出“无成绩不及格学生”的提示信息。
6. 删除信息函数 void dele()
输入一个学号,然后利用循环语句,找到删除位置,与查询类似,设置flag变量,初始值为0,找到学号后,flag的值变为1,利用变量k=i标记该位置。紧接着,判断flag的值,if(flag),利用循环语句for(i=k;i ;即,将后一个学生信息全部赋给前一个学生,覆盖掉前一个学生原来的信息,删删除成功后,全局变量p的值减1;如过flag值为0,则提示所要删除的学号不存在,返回主菜单。 7. 修改信息函数 void modify() 输入一个学号,然后利用循环语句,找到修改位置,与查询类似,设置flag变量,初始值为0, 找到学号后,flag的值变为1,利用变量k=i标记该位置。接着判断flag的值,if(flag),通过scanf语句输入选项,利用if else 语句进入相应的修改项,修改信息;如果flag为0,则返回主菜单。 8. 插入信息函数void insert() 将要插入的学生的各种信息赋值给结构体数组中的stu[p]元素的各个成员,同样,各门课的综合、平均成绩通过将p作为实参传递给calculate(int i)函数中的形参i来计算。最后在函数末尾加上sort()函数,将由于插入数据而被打乱的结构体数组重新排序。 9. 排序函数 void sort() 利用选择法排序,设置一个struct student类型的临时变量temp,for(i=0;i { for(j=i+1;j if(stu[i].average {temp=stu[i];stu[i]=stu[j];stu[j]=temp;}} 通过对平均成绩的比较,交换两个学生所有信息,实现由高到低排序。 10. 防输错模块(分散于各个函数中) 由于在录入数据时可能未按要求录入选项,为了防止在此种情况下程序突然关闭,必须利用if else语句来修补这种漏洞。试举一例,在输出统计数据函数中 void census_output() { int option; system("cls"); printf("\n查询平均成绩排序>>>>>>>>>>>>请按1\n"); printf("\n查询不及格学生名单>>>>>>>>>>请按2.\n"); scanf("%d",&option); if(option==1){…………} else if(option==2){…………} else else {printf("您的输入有误,请选择1或2!");system("pause");getchar();census_output();} 五、运行过程截图 程序运行主菜单界面 录入信息界面 查找到信息输出后的界面 平均成绩输出界面 删除信息成功后的界面 修改信息成功后的界面 1) 怎样在输出文字后产生停顿?刚开始一直不懂,后来通过查询网络,使用system(“pause ”)产生停顿效果。 2) 由于录入及插入数据后,都需要计算课程综合成绩,学生平均成绩,直接写重复,不简洁,通过设置calculate()函数来统一计算。 3) 由于删除及插入数据操作使学生人数p发生了变化,因此在函数结尾时要对p进行相应的变化。 4) 经查询学号与查询姓名放在一个查询函数中,显得冗长且括号配对容易弄错,而且学号或者姓名输入错误要重新输入显得不方便,分别定义了两个分函数来执行,就避免了上面的问题。 5) 性别sex最好设置为含两个字符的字符数组,否则就可能遇到姓名及紧跟姓名的成员信息无法录入的问题。 6) Sort()函数中,临时储存学生信息的变量必须为struct student类型,不能为整型或者其他数据类型。 7) 引用结构体数组中某一元素的成员时,一定要写完整,不能只写成员名来引用,初学者容易犯此类错误。 8) 注意if else语句的括号配对关系。每条语句都必须以分号“;”结尾。 字符数组输入不用取地址符。 9) If语句后面如果要连续执行一些的指令,必须用大括号括起来,否则只能执行第一条语句。 为两周的课程设计接近尾声,我相信每一个认真去做的人都会体会到其中的困难,已经成功后的喜悦。课程设计主要从两方面提升了我。 一方面,通过此次课程设计,我们必须要把书上的只是综合起来,for循环,if else语句的使用,还有switch语句已经选择法排序的算法,还有结构体数组的使用等等,都必须有机地融合到程序之中,构成大程序的砖瓦。在两周时间里,我仔细思考了一个大程序如何运行,大程序中各个小的模块如何进行衔接,函数之间如何调用,函数的递归调用等问题,想的时间久了,这些问题我也逐渐搞清了,自己的程序也编写了出来。通过实践,对书上的内容做到了会使用,而不是仅仅表面上的理解。 另一方面,由于刚开始对程序编写毫无头绪,因此有一定的畏难情绪,不愿意开始编写这个程序,想要蒙混过关。最后通过看书,思考,发现并没有那么困难。等到把一个个分程序完成时,无形中我的克服困难的勇气与信心提升了。另外,编写程序,免不了有问题,通过对问题的解决、程序的调试,我培养了耐心严谨的品质,这对于自身的成长是有益的。 查询函数以及按学号查询函数 void inquire()//定义查找学号或者姓名函数 { void inquire_name(); void inquire_ID(); int a; system("cls");/*清屏函数*/ printf("\n请选择您查询的方式:\n\n通过学号:请按1\t\t\t通过名字:请按2\n"); scanf("%d",&a);/*通过输入的数字决定采用学号或姓名查找两种方式之一*/ if(a==1) inquire_ID(); else if(a==2) inquire_name(); else{printf("输入有误!请重新输入。");system("pause");getchar(); inquire();} printf("按任意键返回主菜单。\n"); system("pause"); menu(); } void inquire_ID() {int option; int i,ID,k,flag=0; printf("请输入要查寻的学号:\n"); scanf("%d",&ID); for(i=0;i 利用循环找到学生 { if(stu[i].ID==ID) {flag=1;k=i;} } if(flag)//找到学生后输出学生信息 { system("cls"); printf("所要查找的学号信息如下:\n"); printf("该学生信息:学号\t姓名\t班级\t性别\t年龄\n"); printf("%d\t%s\t%d\t%s \t%d\n\n",stu[k].ID,stu[k].name,stu[k].cla,stu[k].sex,stu[k].age); printf("该同学的c语言成绩如下平时\t考试\t综合\n"); printf("%5.2f\t%5.2f\t%5.2f\n\n",stu[k].clanguage.usual,stu[k].clanguage.exam,stu[k].clanguage.final); printf("该同学的数学成绩如下平时\t考试\t综合\n"); printf(" %5.2f\t%5.2f\t%5.2f\n\n",stu[k].math.usual,stu[k].math.exam,stu[k].math.final); printf("该同学的数学成绩如下平时\t考试\t综合\n"); printf(" %5.2f\t%5.2f\t%5.2f\n\n",stu[k].pe.usual,stu[k].pe.exam,stu[k].pe.final); printf("该同学的平均成绩为;%5.2f\n\n",stu[k].average); } else {system("cls"); printf("抱歉,未能找到该学号!\n重新输入请按1,返回主菜单请按2\n");//未找到学号,输出错误信息 scanf("%d",&option); if(option==1) {system("cls"); inquire_ID();} else if(option==2) menu(); } } 删除函数 void dele()//定义删除数据函数 { int i,ID,k,flag=0; int option; system("cls"); printf("请输入要删除记录的学生的学号:\n"); scanf("%d",&ID); for(i=0;i 利用循环找到所要删除的学号信息*/ { if(stu[i].ID==ID){flag=1;k=i;} /*找到该学号后,将i赋值给flag*/ } if(flag) /*flag 为真,则从输入的学好开始,将结构体数组中后一位的信息赋给前一位*/ { for(i=k;i stu[i]=stu[i+1]; p=p-1;/*完成删除后,学生数目全局变量的值减一*/ printf("\n数据删除成功!按任意键返回主菜单。\n\n"); system("pause");/*产生停顿*/ menu();/*调用菜单函数*/ } else //flag为零,返回主菜单 {printf("输入有误!按任意键返回主菜单\n"); system("pause"); menu(); } } 修改函数 void modify()//定义修改信息函数 { int i,ID,flag=0,k; int option; system("cls");/*清屏*/ printf("请输入要修改的学号:\n"); scanf("%d",&ID); for(i=0;i 用for循环找到学号,然后修改 { if(stu[i].ID==ID) {flag=1; k=i;} } if(flag) { printf("请选择要修改的项目:1,姓名2,性别3,年龄,4,班级\n"); printf("\t\t 5,c语言成绩6,数学成绩7,体育成绩\n"); scanf("%d",&option); if(option==1) { printf("请输入要修改的学生的姓名\n"); scanf("%s",stu[k].name); } else if(option==2) { printf("请输入要修改的学生的性别\n"); scanf("%s",stu[k].sex);} else if(option==3) {printf("请输入要修改的学生的年龄:\n"); scanf("%d",&stu[k].age);} else if(option==4) {printf("请输入要修改的学生的班级:\n"); scanf("%d",&stu[k].cla);} else if(option==5) {printf("请更新该学生c语言平时以及考试成绩;\n"); scanf("%f,%f",&stu[k].clanguage.usual,&stu[k].clanguage.exam);} else if(option==6) { printf("请更新该学生数学平时以及考试成绩;\n"); scanf("%f,%f",&stu[k].math.usual,&stu[k].math.exam);} else if(option==7) { printf("请更新该学生体育平时以及考试成绩;\n"); scanf("%f,%f",&stu[k].pe.usual,&stu[k].pe.exam);} calculate(k); printf("\n修改成功!继续修改请按1,返回主菜单请按2\n\n"); scanf("%d",&option); if(option==1) {system("cls");system("pause");modify();} else if(option==2) {system("cls");menu();} } else//未找到则输出错误信息,重新输入 {printf("您要修改的学号不存在!按任意键返回主菜单\n"); system("pause"); menu(); } } 排序函数 void sort()//定义排序函数 { int i,j; struct student temp;/*定义一个struct student 的临时变量*/ for(i=0;i { for(j=i+1;j if(stu[i].average {temp=stu[i];stu[i]=stu[j];stu[j]=temp;} } } 本文来源:https://www.2haoxitong.net/k/doc/5fd9ae0a6c85ec3a87c2c5ea.html六、问题,解决方法及注意事项
七、课程设计总结
八、部分源程序代码
文档为doc格式