资源描述
淮北师范大学
程序设计课程设计
学 生 管 理 系 统
———学生成绩管理系统
学 院 计算机科学与技术
专 业 计算机科学与技术(师范)
学 号 ***********
学 生 姓 名 * * *
指导教师姓名 * * *
2010年12月 28 日
16 / 17
一、设计目的与内容
(1)实验目的
l 进一步巩固和复习C程序设计的基础知识。
l 培养学生结构化程序、模块化程序设计的方法和能力。
l 提高学生调试程序的技巧和软件设计的能力。
l 提高学生分析问题、解决问题以及综合利用C语言进行程序设计的能力。
l 了解软件的编制过程。
(2)实验内容
1) 实现对学生信息的查找、添加、删除、修改、浏览、保存、从文件读取功能。
2) 使用结构体对学生信息的存储。
3) 使用链表实现对学生信息的查找、添加、删除、修改、浏览等操作。
4) 使用文件完成数据的存储与读取,要求每次运行某个模块时将数据读入结构体中,并 提供保存选项,将结构体中的数据保存在文件中。
二、算法的基本思想
(1)数据结构
学生成绩信息:
typedef struct studentscore
{ char name[10]; //定义姓名的字符数组
char num[20]; //定义学号的字符数组
struct subject
{char subname[20];//定义学科名的字符数组
float score; //保存学生各科成绩
}sub[5]; //共五门课
double sum; //总分
struct studentscore *next;
}STUCORE;
(2)本系统涉及的知识点
结构体、数组、循环、函数、指针、链表、文件操作。
(3)功能要求功能模块
1、建立学生信息,每个学生的信息包括:学号、姓名、性别、班级、学院
2、用链表的形式对学生信息分别进行查找、添加、删除、修改
3、结果保存在磁盘上
(4)功能模块
学生管理系统
1.文件操作
2.学生基本信息管理
3.学生成绩信息管理
4.退出
文件操作
1.从文件中读取信息
2.学生信息存入文件
3.返回
学生成绩信息管理
1. 查找成绩信息
2. 添加成绩信息
3. 删除成绩信息
4. 修改成绩信息
5. 返回
修改成绩信息
删除成绩信息
添加成绩信息
查找成绩信息
1.按学号查找
2.按姓名查找
3.返回
学生信息存入文件
1.保存学生基本信息
2.保存学生成绩信息
从文件中读取信息
1.读取学生基本信息
2.读取学生成绩信息
(4)算法功能描述
①总体功能说明:
本系统可以做到对1.学生信息:学号、姓名、性别、学院、班级。2.学生成绩信息:学号、姓名、一名学生五门不同学科的学科名及该科成绩。分别进行添加、修改、查找、删除、保存、载入功能。
②学生成绩信息管理功能说明:
可以添加学生学号、姓名、及对一名学生五门不同学科的学科名及该科成绩。并可以通过对输入的学生成绩信息进行修改、删除、保存、载入功能并通过学号和姓名两种方式查找,并且对同名的学生也可以进行区分。并且会保持学好的一致性,保证任意两名学生不会出现学号相重复的情况。
三、主要功能模块流程图(按姓名查找信息的流程图)
Start
Scanf(“%s”,no)
if(strcmp(p->name,no)==0)
while(p!=NULL)
0
1
Printf(“查无此人”)
Printf(“所有信息”)
END
按姓名查找流程图
四、 系统测试
1.主程序界面
首先进入1.文件管理操作。建立单链表。
2.文件管理操作
选择读取的文件(第一次运行时因文件未建立只有在读取文件后才能执行保存文件)
读入文件后就可选择进入的系统。
选择2进入学生基本信息管理系统;
选择3进入学生成绩信息管理系统。
3.学生成绩信息管理
选择1:查询成绩信息。
选择2:添加成绩信息。
选择3:删除成绩信息。
选择4:修改成绩信息。
选择5:返回。
A. 查询成绩信息
选择1:按学号查询成绩信息。
选择2:按姓名查询成绩信息。
可以查找到同名学生的信息。
B. 添加成绩信息
如图添加学生成绩信息。继续添加输入y否则输入n。添加完成后请去往文件管理保存!
C. 删除成绩信息
如图删除学生基本信息。继续删除其它学生输入y否则输入n。删除完成后请去往文件管理保存!
D. 修改成绩信息
如图修改学生基本信息。继续修改其它学生输入y否则输入n。修改完成后请去往文件管理保存!
五、 结论
通过这次课程设计,我感觉到要真正做出一个程序并不很容易,但只要用心去做,总会有收获,特别是当我遇到 一个问题,想办法去解决,最后终于找到方法时,心里的那份喜悦之情真是难以形容。编写程序中遇到问题再所难免,应耐心探究其中的原因,从出现问题的地方起,并联系前后程序,仔细推敲,逐个排查。直到最终搞清为止。我对于链表也有了更深层次的理解,尤其是采用动态内存分配malloc函数的使用。
但我的程序仍让不够完美,因为我修改信息时还不能对学号进行判断,就是说如果修改时使两个学生学号相同就一并保存下来。在查询中可以一并查询出来,但删除修改操作需要按录入顺序捉个操作。这是该程序的不足。而且,在姓名查找中必不能实现模糊查找功能。也就是说,不能对某同学姓名中的一部分进行判断进而进行查找。
这次课程设计能够顺利完成要首先感谢韩玲老师对我的悉心教导,她在我整个编程中给予了我很大帮助。还感谢王保华老师为我解释了查询中链表的循环,陈美荣老师为我讲解了动态内存分配malloc函数。在此我要感谢所有为我的课程设计付出心血的老师们!
参考文献:
谭浩强,《C程序设计(第二版)》,清华大学出版社。
严蔚敏,吴伟民,《数据结构(C语言版)》,清华大学出版社。
六、 源程序及系统文件使用说明
学生成绩信息管理中各模块的功能说明程序代码设计
一:结构体:
typedef struct studentscore
{ char name[10];
char num[20];
struct subject
{char subname[20];
float score;
}sub[5]; //保存学生各科成绩
double sum; //总分
struct studentscore *next;
}STUCORE;
二:添加学生成绩信息函数:(void add_score())
1)函数原形:void add_score()
2)功 能:采用动态内存分配malloc函数和链表结构。利用do while、while循环结构strcpy函数依次输入学生学号、姓名、及对一名学生五门不同学科的学科名及该科成绩。将信息保存在内存中建立的链表里。
3)变量及类型:
STUCORE *stu,*p; 定义结构体指针
char k; 用来接收输入的(y/n)以便通过do while判断是否继续添加信息
int flag; 定义一个整型变量来判断所添加的学生学号是否已经存在文件中,保证学号唯一性
p=head_2; 将结构体下定义的头指针head_2赋给p
4)说明:执行完输入函数后,会在键盘缓冲区中保存回车键,后面再对字符型变量赋值时,会将缓冲区中的回车键当成数据存入变量中,所以要在某些输入语句后面加getchar()函数。并在函数调用结束时利用system("cls")执行清屏操作。添加完成后需要去往文件操作保存。
void add_score()//添加学生成绩信息
{STUCORE *stu,*p;char k;p=head_2; int flag=0;
do
{stu=( STUCORE *) malloc(sizeof(STUCORE));
printf("输入学生的成绩信息:\n");
while(flag==0){printf("请输入学生学号:");scanf("%s",no);flag=Judge(no);}
strcpy(stu->num,no);printf("请输入学生姓名:");scanf("%s",stu->name);
printf("请输入第一门课学科名:");scanf("%s",stu->sub[0].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[0].score);
printf("请输入第二门课学科名:");scanf("%s",stu->sub[1].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[1].score);
printf("请输入第三门课学科名:");scanf("%s",stu->sub[2].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[2].score);
printf("请输入第四门课学科名:");scanf("%s",stu->sub[3].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[3].score);
printf("请输入第五门课学科名:");scanf("%s",stu->sub[4].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[4].score);
stu->sum=stu->sub[1].score+stu->sub[2].score+stu->sub[3].score+stu->sub[4].score+stu->sub[0].score;
getchar();printf("\t\t输入学生信息完成。\n");
while(p->next!=NULL)p=p->next;
p->next=stu;p=stu;p->next=NULL;
printf("\n添加完成后请去往文件管理保存!\n\n是否继续添加学生信息?(y/n):\n");
}while((k=getchar())=='y');
getchar(); system("cls");}
三:删除学生成绩信息函数(void del_score())
1)函数原形:void del_score()
2)功 能:利用strcmp函数、do while、while循环结构通过学号找到要删除的学生并利用链表执行删除操作。将信息保存在内存中建立的链表里。
3)变量及类型:
STUCORE *p,*q; 定义结构体指针
char no[10]; 定义输入的待比较变量
char k,ch; 用来接收输入的(y/n)以便通过do while判断是否删除信息
p=head_2; 将结构体下定义的头指针head_2赋给p
4)说明:执行完删除函数后,会在键盘缓冲区中保存回车键,后面再对字符型变量赋值时,会将缓冲区中的回车键当成数据存入变量中,所以要在某些输入语句后面加getchar()函数。并在函数调用结束时利用system("cls")执行清屏操作。删除完成后需要去往文件操作保存。
void del_score()//删除学生成绩信息
{ STUCORE *p,*q;char no[10];char k,ch;
Do
{ p=head_2;printf("\t\t删除学生的详细资料 \n\n\n");
printf("请输入要删除学生的学号:");scanf("%s",no);
while(strcmp(p->num,no)!=0&&p->next!=NULL) {q=p; p=p->next;}
if(strcmp((p->num),no)==0)
{printf("要删除的学生成绩信息:");
printf("学号:%s\n",p->num);printf("姓名:%s\n",p->name);
printf("%s 成绩: %f\n",p->sub[0].subname,p->sub[0].score);
printf("%s 成绩: %f\n",p->sub[1].subname,p->sub[1].score);
printf("%s 成绩: %f\n",p->sub[2].subname,p->sub[2].score);
printf("%s 成绩: %f\n",p->sub[3].subname,p->sub[3].score);
printf("%s 成绩: %f\n",p->sub[4].subname,p->sub[4].score);
printf("总分:%lf\n",p->sum);getchar();
printf("\n确定删除吗?y/n?\n\n");ch=getchar();
if(ch=='y'){q->next=p->next;printf("\n\t\t\t已删除该学生\n\n");}}
else printf("\n\t\t\t没有该学生\n\n");getchar(); printf("\n删除完成后请去往文件管理保存!\n\n是否继续删除其它学生信息?(y/n?):\n");k=getchar();}while(k=='y');
getchar();system("cls");}
四:修改学生成绩信息函数(void modify_score())
1)函数原形:void modify_score()
2)功 能:利用strcmp函数、do while、while循环结构通过学号找到要修改的学生并利用链表执行修改操作。并将修改后的信息保存在内存中建立的链表里。
3)变量及类型:
STUCORE *p; 定义结构体指针
char no[10]; 定义输入的待比较变量
char k; 用来接收输入的(y/n)以便通过do while判断是否继续修改信息
p=head_2; 将结构体下定义的头指针head_2赋给p
4)说明:执行完修改函数后,会在键盘缓冲区中保存回车键,后面再对字符型变量赋值时,会将缓冲区中的回车键当成数据存入变量中,所以要在某些输入语句后面加getchar()函数。并在函数调用结束时利用system("cls")执行清屏操作。修改完成后需要去往文件操作保存。
void modify_score()//修改学生成绩信息
{system("cls");STUCORE *p;char no[30];char k;
do
{p=head_2;printf("\t\t修改学生的详细资料\n");
printf("输入学生学号:");scanf("%s",no);
while(strcmp(p->num,no)!=0&&p->next!=NULL){ p=p->next;}
if(strcmp((p->num),no)==0)
{printf("要修改的学生的详细资料:\n");
printf("学号:%s\n",p->num);printf("姓名:%s\n",p->name);
printf("%s 成绩: %f\n",p->sub[0].subname,p->sub[0].score);
printf("%s 成绩: %f\n",p->sub[1].subname,p->sub[1].score);
printf("%s 成绩: %f\n",p->sub[2].subname,p->sub[2].score);
printf("%s 成绩: %f\n",p->sub[3].subname,p->sub[3].score);
printf("%s 成绩: %f\n",p->sub[4].subname,p->sub[4].score);
printf("总分:%lf\n",p->sum);
printf("\n\t\t********根据提示输入修改后的信息**********\n\n");
printf("输入新的学生的成绩信息:\n");
printf("请输入新的学生学号:");scanf("%s",p->num);
printf("请输入新的学生姓名:");scanf("%s",p->name);
printf("请输入第一门课学科名:");scanf("%s",stu->sub[0].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[0].score);
printf("请输入第二门课学科名:");scanf("%s",stu->sub[1].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[1].score);
printf("请输入第三门课学科名:");scanf("%s",stu->sub[2].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[2].score);
printf("请输入第四门课学科名:");scanf("%s",stu->sub[3].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[3].score);
printf("请输入第五门课学科名:"); scanf("%s",stu->sub[4].subname);
printf("请输入该课成绩:");scanf("%f",&stu->sub[4].score);
stu->sum=stu->sub[1].score+stu->sub[2].score+stu->sub[3].score+stu->sub[4].score+stu->sub[0].score;}
else
printf("\t\t没有此学生信息!\n\n");
getchar();printf("\n修改完成后请去往文件管理保存!\n\n是否继修改学生信息?(y/n):\n");k=getchar();}while(k=='y');
getchar();system("cls");}
五:按学号查找学生成绩信息函数(void search_num())
1)函数原形:void search_num()
2)功 能:利用strcmp函数、do while、while循环结构通过学号找到要查找的学生并将该学生成绩信息显示出来。
3)变量及类型:
STUCORE *p; 定义结构体指针
char no[10]; 定义输入的待比较变量
char k;用来接收输入的(y/n)以便通过do while判断是否继续利用学号查询信息
int flag; 定义一个整型变量来判断所查找的学生是否存在文件中
p=head_2; 将结构体下定义的头指针head_2赋给p
4)说明:执行完查询函数后,会在键盘缓冲区中保存回车键,后面再对字符型变量赋值时,会将缓冲区中的回车键当成数据存入变量中,所以要在某些输入语句后面加getchar()函数。并在函数调用结束时利用system("cls")执行清屏操作。
void search_num()//按学号查找学生成绩信息
{STUCORE *p;char no[10];char k;int flag;
do
{p=head_2;flag=0;printf("请输入要查找学生的学号:");scanf("%s",no);
while(p!=NULL)
if (strcmp(p->num,no)==0)
{printf("要查询的学生详细资料:\n");
printf("学号:%s\n",p->num);printf("姓名:%s\n",p->name);
printf("%s 成绩: %f\n",p->sub[0].subname,p->sub[0].score);
printf("%s 成绩: %f\n",p->sub[1].subname,p->sub[1].score);
printf("%s 成绩: %f\n",p->sub[2].subname,p->sub[2].score);
printf("%s 成绩: %f\n",p->sub[3].subname,p->sub[3].score);
printf("%s 成绩: %f\n",p->sub[4].subname,p->sub[4].score);
printf("总分:%lf\n",p->sum);p=p->next;flag=1;}
else
p=p->next;
if(flag==0) printf("\n\t\t\t没有该学生\n\n");getchar();printf("\n是否继续查找其它学生信息?y/n?\n");k=getchar();}while(k=='y');
getchar();printf("\n\t\t查看完毕!按任意键返回");getchar();system("cls");}
六:按姓名查找学生成绩函数(void search_name ())
1)函数原形:void search_name()
2)功 能:利用strcmp函数、do while、while循环结构通过姓名找到要查找的学生并将该学生成绩信息显示出来。(包括同名的学生)
3)变量及类型:
STUCORE *p; 定义结构体指针
char no[10]; 定义输入的待比较变量
char k;用来接收输入的(y/n)以便通过do while判断是否继续利用姓名查询信息
int flag; 定义一个整型变量来判断所查找的学生是否存在文件中
p=head_2; 将结构体下定义的头指针head_2赋给p
4)说明:执行完查询函数后,会在键盘缓冲区中保存回车键,后面再对字符型变量赋值时,会将缓冲区中的回车键当成数据存入变量中,所以要在某些输入语句后面加getchar()函数。并在函数调用结束时利用system("cls")执行清屏操作。
void search_name()//按姓名查找学生成绩
{STUCORE *p;char no[10];char k;int flag;
do
{p=head_2;flag=0;printf("请输入要查找学生的姓名:");scanf("%s",no);
while(p!=NULL)
if (strcmp(p->name,no)==0)
{printf("要查询的学生详细资料:\n");
printf("学号:%s\n",p->num);printf("姓名:%s\n",p->name);
printf("%s 成绩: %f\n",p->sub[0].subname,p->sub[0].score);
printf("%s 成绩: %f\n",p->sub[1].subname,p->sub[1].score);
printf("%s 成绩: %f\n",p->sub[2].subname,p->sub[2].score);
printf("%s 成绩: %f\n",p->sub[3].subname,p->sub[3].score);
printf("%s 成绩: %f\n",p->sub[4].subname,p->sub[4].score);
printf("总分:%lf\n",p->sum);p=p->next;flag=1;}
else
p=p->next;
if(flag==0) printf("\n\t\t\t没有该学生\n\n");getchar();printf("\n是否继续查找其它学生信息?y/n?\n");k=getchar();}while(k=='y');
getchar();printf("\n\t\t查看完毕!按任意键返回");getchar();system("cls");}
七:查找学生成绩信息函数
void search_score()//查找学生成绩信息
{system("cls");int a;
printf("\t\t**************************************\n");
printf("\t\t**************************************\n");
printf("\t\t\t1:按学号查找。\n");printf("\t\t\t2:按姓名查找。\n");printf("\t\t\t3:退出。\n");
printf("\t\t**************************************\n");
printf("\t\t**************************************\n");
printf("\n\t\t输入一个有效的数字,选择你要做的操作:\n");scanf("%d",&a);
switch(a)
{case 1:search_num();break;case 2:search_name();break;case 3:score();break;
default:printf("\t\t\t错误的菜单选项\n\n");break;}}
八:学生成绩管理函数
void score()//学生成绩管理
{system("cls");int a;
printf("\t\t*************学生管理系统**************\n");
printf("\t\t**************************************\n");
printf("\t\t\t1:查找成绩信息。\n");printf("\t\t\t2:添加成绩信息。\n");
printf("\t\t\t3:删除成绩信息。\n");printf("\t\t\t4:修改成绩信息。\n");
printf("\t\t\t5:返回。\n");
printf("\t\t**************************************\n");
printf("\t\t**************************************\n");printf("\n\t\t输入一个有效的数字,选择你要做的操作:\n");scanf("%d",&a);
switch(a)
{case 1:search_score();break;case 2:add_score();break;
case 3:del_score();break;case 4:modify_score();break;
case 5:main();break;default:printf("\t\t\t错误的菜单选项\n\n");break;}}
九:文件载入函数(void file3(void))
1)函数原形:void file3(void)
2)功 能:采用动态内存分配malloc函数和链表结构。建立打开“student.dat”文件保存数据。并建立头指针为head_2的单链表。
3)变量及类型:
STUCORE *stu,*p; 定义结构体指针
FILE *fp; 定义文件指针
4)说明:执行操作前一定要先执行void file3(void) 以通过动态内存分配建立打开“student.dat”文件保存数据。并建立头指针为head_2的单链表。
void file3(void)//文件载入
{STUCORE *stu,*p;FILE *fp;stu=( STUCORE *) malloc(sizeof(STUCORE));
if((fp=fopen("student.dat","rb"))==NULL)
{printf("\t\t\t暂无学生信息,请添加!\n\n");head_2=stu;head_2->next=NULL;}
else {head_2=p=stu;
do
{if(fread(stu,sizeof(STUCORE),1,fp)==1)
{p->next=stu;p=p->next;stu=( STUCORE *) malloc(sizeof(STUCORE));}
}while(!feof(fp));p->next=NULL;}}
十:文件保存写入函数(void file4(void))
1)函数原形:void file4(void)
2)功 能:将链表内存中的数据保存写入到“student.dat”文件中。
3)变量及类型:
STUCORE *stu,*p; 定义结构体指针
FILE *fp; 定义文件指针
4)说明:执行添加,删除,修改操作后一定要执行void file4(void) 以将链表内存中的数据保存写入到“student.dat”文件中。
void file4(void) //文件保存写入
{STUCORE *p;FILE *fp;
if((fp=fopen("student.dat","wb+"))==NULL)
printf("\t\t\t文件无法正常打开!\n\n");
else
{p=head_2;
do
{fwrite(p,sizeof(STUCORE),1,fp); p=p->next;}while(p!=NULL);}
fclose(fp);}
十一:判断学号唯一函数
1)函数原形:void search_name()
2)功 能:利用while循环结构和if语句通过strcmp比较输入的学号与文件中已经保存过的学号信息,并通过返回(1/0)来选择是否允许该学号添加从而达到学号的唯一性。
3)变量及类型:
STUCORE *p; 定义结构体指针
p=head_2; 将结构体下定义的头指针head_2赋给p
int Judge(char no[10])
{STUCORE *p; p=head_2;
while(strcmp(p->num,no)!=0&&p->next!=NULL) {p=p->next;}
if(strcmp((p->num),no)==0)
{printf("学号输入失败,该学号已存在,请重新输入!\n");return (0);} return (1);}
十二:文件管理
void file(void)//文件管理
{system("cls");int a;
printf("\t\t*************文件管理*****************\n");
printf("\t\t**************************************\n");
printf("\t\t\t1:读取学生信息文件。\n");printf("\t\t\t2:学生信息文件保存。\n");
printf("\t\t\t3:读取学生成绩文件。\n");printf("\t\t\t4:学生信息文件保存。\n");
printf("\t\t\t5:返回。\n");
printf("\t\t**************************************\n");
printf("\t\t**************************************\n");
printf("\n\t\t输入一个有效的数字,选择你要做的操作:\n");scanf("%d",&a);
switch(a)
{case 1:file1();break;case 2:file2();break;
case 3:file3();break;case 4:file4();break;
case 5:main();break;default:printf("\t\t错误的菜单选项");break;}}
十三:主函数
void main()//主函数
{int a;
while(1)//无限循环
{printf("\t\t*************学生管理系统**************\n");
printf("\t\t\t1:文件管理操作。\n");printf("\t\t\t2:学生基本信息管理。\n");
printf("\t\t\t3:学生成绩信息管理。\n");printf("\t\t\t4:退出。\n");
printf("\t\t**************************************\n");
printf("\n\t\t输入一个有效的数字,选择你要做的操作:\n"); scanf("%d",&a);
switch(a)
{case 1:file();break;case 2:message();break;
case 3:score();break;case 4:printf("\t\t退出系统成功\n\n");exit(0);break;
default:printf("\t\t\t错误的菜单选项\n\n");break; }
}}
展开阅读全文