资源描述
题目
学生成绩管理系统
一、 功能
1. 每一条记录包括一个学生的学号、姓名、语数外3门成绩、平均成绩
2. 输入功能:可以一次完成有限(不大于2000)条记录的输入
3. 显示功能:完成全部学生记录的显示
4. 查找功能:完成按学号或姓名查找学生记录,并显示
5. 排序功能:按学生学号或平均成绩进行排序
6. 保存功能:将学生记录保存在Information.txt文件中
7. 读取功能:将保存在文件中的学生记录读取出来
8. 有一个清晰美观界面来调用各个功能
二、 要求
1. 整个系统均用C语言实现
2. 利用指针、结构体数组或链表来实现学生成绩的数据结构设计
3. 系统具有输入、显示、查询、修改、删除、排序、保存、读取等基本功能
4. 系统的各个功能模块都用函数的形式来实现
5. 可以将学生成绩信息保存在文件中
6. 可以将学生信息从文件中读取出来
三、 设计内容
整个学生成绩管理系统由主函数及12个子函数构成,实现学生成绩录入、显示、查询、排序、修改、保存、读取和删除共8项功能,各函数功能相信说明如下:
1.主函数 int main()
利用无限次循环while和switch实现对各个函数的调用,使用时根据输入的数字来调用相应的函数
2. 显示主菜单函数void DispMainMenu()
这是一个无参函数,用来显示程序主菜单,用户通过输入对应功能前的数字来实现相应的功能
3. 学生成绩录入函数int InformationInput(STUDENT stu[],int cn)
这是一个有返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int cn为当前学生人数,返回值为当前学生人数。其作用是输入有限个学生的成绩信息。
算法:定义3个变量,num用来存放本次录入学生人数,i、j为循环变量。由键盘输入学生人数赋值给num,判断num是否大于MAX_NUM(2000),若大于,则提示输入人数太多,函数返回值0;若不大于,则依次输入num个学生信息。
4. 显示所有学生信息函数void DispInformation(STUDENT stu[],int MAX)
这是一个无返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为为当前学生人数。其作用是现实当前所有学生成绩信息。
5. 查找指定学号的学生的信息函数int FindStudentnumber(STUDENT stu[],int findnumber,int MAX)
这是一个有返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为当前学生人数。其作用是根据指定学号查询学生成绩信息,若查找到指定学号学生信息,则返回该学生学号,否则返回-1。
算法:
6. 查找指定姓名的学生的信息函数int FindStudentname(STUDENT stu[],char findname[],int MAX)
这是一个有返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为当前学生人数。其作用是根据指定姓名查询学生成绩信息,若查找到指定姓名学生信息,则返回该学生学号,否则返回-1。
算法:
7. 学生信息查询函数void QueryInformation(STUDENT stu[],int MAX)
这是一个无返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为当前学生人数。其作用是可以根据学号或姓名查找到指定学生的成绩信息。
算法:定义查询方式字符变量select,指定学号整型变量findnumber,指定姓名字符串数组findname[10],整型变量i,循环变量j。调用函数时,屏幕提示选择查询方式,若选择按学号查询,则输入学号后调用查找指定学号的学生的信息函数int FindStudentnumber(STUDENT stu[],int findnumber,int MAX)将返回值赋给变量i,若变量i不为-1,则查找成功,输出学生信息,否则在屏幕显示“输入学号不存在”;若选择按姓名查询则输入姓名后调用查找指定姓名的学生的信息函数int FindStudentname(STUDENT stu[],char findname[],int MAX)将返回值赋给i,若变量i不为-1,则查找成功,输出学生信息,否则在屏幕显示“输入学号不存在”。若在选择查询方式时输入除“1”、“2”外的其他字符,则提示“选择错误”。
N-S图
8. 修改学生信息函数 void EditInformation(STUDENT stu[],int MAX)
这是一个无返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为当前学生人数。其作用是修改或删除指定学生的成绩信息。
算法:定义整型变量i、j,j为循环变量;浮点型变量sum,用来寻访总成绩;整形变量findnum用来存放需要修改信息的学生学号;字符变量select用来存放修改方式代号。输入学号后调用查找指定学号的学生的信息函数int FindStudentnumber(STUDENT stu[],int findnumber,int MAX)将返回值赋给变量i,若变量i不为-1,则存在该学号学生。在屏幕提示选择修改方式,若选择修改信息,则先在屏幕输出原信息,后按提示依次修改信息;若选择删除信息,则调用删除信息函数void Delete(STUDENT stu[],int n,int MAX)删除该学号学生信息。若未查找到指定学号,则在屏幕输出“您输入的学号不存在”。
N-S图
9. 按学号排序函数void SortNum(STUDENT stu[],int MAX)
这是一个无返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为当前学生人数。其作用是用冒泡法将学生成绩信息按学号由小到大排列。
算法:定义循环变量i、j,结构体变量p作为中间变量。冒泡法完成排序后,调用显示所有学生信息函数void DispInformation(STUDENT stu[],int MAX)在屏幕打印出排序后的学生成绩信息。
N-S图
10. 按平均成绩排序函数void SortScore(STUDENT stu[],int MAX)
这是一个无返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为当前学生人数。其作用是用冒泡法将学生成绩信息按平均成绩由大到小排列。
算法:定义循环变量i、j,结构体变量p作为中间变量。冒泡法完成排序后,调用显示所有学生信息函数void DispInformation(STUDENT stu[],int MAX)在屏幕打印出排序后的学生成绩信息。
N-S图
11. 保存数据到文件函数void Save(STUDENT stu[],int MAX)
这是一个无返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int MAX为当前学生人数。其作用是将存放在结构体数组中的学生成绩信息保存到文件Information.txt中。
算法:定义整型变量i,文件指针*fp。若成功打开文件Information.txt,则用fwrite()将存放在结构体数组中的学生成绩信息保存到文件Information.txt中;若打开失败,则在屏幕输出“can not open file”。
N-S图
12. 打开数据文件函数int Read(STUDENT stu[])
这是一个有返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,返回值为读取到的学生信息个数,即学生人数。其作用是将存放在文件Information.txt中的学生成绩信息存放到结构体数组中。
算法:定义整型变量i,文件指针*fp。若成功打开文件Information.txt,则计数变量赋值为0,每完成一次读取,i自加1。若打开失败,则在屏幕输出“can not open file”。
N-S图
13.删除信息函数void Delete(STUDENT stu[],int n,int MAX)
这是一个无返回值的有参函数,形参STUDENT stu[]为结构体数组指针,表示存有学生信息的结构体数组的头指针,形参int n表示血药删除的学生序号,形参int MAX为当前学生人数。其作用是删除第n个学生的信息。
算法:定义循环变量i、j,文件指针*fp。打开存有学生成绩信息的文件Information.txt,在屏幕显示源信息。然后将存放在结构体数组中的信息,从第n个开始,之后每一组数据覆盖前一组数据,以达到删除信息的同时又保证结构体数组中信息连续的目的。之后当前学生人数自减1,重新保存数据到文件Information.txt,在屏幕输出当前所有学生信息。
N-S图
五、调试分析
1.运行时输入信息没有按照scanf()函数格式输入,导致程序无法正常继续运行。
2.按照正确格式输入完信息后按回车键后出现“烫烫烫烫”字样的乱码,后经检查发现在学生成绩输入函数int InformationInput(STUDENT stu[],int cn)中调用了显示所有学生信息函数void DispInformation(STUDENT stu[],int MAX),而显示所有学生信息函数void DispInformation(STUDENT stu[],int MAX)中,语句for (i=0;i<MAX;i++)后误按了一个“;”导致不能正常执行循环体,后经考虑,决定删除输入完后显示学生信息和排序的语句。
3.经2修改后再次运行,出现了运行结果一闪而过的情况,所以上网查找解决方法。先开始查到的方法是需要添加头文件#include<conio.h>并且在需要停留的地方输入语句“getch();”,再次运行发现运行结果还是一闪而过。再次查询后,将getch()改为“system("pause");”。再次运行能正常显示。
4.经3修改后再次运行,在排序部分,发现按照平均成绩排序时是由小到大排序的,不符合实际应用中最常用的由大到小排序,遂进行修改。
5.经4修改后,在修改信息时,结果不能正常输入学号,检查代码后发现语句“scanf("%d",&stu[i].number);”中“stu[i].number”前漏掉了取地址符号“&”。
6.经5修改后,程序能完整运行,但是在查看文件内容是发现信息均为乱码,后有查阅教科书,其解释为fread()和fwrite()一般用于二进制文件的处理。
7.程序运行后,界面内容太多,容易混乱,查询后添加清屏函数“system("cls");”
六、总结
经过这次C语言实践活动,我觉得我的C语言水平相对上学期期末又提高了不少。过去只是对单个知识点较为清楚,如今已经能够形成体系,并且写出有使用价值的程序。虽然程序很小,但是万事都要有个循序渐进、由易到难的过程。另外,这次实践对我通过江苏省计算机等级考试(二级C)也有很大的帮助。过去我们都是软件的使用者,看到的都是软件给我们处理日常事务的便捷之处,如今我们已经能深入后台,自己设计、编写程序了,今后还要躲在易用性和美观上面多下功夫。
我相信,这次实践会成为我今后进行编程、开发的良好开端和基础。
附程序源代码:
/***********************************头文件***********************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#include<conio.h>
#define MAX_NUM 2000 /*人数上限2000*/
/********************************定义数据结构********************************/
typedef struct student
{
int number; /*学号*/
char name[10]; /*姓名*/
float score[3]; /*三门课成绩*/
float aver; /*平均成绩*/
}STUDENT;
/**********************************函数原型**********************************/
void DispMainMenu(); /*显示主菜单*/
int InformationInput(STUDENT stu[],int cn); /*学生成绩录入*/
void DispInformation(STUDENT stu[],int MAX); /*显示所有学生信息*/
int FindStudentnumber(STUDENT stu[],int findnumber,int MAX); /*查找指定学号的学生的信息*/
int FindStudentname(STUDENT stu[],char findname[],int MAX); /*查找指定姓名的学生的信息*/
void QueryInformation(STUDENT stu[],int MAX); /*学生信息查询*/
void EditInformation(STUDENT stu[],int MAX); /*修改学生信息*/
void SortNum(STUDENT stu[],int MAX); /*按学号排序*/
void SortScore(STUDENT stu[],int MAX); /*按平均成绩排序*/
void Save(STUDENT stu[],int MAX); /*保存数据到文件*/
int Read(STUDENT stu[]); /*打开数据文件*/
void Delete(STUDENT stu[],int n,int MAX); /*删除信息*/
/*********************************显示主菜单*********************************/
void DispMainMenu()
{
printf("***********************学生成绩管理系统***********************\n");
printf(" \t1.信息录入 \t2.按学号排序\n");
printf(" \t3.按平均成绩排序 \t4.信息修改\n");
printf(" \t5.信息查询 \t6.保存到数据文件\n");
printf(" \t7.打开数据文件 \t8.显示所有学生信息\n");
printf(" \t0.退出");
printf("\n**************************************************************\n");
printf("请选择0-8:"); /*显示菜单信息*/
}
/*******************************学生成绩录入*******************************/
int InformationInput(STUDENT stu[],int cn)
{
int num,i,j;
float sum=0;
printf("\n请输入本次录入的学生人数:");
scanf("%d",&num);
if(num>MAX_NUM)
{
printf("您输入的人数太多,大于%d人!\n",MAX_NUM);
system("pause");
return 0;
}
for(i=cn;i<num+cn;i++) /*输入num个学生的信息*/
{
printf("请输入第%d个学生的学号:",i+1);
scanf("%d",&stu[i].number);
printf(" 姓名:");
scanf("%s",stu[i].name);
printf(" 语数外成绩:");
for(j=0;j<3;j++)
{
scanf("%f",&stu[i].score[j]);
sum=sum+stu[i].score[j];
}
stu[i].aver=sum/3;
sum=0;
}
system("pause");
return (num+cn);
}
/******************************显示所有学生信息******************************/
void DispInformation(STUDENT stu[],int MAX)
{
int i,j;
printf("\n序号\t学号\t姓名\t语数外成绩\t\t平均成绩\n");
for(i=0;i<MAX;i++)
{
printf("%d\t%d\t%s\t",i+1,stu[i].number,stu[i].name);
for(j=0;j<3;j++)
printf("%.2f\t",stu[i].score[j]);
printf("%.2f",stu[i].aver);
printf("\n");
}
printf("\n");
system("pause");
}
/**************************查找指定学号的学生的信息**************************/
int FindStudentnumber(STUDENT stu[],int findnumber,int MAX)
{
int i;
for(i=0;i<MAX;i++)
{
if(stu[i].number==findnumber)
break;
}
if(i<MAX) /*判断找到的i是否小于MAX,若小于,则执行了break跳出循环,即找到该指定学号的学生*/
return i;
else
return -1;
}
/**************************查找指定姓名的学生的信息**************************/
int FindStudentname(STUDENT stu[],char findname[],int MAX)
{
int i;
for(i=0;i<MAX;i++)
{
if(strcmp(stu[i].name,findname)==0)
break;
}
if(i<MAX) /*判断找到的i是否小于MAX,若小于,则执行了break跳出循环,即找到该指定姓名的学生*/
return i;
else
return -1;
}
/*******************************学生信息查询*******************************/
void QueryInformation(STUDENT stu[],int MAX)
{
char select;
int i,j;
int findnumber;
char findname[10];
printf("************************请选择查询方式************************\n");
printf(" \t1.按学号查询;\t2.按姓名查询\n");
printf("**************************************************************\n");
printf("请选择1或2:");
select=getche();
switch(select)
{
case '1':
printf("\n您选择的是按学号查询\n请输入学生的学号:"); /*按学号查询*/
scanf("%d",&findnumber);
if((i=FindStudentnumber(stu,findnumber,MAX))!=-1)
{
printf("\n查找结果如下:\n");
printf("\n学号\t姓名\t语数外成绩\t\t平均成绩\n");
printf("%d\t%s\t",stu[i].number,stu[i].name);
for(j=0;j<3;j++)
printf("%.2f\t",stu[i].score[j]);
printf("%.2f\n",stu[i].aver);
}
else
printf("您输入的学号不存在!\n");
break;
case '2':
printf("\n您选择的是按姓名查询\n请输入学生的姓名:"); /*按学号查询*/
scanf("%s",&findname);
if((i=FindStudentname(stu,findname,MAX))!=-1)
{
printf("\n查找结果如下:\n");
printf("\n学号\t姓名\t语数外成绩\t\t平均成绩\n");
printf("%d\t%s\t",stu[i].number,stu[i].name);
for(j=0;j<3;j++)
printf("%.2f\t",stu[i].score[j]);
printf("%.2f\n",stu[i].aver);
}
else
{
printf("您输入的学号不存在!\n");
system("pause");
}
break;
default:
printf("选择错误!\n");
}
}
/*******************************修改学生信息*******************************/
void EditInformation(STUDENT stu[],int MAX)
{
int i,j;
float sum=0;
int findnum;
char select;
printf("\n请输入学生学号:");
scanf("%d",&findnum);
if((i=FindStudentnumber(stu,findnum,MAX))!=-1)
{
printf("************************请选择修改方式**********************\n");
printf("\t1.修改信息;\t2.删除信息\n");
printf("****************************************************************\n");
printf("请选择1或2:");
select=getche();
switch(select)
{
case '1':
printf("您选择的是修改信息!\n");
printf("姓 名:%s\n",stu[i].name);
printf("原信息:\n 学号:%d\t语数外成绩:",stu[i].number);
for(j=0;j<3;j++)
printf("%.2f\t",stu[i].score[j]);
printf("\t平均成绩:%.2f\n",stu[i].aver);
printf("请输入新信息\n");
printf("学号:\t");
scanf("%d",&stu[i].number);
printf("姓名:\t");
scanf("%s",stu[i].name);
printf("语数外成绩:\t");
for(j=0;j<3;j++)
{
scanf("%f",&stu[i].score[j]);
sum=sum+stu[i].score[j];
}
stu[i].aver=sum/3;
break;
case '2':
printf("您选择的是删除信息!\n");
Delete(stu,i,MAX);
break;
}
}
else
{
printf("您输入的学号不存在!\n");
system("pause");
}
}
/*******************************按学号排序*******************************/
void SortNum(STUDENT stu[],int MAX) /*冒泡法由小到大排序*/
{
int i,j;
STUDENT p;
for(i=0;i<MAX-1;i++)
for(j=0;j<MAX-1-i;j++)
if(stu[j].number>=stu[j+1].number)
{
p=stu[j];
stu[j]=stu[j+1];
stu[j+1]=p;
}
printf("按学号排序后:\n");
DispInformation(stu,MAX);
}
/*****************************按平均成绩排序*****************************/
void SortScore(STUDENT stu[],int MAX) /*冒泡法由大到小排序*/
{
int i,j;
STUDENT p;
for(i=0;i<MAX-1;i++)
for(j=0;j<MAX-1-i;j++)
if(stu[j].aver>=stu[j+1].aver)
{
p=stu[j];
stu[j]=stu[j+1];
stu[j+1]=p;
}
printf("按平均成绩排序后:\n");
DispInformation(stu,MAX);
}
/*******************************保存数据到文件*******************************/
void Save(STUDENT stu[],int MAX)
{
int i;
FILE *fp;
if((fp=fopen("Information.txt","w+"))!=NULL)
{
for(i=0;i<MAX;i++)
fwrite(&stu[i],sizeof(STUDENT),1,fp);
fclose(fp);
}
else
printf("cannot open file!\n");
}
/*******************************打开数据文件*******************************/
int Read(STUDENT stu[])
{
int i;
int result=-1;
FILE *fp;
if((fp=fopen("Information.txt","r"))!=NULL)
{
i=0;
while(fread(&stu[i],sizeof(STUDENT),1,fp)!=0)
i++; /*读取到一个信息时,i作为学生人数自加1*/
result=i;
fclose(fp);
}
else
printf("cannot open the file!\n");
return result;
}
/*******************************删除信息*******************************/
void Delete(STUDENT stu[],int n,int MAX)
{
FILE *fp;
int i,j;
if((fp=fopen("Information.txt","rb"))==NULL)
{
printf("cannot open the file!\n");
exit(0);
}
printf("\n源信息:\n");
DispInformation(stu,MAX);
for(i=n;i<MAX-1;i++)
{
stu[i].number=stu[i+1].number;
strcpy(stu[i].name,stu[i+1].name);
for(j=0;j<3;j++)
stu[i].score[j]=stu[i+1].score[j];
stu[i].aver=stu[i+1].aver;
}
MAX--; /*删除一个学生信息后人数MAX自减1*/
printf("当前文件内容:\n");
Save(stu,MAX);
DispInformation(stu,MAX);
}
/*******************************主函数*******************************/
int main()
{
char select;
STUDENT stu[MAX_NUM];
int current_number=0;
select=0;
while(select!='0')
{
system("cls"); /*清屏*/
DispMainMenu();
select=getche();
switch(select)
{
case '0':
printf("\n您选择的是退出\n");
system("pause");
continue;
case '1':
printf("\n您选择的是信息录入\n");
current_number=InformationInput(stu,current_number);
break;
case '2':
printf("\n您选择的是按学号排序\n");
SortNum(stu,current_number);
break;
case '3':
printf("\n您选择的是按平均成绩排序\n");
SortScore(stu,current_number);
break;
case '4':
printf("\n您选择的是信息修改\n");
EditInformation(stu,current_number);
break;
case '5':
printf("\n您选择的是信息查询\n");
QueryInformation(stu,current_number);
system("pause");
break;
case '6':
printf("\n您选择的是保存到数据文件\n");
Save(stu,current_number);
system("pause");
break;
case '7':
printf("\n您选择的是打开数据文件\n");
if((current_number=Read(stu))==-1)
current_number=0;
else
DispInformation(stu,current_number);
break;
case '8':
printf("\n您选择的是显示所有学生信息\n");
DispInformation(stu,current_number);
break;
default:
printf("\n选择错误,请重新选择!\n");
system("pause");
}
}
return 0;
展开阅读全文