一、实验内容
编写并调试程序,实现学校各专业班级学生信息的管理。将10个学生的信息存储在文件studentInit.dat中;并定义学生信息的结构体类型,包括:学号、姓名、专业、班级、3门成绩;和符号常量N(学生数)。
#define N 10
struct Student{
char num[15];//学号
char name[15];//姓名
char major[10];//专业(computer,software,network)
int classNo;//班级(1-2)
int score[3];//3门课的成绩(0-2)
};
typedef
struct Student STU;
二、实验要求
(1)main函数:以菜单形式将各项功能提供给用户,根据用户的选择,调用相应的函数。 STU student[N]; //保存输入的N名学生信息
(2)定义函数void Input(STU *p, int n):从文件sutdentInit中输入n个学生的信息。
(3)定义函数void Output(STU *p):将p所指的某个学生信息表格化屏幕输出。
(4)定义函数STU Fetch(int studentIndex):从文件中随机读取第studentIndex个(0<= studentIndex <=N-1)学生的信息。
(5)定义函数void Search(STU *p, int classNo, char s, int scoreSum);:实现班级和成绩的综合查找(如1班,总分>240的同学)。
(6)定义函数int Max(STU *p, int scoreIndex):求所有学生、下标为scoreIndex的课程分数最高的学生序号(在数组中的下标),学生序号作为返回值。
(7)定义函数void Sort_select(STU *p): 对所有学生,按平均成绩由低到高进行简单选择排序。
(8)定义函数void Sort_buble(STU *p, int n); 对某个班级的学生,按平均成绩由高到低进行起泡排序。并调用Output输出。定义局部变量: STU stu_class_ave[N]; //按平均成绩排序后的某个班级的学生信息; int count;//实际元素个数
(9)定义函数void Sort_insert(STU *p, int n, char *major):对某个专业的学生,按某门课程成绩由低到高进行直接插入排序。并调用Output输出。 定义局部变量: STU stu_class_ subject [N]; //按某门课程成绩排序后的某个专业的学生信息; int count; //实际元素个数
(10)定义函数void Save(STU *p,int n) :将学生信息存入文件。
(11)定义函数void Welcome(),制作学生管理系统界面菜单。
(12)定义函数void Read() :从文件中读取所有学生信息到结构体中。 (13)定义函数void Revise(STU *p) :修改学生信息,其中可以选择修改学生的姓名、专业、班级、三门成绩中的任意某门成绩。
(14)定义函数void Delete(STU *p,int n) :从结构体中删除n个学生信息。
(15)定义函数void Add(STU *p,int n),添加n个学生信息到结构体中。
(16)定义函数void Sort_select_reverse(STU *p),对所有学生,按平均成绩由高到低进行简单选择排序。
(17) 定义函数void Sort_buble_reverse(STU *p,int n):某个班级的学生,按平均成绩由低到高进行起泡排序。并调用Output输出。
(18)定义函数voidSort_insert_reverse(STU *p,int n,char *major):对某个专业的学生,按某门课程成绩由高到低进行直接插入排序。并调用Output输出。
三、算法流程图(插入排序)
四、程序清单
#include#include #include #include #include #define N 10 struct Student{ char num[15]; //学号 char name[15]; //姓名 char major[20]; //专业(computer,software,network) int classNo; //班级(1-2) int score[3]; //3门课的成绩(0-2) int sum=0; //三门课的总成绩 double aver; //三门课的平均成绩 }; typedef struct Student STU; int start=0; //结构体数组的开头 int end=10; //结构体数组的结尾 STU stu[N+10]; //定义结构体数组 int mp[100]; //定义数组,记录某课程最高分的序号 //以下为调用函数 void welcome(); void Input(STU *p,int n); //从文件sutdentInit中输入n个学生的信息 void Read(); //从文件中读取学生信息 void Output(STU *p); //将文件里的全部学生信息表格化屏幕输出。 STU Fetch(int studentIndex); //从文件中随机读取第studentIndex个(0<= studentIndex <=N-1)学生的信息。 void Search(STU *p,int classNo,int scoreSum); //实现班级和成绩的综合查找(如1班,总分>240的同学)。 int Max(STU *p,int scoreIndex); //求所有学生、下标为scoreIndex的课程分数最高的学生序号(在数组中的下标),学生序号作为返回值。 void Sort_select(STU *p); //对所有学生,按平均成绩由低到高进行简单选择排序。 void Sort_select_reverse(STU *p) ; //对所有学生,按平均成绩由高到低进行简单选择排序。 void Sort_buble(STU *p,int n); //对某个班级的学生,按平均成绩由高到低进行起泡排序。并调用Output输出。 void Sort_buble_reverse(STU *p,int n); 对某个班级的学生,按平均成绩由低到高进行起泡排序。并调用Output输出。 void Sort_insert(STU *p,int n,char *major); //对某个专业的学生,按某门课程成绩由低到高进行直接插入排序。并调用Output输出。 void Sort_insert_reverse(STU *p,int n,char *major); //对某个专业的学生,按某门课程成绩由高到低进行直接插入排序。并调用Output输出。 void Save(STU *p,int n); //将学生信息存入文件。 void Revise(STU *p); //修改学生信息 void Delete(STU *p,int n); //删除n个学生信息 void Add(STU *p,int n); //添加学生信息 int main(){ while(1) { welcome(); } system("pause"); return 0; } void welcome() { int num; printf(" ***********************************************************n"); printf(" * 学生信息管理系统 *n"); printf(" ***********************************************************nn"); printf(" *******************系统功能菜单****************************n"); printf(" ---------------------- ------------------------------- n"); printf(" ***************************************************** n"); printf(" * 0.写入学生信息到文件里 * * 1.从文件中读取学生信息 * n"); printf(" ***************************************************** n"); printf(" * 2.输出全部学生信息 * * 3.文件中随机读取学生信息 * n"); printf(" ***************************************************** n"); printf(" * 4.班级成绩综合查询 * * 5.课程最高分成绩查询 * n"); printf(" ***************************************************** n"); printf(" * 6.全体学生平均分查询 * * 7.班级学生平均分查询 * n"); printf(" ***************************************************** n"); printf(" * 8.专业课程成绩查询 * * 9.添加学生信息 * n"); printf(" ***************************************************** n"); printf(" * 10.修改学生信息 * * 11.删除学生信息 * n"); printf(" ***************************************************** n"); printf(" * 12.保存学生信息到文件里* * 13.退出程序 * n"); printf(" ***************************************************** n"); printf(" ---------------------- ---------------------- n"); printf("请选择菜单编号:"); scanf("%d", &num); switch (num) { case 0: Input(&stu[start],N); break; case 1: Read(); break; case 2: printf("全部学生信息如下:n"); printf("**********************************************************************************************************n"); printf("* 学号 * 姓名 * 专业t * 班级 * 语文 * 数学 * 英语 * 平均分 * 总分n"); for(int i=0;i Output(&stu[i]); } printf("**********************************************************************************************************nnnn"); system("pause"); break; case 3: printf("请输入需要查询的学生序号:n"); int x; scanf("%d",&x); Fetch(x); printf("nnn"); system("pause"); printf("nnn"); break; case 4: int n; int grade; printf("请输入需要查询的班级n以及班级总分grade:n"); scanf("%d%d",&n,&grade); Search(&stu[start],n,grade); printf("nnnn"); system("pause"); printf("nnnn"); break; case 5: int y; printf("请输入课程序号(0是语文、1是数学、2是英语)n"); scanf("%d",&y); printf("该课程最高分的学生序号和姓名为:n"); for(int i=0;i printf("%d %sn",mp[i],stu[mp[i]].name); } printf("nnnnnn"); break; case 6: printf("请选择tt升序查询(1)t降序查询(2)tnn"); int aa; scanf("%d",&aa); switch(aa) { case 1: Sort_select(stu); break; case 2: Sort_select_reverse(stu); break; } printf("nnnnn"); system("pause"); printf("nnnn"); break; case 7: int p; printf("请输入要查询的班级(1、2、3):n"); scanf("%d",&p); printf("请输入tt升序排序(1)t降序排序(2)nn"); int bb; scanf("%d",&bb); switch(bb) { case 1: Sort_buble_reverse(stu,p); break; case 2: Sort_buble(stu,p); break; } printf("nnn"); system("pause"); printf("nnn"); break; case 8: int m; char str[15]; printf("请输入查询课程(0是语文,1是数学,2是英语)和专业(computer、pilot、teacher、nurse、driver)n"); scanf("%d%s",&m,str); printf("请输入tt升序排序(1)t降序排序(2)t"); int cc; scanf("%d",&cc); switch(cc){ case 1: Sort_insert(stu,m,str); break; case 2: Sort_insert_reverse(stu,m,str); break; } printf("nnn"); system("pause"); printf("nnn"); break; case 9: int a; printf("请输入要添加信息的学生个数:n"); scanf("%d",&a); Add(&stu[end],a); printf("nnn"); system("pause"); printf("nnn"); break; case 10: Revise(stu); printf("nnn"); system("pause"); printf("nnn"); break; case 11: printf("请输入要删除信息的学生个数:n"); int xx; scanf("%d",&xx); Delete(stu,xx); printf("nnn"); system("pause"); printf("nnn"); break; case 12: Save(stu,end); printf("nnn"); system("pause"); printf("nnn"); break; case 13: printf("即将退出程序!n"); exit(0); default:printf("请在0-12之间选择nnn"); } } void Input(STU *p,int n){ FILE *fp; if((fp=fopen("studentInit.dat","wb"))==NULL){ //打开文件 wb是写入二进制文件 给他一个权限 printf("cannot open filen"); exit(0); } for(int i=0;i printf("请输入十位学生的学号、姓名、专业、班级以及学生的三门课成绩:n"); scanf("%s %s %s %d",stu[i].num,stu[i].name,stu[i].major,&stu[i].classNo); for(int j=0;j<=2;j++){ scanf("%d",&stu[i].score[j]); stu[i].sum+=stu[i].score[j]; } stu[i].aver=stu[i].sum*1.0/3; if((fwrite(&stu[i],sizeof(STU),1,fp))!=1){ printf("file write errorn"); } } fclose(fp); printf("nnn十位同学的信息已经输入成功!!!nnnn"); system("pause"); printf("nnn"); } void Read(){ FILE *fp; if((fp=fopen("studentInit.dat","rb"))==NULL) { printf("cannot open filen"); exit(0); } for(int i=0;i fread(&stu[i],sizeof(STU),1,fp); } printf("nnn文件读取成功nnnnn"); fclose(fp); } void Output(STU *p){ printf("* %s * %s * %st * %d * %d * %d * %d * %.2lf * %dnn",(*p).num,(*p).name,(*p).major,(*p).classNo,(*p).score[0],(*p).score[1],(*p).score[2],(*p).aver,(*p).sum); } STU Fetch(int studentIndex){ FILE *fp; if((fp=fopen("studentInit.dat","rb"))==NULL){ printf("can not open filen"); exit(0); } printf("第%d个学生的基本信息与成绩:n",studentIndex); fseek(fp,studentIndex*sizeof(STU),0); //移动文件位置标记,从头开始 fread(&stu[studentIndex],sizeof(STU),1,fp); //读一个数据块到数据块里 printf("%s %s %s %d %d %d %d",stu[studentIndex].num,stu[studentIndex].name,stu[studentIndex].major,stu[studentIndex].classNo,stu[studentIndex].score[0],stu[studentIndex].score[1],stu[studentIndex].score[2]); } void Search(STU *p, int classNo,int scoreSum){ printf("%d班里总分大于%d分的学生有:n",classNo,scoreSum); for(int i=0;i if((*p).classNo==classNo){ int sum=0; for(int j=0;j<=2;j++) sum+=(*p).score[j]; if(sum>=scoreSum){ printf("%st其总分为:%dn",(*p).name,sum); } } } } int Max(STU *p, int scoreIndex){ memset(mp,0,sizeof(mp)); int maxx=0; int j=0; for(int i=0;i if((*p).score[scoreIndex]>=maxx) { maxx=(*p).score[scoreIndex]; } } for(int i=0;i if(stu[i].score[scoreIndex]==maxx){ mp[j++]=i; } } return j; } void Sort_select(STU *p){ for(int i=0;i int k=i; for(int j=i+1;j if((*(p+k)).aver>(*(p+j)).aver){ STU s=(*(p+k)); (*(p+k))=(*(p+j)); (*(p+j))=s; } } } printf("所有学生的平均成绩从低到高选择排序后的结果:n"); for(int i=0;i printf("%st%.2lftn",stu[i].name,stu[i].aver); } } void Sort_select_reverse(STU *p){ for(int i=0;i int k=i; for(int j=i+1;j if((*(p+k)).aver<(*(p+j)).aver){ STU s=(*(p+k)); (*(p+k))=(*(p+j)); (*(p+j))=s; } } } printf("所有学生的平均成绩从高到低选择排序后的结果:n"); for(int i=0;i printf("%st%.2lftn",stu[i].name,stu[i].aver); } } void Sort_buble(STU *p, int n){ printf("%d班里总成绩通过冒泡排序由高到低的学生成绩为:n",n); printf("**********************************************************************************************************n"); printf("* 学号 * 姓名 * 专业t * 班级 * 语文 * 数学 * 英语 * 平均分 * 总分n"); STU stu_class_ave[N+10]; for(int i=0;i for(int j=0;j if(stu[j].aver STU s=stu[j]; stu[j]=stu[j+1]; stu[j+1]=s; } } } int count=0; for(int i=0;i if(stu[i].classNo==n) stu_class_ave[count++]=stu[i]; } for(int i=0;i Output(&stu_class_ave[i]); } printf("**********************************************************************************************************n"); } void Sort_buble_reverse(STU *p, int n){ printf("%d班里总成绩通过冒泡排序由低到高的学生成绩为:n",n); printf("**********************************************************************************************************n"); printf("* 学号 * 姓名 * 专业t * 班级 * 语文 * 数学 * 英语 * 平均分 * 总分n"); STU stu_class_ave[N+10]; for(int i=0;i for(int j=0;j if(stu[j].aver>stu[j+1].aver){ STU s=stu[j]; stu[j]=stu[j+1]; stu[j+1]=s; } } } int count=0; for(int i=0;i if(stu[i].classNo==n) stu_class_ave[count++]=stu[i]; } for(int i=0;i Output(&stu_class_ave[i]); } printf("**********************************************************************************************************n"); } void Sort_insert(STU *p, int n, char *major){ printf("插入排序后%s专业的该课程成绩由低到高为:n",major); printf("**********************************************************************************************************n"); printf("* 学号 * 姓名 * 专业t * 班级 * 语文 * 数学 * 英语 * 平均分 * 总分n"); STU stu_class_subject [N+10]; STU cmp; int temp,j; for(int i=1;i cmp=stu[i]; temp=stu[i].score[n]; for(j=i-1;stu[j].score[n]>temp,j>=0;j--){ stu[j+1]=stu[j]; } stu[j+1]=cmp; } int count=0; for(int i=0;i if(!strcmp((*p).major,major)) stu_class_subject[count++]=*p; } for(int i=0;i Output(&stu_class_subject[i]); } printf("**********************************************************************************************************n"); } void Sort_insert_reverse(STU *p, int n, char *major){ printf("插入排序后%s专业的该课程成绩由高到低为:n",major); printf("**********************************************************************************************************n"); printf("* 学号 * 姓名 * 专业t * 班级 * 语文 * 数学 * 英语 * 平均分 * 总分n"); STU stu_class_subject [N+10]; STU cmp; int temp,j; for(int i=1;i cmp=stu[i]; temp=stu[i].score[n]; for(j=i-1;stu[j].score[n] =0;j--){ stu[j+1]=stu[j]; } stu[j+1]=cmp; } int count=0; for(int i=0;i if(!strcmp((*p).major,major)) stu_class_subject[count++]=*p; } for(int i=0;i Output(&stu_class_subject[i]); } printf("**********************************************************************************************************n"); } void Add(STU *p,int n) { STU *pp=p; //将曾删过的学生总分与平均分归零 for(int i=0;i (*pp).sum=0; (*pp).aver=0; } for(int i=0;i printf("请输入学生的学号、姓名、专业、班级:n"); scanf("%s%s%s%d",(*p).num,(*p).name,(*p).major,&((*p).classNo)); printf("请输入该学生的三门成绩,语文、数学、英语:n"); for(int j=0;j<=2;j++){ scanf("%d",&((*p).score[j])); (*p).sum+=(*p).score[j]; } (*p).aver=(*p).sum*(1.0)/3; } end+=n; printf("学生信息添加成功!!!nn"); } void Revise(STU *p){ printf("nn请输入需要修改的学生学号:n"); char numm[20]; int flag; bool pd; scanf("%s",numm); for(int i=0;i if(!strcmp((*p).num,numm)){ pd=true; flag=i; printf("* 学号 * 姓名 * 专业t * 班级 * 语文 * 数学 * 英语 *n"); printf("* %s * %s * %st * %d * %d * %d * %d *n",(*p).num,(*p).name,(*p).major,(*p).classNo,(*p).score[0],(*p).score[1],(*p).score[2]); break; } else{ pd=false; } } if(pd){ printf("n请输入需要修改的信息n"); printf("t1.修改名字t2.修改专业t3.修改班级t4.修改语文t5.修改数学t6.修改英语nn"); int m; scanf("%d",&m); switch(m){ case 1: char newname[15]; printf("请输入新名字:n"); scanf("%s",newname); strcpy(stu[flag].name,newname); break; case 2: char newmajor[20]; printf("请输入新专业:n"); scanf("%s",newmajor); strcpy(stu[flag].major,newmajor); break; case 3: int newclass; printf("请输入新班级:n"); scanf("%d",&newclass); stu[flag].classNo=newclass; break; case 4: int grade1; printf("请输入新的语文成绩:n"); scanf("%d",&grade1); stu[flag].score[0]=grade1; break; case 5: int grade2; printf("请输入新的数学成绩:n"); scanf("%d",&grade2); stu[flag].score[1]=grade2; break; case 6: int grade3; printf("请输入新的英语成绩:n"); scanf("%d",&grade3); stu[flag].score[2]=grade3; break; } printf("nn该学生信息修改成功!!!"); } else{ printf("该学生不存在!n"); } } void Delete(STU *p,int n){ printf("请输入需要删除信息的%d个学生学号:n",n); int bp=0; char str[20][20]; for(int i=1;i<=n;i++){ scanf("%s",str[i]); } for(int i=1;i<=n;i++){ //遍历每一个需要删除信息的学生学号 int flag=0; for(int j=0;j if(!strcmp(stu[j].num,str[i])){ flag=1; bp=1; for(int k=j;k stu[k]=stu[k+1]; } end-=1; break; } } if(!flag) printf("学号为%s的学生信息因为不存在而无法删除!n",str[i]); } if(bp) printf("学生信息删除成功!!!nnn"); } void Save(STU *p,int n){ FILE *fp; if((fp=fopen("studentInit.dat","wb"))==NULL){ //打开文件 wb是写入二进制文件 给他一个权限 printf("cannot open filen"); exit(0); } for(int i=0;i if((fwrite(&stu[i],sizeof(STU),1,fp))!=1){ printf("file write errorn"); } } fclose(fp); printf("所有学生信息已经成功保存到文件里面!!!nn"); }
五、实验总结与分析(所设计系统的特色之处,实验过程中遇到的具体问题及解决方法)
1.特色:该程序在原有的十大函数九大功能基础上增添了八大函数四大新功能。分别是通过函数void Read();void Revise(STU *p);void Delete(STU *p,int n);void Add(STU *p,int n)实现了从文件中读取信息到结构体中,修改学生信息,删除学生信息,添加学生信息四大新功能。
对于新功能一:可以随时读取文件中的二进制信息到结构体中,利于用户保存或者修改信息到文件里以后的读档;
对于新功能二:利用学生学号的唯一性匹配学生学号,从而可以选择对学生的姓名、专业、班级、三门成绩进行修改。
对于新功能三:利用学生学号的唯一性匹配学生学号,从而在结构体在删除该学生信息,当然也可以一次性删除多个学生信息,利用的方法是覆盖法,即将要删除的学生后面的学生信息赋值给前面的学生从而将其覆盖掉。
对于新功能四:可以一次性添加多个学生信息到结构体中,增加了学生管理系统的合理性和灵活性。
当然,还扩展了排序的这个必须功能,可以使学生信息按照学号、姓名、专业的字典序或者班级、成绩的大小分别选择进行升序排序还是降序排序。
2.问题与解决方法
问题一:在文件里输入学生信息以后,每次调用函数对学生信息进行修改、查询、删除和增添时都需要先从文件里读取所有的二进制信息到结构体中,才能借助结构体来对学生的信息进行更改。
解决方法:定义了Read()函数,随时随地可以将文件里的学生信息读取到结构体中,从而只需要在文件里的信息有变更时读取一次就好。
问题二:用Fetch()函数从文件中随机读取某个学生信息时,因为文件里的信息是二进制数据,要想查询某个学生信息时需要找到它的结构体指针在文件里的位置。
解决方法:通过fseek()函数从文件的开头开始读取,跳到你需要查询的学生信息的数据,通过fread()读取这块信息到结构体中。
问题三:用函数Max()查询某课程最高分的学生序号时,由于返回值类型是int型,如果某课程最高分的学生有多个时,只能返回一个学生序号。
解决方法:定义一个int型变量j,用来记录第一个课程最高分的学生序号,并且将j作为该函数的返回值。若有其他学生也是该课程最高分,则直接在Max()函数里通过Output()函数输出该学生序号。
问题四:调用Save()函数保存结构体信息到文件里时,由于fwrite()写入信息会覆盖之前写入的信息,而不是添加,导致文件里的信息在每次调用函数Save()后都是崭新的,而不是在原来的文件上保存。
解决方法:为了解决这个方法,我选择了一个比较笨重的方法,就是每次调用Save()函数时,都将结构体里的所有学生信息重新写到文件里,而不是只将更改过的或者增减过的学生信息写到文件里。
问题五:调用Detele()函数删除学生信息时,如果删除了某个学生的信息,不知道如何将他的信息从结构体内存里清除,因为结构体不能像字符一样赋值为’ ’,也不能像指针一样赋值为NULL.
解决方法:从要删除信息的学生序号后一个开始,一直到结构体的最后一个学生,将他们的信息依次赋值给前一个学生,从而覆盖掉要删除的学生信息,使其信息在结构体里被删除。



