学生成绩管理系统
设计一个简单的学生成绩管理程序
基本要求:
(1)管理功能包括列表,求平均成绩、查找最高分。
(2)可以实现按平均成绩排序;
(3)求平均成绩可按个人或科目进行;
(4)查找可按最高个人平均分进行,或按指定科目的最高分进行;
(5)每个学生的信息包括:序号、学号、性别、成绩1、成绩2、成绩3、成绩4;
(6)基本功能为:建立文件、增加学生记录、新建学生信息文件、删除/修改学生记录
#include<stdio.h> #include<stdlib.h> #include<conio.h> #include<string.h> #define INITIAL_SIZE 100 //数组初始的大小 #define INCR_SIZE 50 //数组每次增加的大小 #define NUM_SUBJECT 4 //科目数 #define NULL 0 struct student_info { char number[15]; //学号 char name[20]; //姓名 char gender[4]; //性别 float score[NUM_SUBJECT]; //分别为该学生4门课的成绩 float sum; //总分 float average; //平均分 int index; //名次 }; typedef struct student_info StuInfo; extern int numStus; //记录的学生数 extern StuInfo *records; //记录学生信息的数组 extern char savedTag; //信息是否已保存的标志,0为已保存,1为未保存 extern int arraySize; //数组大小 extern char *subject[]; void handle_menu(void); int menu_select(void); void addRecord(void); void modifyRecord(void); void queryInfo(void); void removeRecord(void); void sortInfo(void); int saveRecords(void); int loadRecords(void); void newRecord(void); void quit(void); void showTable(void); int findRecord(char *target,int targetType,int form); int getIndex(float sum); void copyRecord(StuInfo *src,StuInfo *dest); void average(void); void search(void); void shuchu(void); void shaixuan(void); int numStus = 0; StuInfo *records = NULL; char savedTag = 0; int arraySize; char *subject[]={"语文","数学","英语","理综"}; void main() { printf("\n"); printf("\t*************************************\n"); printf("\t* 这是一个 *\n"); printf("\t* 学生成绩管理程序 *\n"); printf("\t* 可以对学生的成绩进行管理 *\n"); printf("\t* 欢迎使用本程序 *\n"); printf("\t*************************************\n"); printf("\n"); handle_menu(); } //菜单处理函数 void handle_menu(void) { for(;;) { switch(menu_select()) { case 1: saveRecords(); break; case 2: addRecord(); break; case 3: newRecord(); break; case 4: removeRecord(); break; case 5: modifyRecord(); break; case 6: average(); break; case 7: search(); break; case 8: sortInfo(); break; case 9: shuchu(); break; case 10: loadRecords(); break; case 11: shaixuan(); break; case 12: quit(); } } } //菜单选择函数 int menu_select() { char s[2]; int cn = 0; printf("\n"); printf("\t1 建立文件\n"); printf("\t2 增加学生记录\n"); printf("\t3 新建学生信息文件\n"); printf("\t4 删除学生记录\n"); printf("\t5 修改学生记录\n"); printf("\t6 求平均成绩\n"); printf("\t7 查找最高分\n"); printf("\t8 按总分排序\n"); printf("\t9 输出所有记录\n"); printf("\t10 读取文件\n"); printf("\t11 按平均成绩筛选\n"); printf("\t12 退出程序"); printf("\n\t 数字对应相应功能,请选择1--12:"); for(;;) { gets(s); cn = atoi(s); //处理键入的非数字键 if(cn<1||cn>12) { printf("\n\t输入错误,请重新输入!\n"); printf("\t0--12:"); } else break; } return cn; } //建立文件函数 int saveRecords() { FILE *fp; char fname[30]; printf("\t您选择的是:建立文件\n"); if(numStus == 0) { printf("没有记录可存!\n"); return -1; } printf("请输入你要存入的文件名(直接回车选择文件stu_info):"); gets(fname); if(strlen(fname) == 0) strcpy(fname,"stu_info"); if((fp = fopen(fname,"wb")) == NULL) { printf("不能存入文件!\n"); return -1; } printf("\n存文件......\n"); fwrite(records,sizeof(StuInfo)*numStus,1,fp); fclose(fp); printf("%d条记录已经存入文件,请继续操作。\n",numStus); savedTag = 0; //更新是否已保存的标记 return 0; } //增加学生记录 void addRecord() { char str[10]; int j; float mark,sum; printf("\t增加学生记录\n"); if(numStus == 0) printf("原来没有记录,现在建立新表\n"); else printf("下面在当前的末尾增加新的信息\n"); while(1) { printf("您将要添加一组信息,确定吗?(Y/N):"); gets(str); if(str[0] == 'n'||str[0] == 'N') //不再添加信息 break; if(numStus>=arraySize) //数组空间不足,需要重新申请空间 { records = realloc(records,(arraySize+INCR_SIZE) *sizeof(StuInfo)); if(records == NULL) { printf("memory failed"); exit(-1); } arraySize = arraySize+INCR_SIZE; } printf("请输入学号:"); gets(records[numStus].number); printf("请输入姓名:"); gets(records[numStus].name); printf("请输入性别(0为女,输入其它为男):"); gets(str); if(str[0] == '0') strcpy(records[numStus].gender,"女"); else strcpy(records[numStus].gender,"男"); sum = 0; for(j=0;j<NUM_SUBJECT;j++) { printf("请输入%s成绩:",subject[j]); gets(str); mark = (float)atof(str); records[numStus].score[j] = mark; sum += mark; } records[numStus].sum = sum; records[numStus].average = sum/NUM_SUBJECT; records[numStus].index = getIndex(sum); numStus++; } printf("现在一共有%d条信息",numStus); savedTag = 1; } //新建学生信息文件 void newRecord(void) { char str[5]; printf("新建学生信息文件\n"); if(numStus != 0) { if(savedTag == 1) { printf("现在已经有记录,选择处理已有记录的方法。\n"); printf("是否保存原来的记录?(Y/N):"); gets(str); if(str[0]!='n'&&str[0]!='N') saveRecords(); } } numStus = 0; addRecord(); } //删除学生记录 void removeRecord() { char str[5]; char target[20]; int type; int i,j; int tmpi; printf("删除学生记录\n"); if(numStus == 0) { printf("没有可供删除的记录!"); return; } while(1) { printf("\t1 按学号\n"); printf("\t2 按姓名\n"); printf("\t3 按名次\n"); printf("\t数字对应删除方式!\n"); printf("请输入如何找到欲删除的记录的方式(直接输入回车结束移除操作):"); gets(str); if(strlen(str) == 0) break; if(str[0] == '1') { printf("请输入该学生的学号:"); gets(target); type = 0; } else if (str[0] == '2') { printf("请输入该学生的姓名"); gets(target); type = 1; } else { printf("请输入该学生的名次:"); gets(target); type = 2; } i = findRecord(target,type,0); if(i == -1) printf("没有符合条件的学生!\n"); while(i != -1) { showTable(); printf("%s\t%s\t%s",records[i].number,records[i].name,records[i].gender); for(j=0;j<NUM_SUBJECT;j++) { printf("\t%.1f",records[i].score[j]); } printf("\t%.1f\t%.1f\t%d\n",records[i].sum,records[i].average,records[i].index); printf("确定要删除这个学生的信息吗?(Y/N):"); gets(str); if(str[0] == 'Y'||str[0] == 'y') { numStus--; tmpi = records[i].index; //将后面的记录前移 for(j=1;j<numStus;j++) copyRecord(&records[j+1],&records[j]); //将名次排在被删除记录后面的记录的名次减1 for(j=0;j<numStus;j++) { if(records[j].index > tmpi) records[j].index--; } } //取下一个符合条件的记录 i = findRecord(target,type,i+1); } } savedTag = 1; } //修改学生记录 void modifyRecord() { char str[5]; char target[20]; int type; int i,j; int tmpi; float sum,mark; int count = 0; //总分大于sum的人数 printf("修改学生记录\n"); if(numStus == 0) { printf("没有可供修改的记录!"); return; } while(1) { printf("\t1 按学号\n"); printf("\t2 按姓名\n"); printf("\t3 按名次\n"); printf("\t数字对应修改方式!\n"); printf("请输入如何找到欲修改的记录的方式(直接输入回车结束修改操作):"); gets(str); if(strlen(str) == 0) break; if(str[0] == '1') { printf("请输入该学生的学号:"); gets(target); type = 0; } else if (str[0] == '2') { printf("请输入该学生的姓名"); gets(target); type = 1; } else { printf("请输入该学生的名次:"); gets(target); type = 2; } i = findRecord(target,type,0); if(i == -1) printf("没有符合条件的学生!\n"); while(i != -1) { showTable(); printf("%s\t%s\t%s",records[i].number,records[i].name,records[i].gender); for(j=0;j<NUM_SUBJECT;j++) { printf("\t%.1f",records[i].score[j]); } printf("\t%.1f\t%.1f\t%d\n",records[i].sum,records[i].average,records[i].index); printf("确定要修改这个学生的信息吗?(Y/N):"); gets(str); if(str[0] == 'Y'||str[0] == 'y') { tmpi = records[i].index; printf("下面请重新输入该学生的信息:\n"); printf("请输入学号:"); gets(records[numStus].number); printf("请输入姓名:"); gets(records[numStus].name); printf("请输入性别(0为女,输入其它为男):"); gets(str); if(str[0] == '0') strcpy(records[numStus].gender,"女"); else strcpy(records[numStus].gender,"男"); sum = 0; for (j=0;j<NUM_SUBJECT;j++) { printf("请输入%s成绩:",subject[j]); gets(str); mark = (float)atof(str); records[numStus].score[j] = mark; sum += mark; } records[numStus].sum = sum; records[numStus].average = sum/NUM_SUBJECT; //将原来名次排在被修改记录之后,而其小于等于 //修改后记录的sum的记录的名次减1 //将原来名次排在被修改记录之前或相同,而其 //大于修改后记录的sum的记录的名次增1 count = 0; for (j=0;j<numStus;j++ ) { if(j == i) continue; if(records[j].index>tmpi&&records[j].sum>sum) records[j].index--; else if (records[j].index<=tmpi&&records[j].sum<sum) records[j].index++; if (records[j].sum>sum) count++; } records[i].index = count+1; } i = findRecord(target,type,i+1); } } savedTag = 1; } //退出程序 void quit(void) { char str[5]; if (savedTag == 1) { printf("是否保存原来的记录(Y/N)"); gets(str); if (str[0] != 'n' && str[0] != 'N') saveRecords(); } free(records); exit(0); } //找出总分为sum在第0至numStus-1个记录中按升序排序的位置 int getIndex(float sum) { int i; int count = 0; //总分大于sum的人数 for (i=0; i<numStus ;i++ ) { if(records[i].sum<sum) { records[i].index++; //总分小于sum的记录名次加1 } else if (records[i].sum > sum) { count++; } } return count+1; } //查找指明定的记录 int findRecord(char *target,int targetType,int from) { int i; for (i=from;i<numStus ;i++ ) { if ((targetType==0 && strcmp(target,records[i].number)==0)|| (targetType==1 && strcmp(target,records[i].name)==0)|| (targetType==2 && atoi(target)==records[i].index)) return i; } return -1; } //打印表头 void showTable(void) { int j; printf("学号\t姓名\t性别"); for (j=0; j<NUM_SUBJECT ;j++ ) printf("\t%s",subject[j]); printf("\t总分\t平均分\t序号\n"); } //将scr指向的一条记录复制给dest指明向的记录 void copyRecord(StuInfo *src,StuInfo *dest) { int j; strcpy(dest->number,src->number); strcpy(dest->name,src->name); strcpy(dest->gender,src->gender); for (j=0; j<NUM_SUBJECT ;j++ ) { dest->score[j]=src->score[j]; } dest->sum = src->sum; dest->average = src->average; dest->index = src->index; } //求平均成绩函数 void average() { int i,kemu; float sum; char str[5]; float average; printf("\t1 语文\n"); printf("\t2 数学\n"); printf("\t3 英语\n"); printf("\t4 理综\n"); printf("请输入您要计算平均成绩的科目(数字代表相应科目):"); gets(str); if(strlen(str) == 0) exit (0); for ( ; ; ) { kemu = atoi(str); if(kemu<1||kemu>4) { printf("您的输入有误,请重新输入,1--4:"); gets(str); if(strlen(str) == 0) exit(0); } else { for(i=0;i<numStus;i++) { sum = sum + records[i].score[kemu-1]; } average = sum/numStus; break; } } printf("平均分为%.1f",average); } //查找最高分函数 void search() { int i,j=0,kemu,tag=0,ind[20]; int k; char str[5]; float max; printf("\t1 语文\n"); printf("\t2 数学\n"); printf("\t3 英语\n"); printf("\t4 理综\n"); printf("\t5 总分\n"); printf("请输入你要查找的最高分的选项(数字代表相应选项,直接回车退出),1--5:"); for ( ; ; ) { gets(str); if(strlen(str) == 0) exit (0); kemu = atoi(str); if(kemu<1||kemu>5) printf("您的输入有误,请重新输入,1--5:"); else break; } if(kemu>=1&&kemu<=4) { max = 0; for ( i=0 ; i< numStus ;i++ ) { if(max < records[i].score[kemu-1]) { max = records[i].score[kemu-1]; } } for ( i=0; i<numStus ;i++ ) { if( (kemu==1 && max == records[i].score[0])|| (kemu==2 && max == records[i].score[1])|| (kemu==3 && max == records[i].score[2])|| (kemu==4 && max == records[i].score[3]) ) { for( ;j<20;j++) { ind[j] = i; tag++; break; } } } showTable(); for(j=0;j<tag;j++) { printf("%s\t%s\t%s",records[ind[j]].number,records[ind[j]].name,records[ind[j]].gender); for(k=0;k<NUM_SUBJECT;k++) { printf("\t%.1f",records[ind[j]].score[k]); } printf("\t%.1f\t%.1f\t%d\n",records[ind[j]].sum,records[ind[j]].average,records[ind[j]].index); } printf("\t这就是您要查找的信息\n"); } else { max = 0; for (i=0;i<numStus;i++) { if(max<records[i].sum) max = records[i].sum; } for(i=0;i<numStus;i++) { if(records[i].sum == max) for( ;j<20;j++) { ind[j] = i; tag++; break; } } showTable(); for(j=0;j<tag;j++) { printf("%s\t%s\t%s",records[ind[j]].number,records[ind[j]].name,records[ind[j]].gender); for(k=0;k<NUM_SUBJECT;k++) { printf("\t%.1f",records[ind[j]].score[k]); } printf("\t%.1f\t%.1f\t%d\n",records[ind[j]].sum,records[ind[j]].average,records[ind[j]].index); } printf("\t这就是您要查找的信息\n"); } return; } //按总分降序函数 void sortInfo(void) { int i,j; StuInfo tmps; if(numStus == 0) { printf("没有可供查询的记录!"); return; } for(i=0;i<numStus;i++) { for(j=0;j<numStus-i;j++) { if( records[j].sum<records[j+1].sum) { copyRecord(&records[j],&tmps); copyRecord(&records[j+1],&records[j]); copyRecord(&tmps,&records[j+1]); } } } printf("排序已完成!\n"); shuchu(); savedTag = 1; } //输出所有记录 void shuchu(void) { int i,j; showTable(); for(i=0;i<numStus;i++) { printf("%s\t%s\t%s",records[i].number,records[i].name,records[i].gender); for(j=0;j<NUM_SUBJECT;j++) { printf("\t%.1f",records[i].score[j]); } printf("\t%.1f\t%.1f\t%d\n",records[i].sum,records[i].average,records[i].index); } } //文件读取操作函数 int loadRecords() { FILE *fp; char fname[30]; char str[5]; if(numStus!=0 && savedTag == 0) { printf("\t请选择您是要覆盖现有记录(Y),还是要将\n"); printf("\t读取的记录添加到现有的记录之后(N)\n"); printf("\t直接回车则覆盖现有的记录:"); gets(str); if(str[0]=='n'||str[0]=='N') { savedTag = 1; } else { if(savedTag == 1) { //覆盖现有记录 printf("\t读取文件会更改原来的记录\n"); printf("是否保存原来的记录(Y/N):"); gets(str); if(str[0]!='n'||str[0]!='N') saveRecords(); } numStus = 0; } } printf("请输入要读取的文件名(直接回车选择文件stu_info)"); gets(fname); if(strlen(fname)==0) strcpy(fname,"stu_info"); if((fp=fopen(fname,"rb"))==NULL) { printf("打不开文件!请重新选择\n"); return -1; } printf("\t读文件\n"); while(!feof(fp)) { //现在的空间不足,需要重新申请空间 if(numStus >= arraySize) { records = realloc(records,(arraySize+INCR_SIZE) *sizeof(StuInfo)); if(records == NULL) { printf("memory failed!"); exit(-1); } arraySize = arraySize+INCR_SIZE; } if(fread(&records[numStus],sizeof(StuInfo),1,fp) !=1) break; //按照addRecord函数的方法,更新名次 records[numStus].index = getIndex(records[numStus].sum); numStus++; } fclose(fp); printf("现在共有%d条记录。",numStus); return 0; } //平均分筛选 void shaixuan(void) { float average; int i=0,numstus=0,j; printf("本程序给出大于等于已知平均成绩的学生的信息\n"); printf("请输入你要筛选的下限平均分:"); scanf("%f",&average); showTable(); for (i=0 ;i< numStus;i++ ) { if(records[i].average>=average) { printf("%s\t%s\t%s",records[i].number,records[i].name,records[i].gender); for(j=0;j<NUM_SUBJECT;j++) { printf("\t%.1f",records[i].score[j]); } printf("\t%.1f\t%.1f\t%d\n",records[i].sum,records[i].average,records[i].index); numstus++; } } printf("共有%d条记录",numstus); }