学生成绩

来源:互联网 发布:u盘安装mac os 编辑:程序博客网 时间:2024/04/26 18:49
#define N 3//学生人数 #define M 3//科目数//交替读写在没处读写操作位置原地踏步 Marktime检查 #define S 4 //分数段数 //当学生信息(分数覆盖,人数变动)重新计算并写入文件 #define MarkTime fseek(fp,0L,SEEK_CUR);#include<stdlib.h>#include<stdio.h>typedef struct data_block_of_a_student_scores{long id;char name[20];int score[M];int sum_score;int aver_score;int place;}STUDENT;typedef struct data_block_of_all_students_statistics{char section[10];int score[M];int sum_score;int aver_score;int place;}STATISTICS; int user_choice(void);void main_menu_user_choice(int *chioce);void batch_input(FILE *fp);void single_input(FILE *fp);void find_a_STUDENT(FILE *fp);void lookup_then_delete_a_STUDENT(FILE *fp);long whether_id_exist(long id,FILE *fp);void delet_a_STUDENT(FILE *fp,long delet_pos);void print_all_student(FILE *fp);void compute_all_student_place(FILE *fp);/*void compute_all_student_place(FILE *fp){//该函数还未添加Marktime long now_pos=ftell(fp);fseek(fp,0L,SEEK_END);long end_pos=ftell(fp); long sum_stud=end_pos/sizeof(STUDENT);//经过思考这是正确的,传进的fp在文件尾部,他的fetll值是结构体大小的整数倍; STUDENT *p,*q,*m;m=(STUDENT *)malloc((unsigned)(end_pos));rewind(fp);fread(p,end_pos,1,fp);q=p=(STUDENT *)(&m->sum_score);for(;p-q<sum_stud;p++){MarkTime//数:p【0】 p【i】 p【sum_stud】指向数的指针p,p+i p+sum_stud fread(&a_stud,(long)(sizeof(STUDENT)),1,fp);if(a_stud.id==id){whether=1;fseek(fp,-(long)(sizeof(STUDENT)),SEEK_CUR);break;}}free(m); fseek(fp,+now_pos,SEEK_SET);return;}*//*计算学生排名的已有的两种方法:1.将文件所有数据块读入本函数malloc来的一片区域,然后对这篇区域使用(struct*)格式划分,他们就成了结构体数组的一个个元素,对结构体数组进行选择排序,(结构体之间可以直接赋值) 对排序好的结构体数组元素 用循环体对他们的place成员 一次赋值1,2,3,4,5,6然后关闭文件,再用wb+打开,将数据块写入文件 这样文件中的学生信息,就是按place排序的了2.【此方法节省空间】 malloc一片区域,大小=学生人数*(总分,整形数字i(作为排名编号))(总分是浮点数的话,完全读写,是可以用此结果搜索彼结果的我猜【二进制编码相同,所以目前这样猜】), 这片区域当做结构体数组处理,对结构体数组的每个成员按照 总分选择排序,对排序结果,用循环体一次对他们的i成员 赋值1 2 3 4 5。。。然后用总分去文件中查找【需要编写用总分搜索的函数,【按照二进制编码是否相同绝对可以搜索到,但是可以这样底层的方式实现吗,如果直接对数据块读取的浮点数进行比较可以实现吗】,优点:软件运行负载小】,找到合适的对象,对他的place赋i的值3. 将文件所有数据块读入本函数malloc来的一片区域,然后对这篇区域使用(struct*)格式划分,他们就成了结构体数组的一个个元素,对结构体数组进行选择排序,(结构体之间可以直接赋值) 对排序好的结构体数组元素 用循环体对他们的place成员 依次赋值1,2,3,4,5,6使用malloc区域内地数据的id 调用whether exist函数 搜索文件,对找到的对象的place值赋malloc区域内的结构体的place值 。【【【【【注意:方法2,3两个对文件中的place进行赋值的时候可以使用循环体标志i的来做操作 (i=1;i<=sum_sutd;i++) */void print_all_student(FILE *fp){STUDENT a_stud;rewind(fp);printf("id\tname\tenglish\tclanguage\tmath\tsum\taver\tplace\n");fgetc(fp); while(!feof(fp)){fseek(fp,-1L,SEEK_CUR); MarkTimefread(&a_stud,sizeof(STUDENT),1,fp);printf("%ld\t",a_stud.id);printf("%s\t",a_stud.name);printf("%d\t",a_stud.score[0]);printf("%d\t\t",a_stud.score[1]);printf("%d\t",a_stud.score[2]);printf("%d\t",a_stud.sum_score);printf("%d\t",a_stud.aver_score);printf("%d\n",a_stud.place);fgetc(fp);}return;}int user_choice(void){//y:返回值为1 n:返回值为0   注意:使用该函数会让用户进行输入操作 fflush(stdin);char whether=getchar();fflush(stdin); while(whether!='y'&&whether!='n'){printf("输入无效,请重试!(y/n)\n");whether=getchar();fflush(stdin);}if(whether=='y'){whether=1;}if(whether=='n'){whether=0;}return whether;}void main_menu_user_choice(int *chioce){//chioce指向输入的整数 fflush(stdin);scanf("%d",chioce);while(*chioce!=1&&*chioce!=2&&*chioce!=3&&*chioce!=4&&*chioce!=5&&*chioce!=6&&*chioce!=7){printf("输入无效,请重试!\n");fflush(stdin);scanf("%d",chioce);}return; } void batch_input(FILE *fp){//自文件尾部延长文件 int i,num;STUDENT a_stud;fseek(fp,0L,SEEK_END);printf("您要添加几个学生的数据:");fflush(stdin);scanf("%d",&num);for(i=0;i<num;i++){single_input(fp);}printf("批量添加学生数据成功!\n");return;}void single_input(FILE *fp){ //自文件尾部延长文件 int i,choice=-1;STUDENT a_stud;fseek(fp,0L,SEEK_END);printf("id:");fflush(stdin);scanf("%ld",&a_stud.id);while(whether_id_exist(a_stud.id,fp)!=-1L){printf("该id信息已经存在,您要重新输入id还是覆盖该id学生的信息?\n(y:重新输入id/n:覆盖该id学生的信息)\n");choice=user_choice();if(choice==1){printf("重新输入id:");fflush(stdin);scanf("%ld",&a_stud.id);}if(choice==0){printf("您选择覆盖该学生的信息。\n");fseek(fp,+whether_id_exist(a_stud.id,fp),SEEK_SET);}}printf("name:");fflush(stdin);scanf("%s",a_stud.name);printf("score of english:");fflush(stdin);scanf("%d",&a_stud.score[0]);printf("score of clanguage:");fflush(stdin);scanf("%d",&a_stud.score[1]);printf("score of math:");fflush(stdin);scanf("%d",&a_stud.score[2]);for(i=0,a_stud.sum_score=0;i<M;i++){a_stud.sum_score+=a_stud.score[i];}a_stud.aver_score=a_stud.sum_score/M;a_stud.place=0;MarkTimefwrite(&a_stud,sizeof(STUDENT),1,fp);if(choice==0){fseek(fp,0L,SEEK_END);}return;}//先写一个用id进行精确搜索的查找函数吧 用姓名查找的留出缺口 稍后实现 void find_a_STUDENT(FILE *fp){int i;long id,right_pos,now_pos=ftell(fp); STUDENT a_stud;printf("您想输入id,还是姓名?(y:使用id/n:使用姓名)\n");i=user_choice();if(i==1){//使用ID擦找 printf("输入id:");fflush(stdin);scanf("%ld",&id);if( ( right_pos=whether_id_exist(id,fp) ) ==-1L){printf("不存在该id的相关数据!\n");}else{printf("已找到相关数据:\n");fseek(fp,+right_pos,SEEK_SET);MarkTimefread(&a_stud,sizeof(STUDENT),1,fp);printf("id\tname\tenglish\tclanguage\tmath\tsum\taver\tplace\n");printf("%ld\t",a_stud.id);printf("%s\t",a_stud.name);printf("%d\t",a_stud.score[0]);printf("%d\t\t",a_stud.score[1]);printf("%d\t",a_stud.score[2]);printf("%d\t",a_stud.sum_score);printf("%d\t",a_stud.aver_score);printf("%d\n",a_stud.place); }}if(i==0){//使用姓名查找 } fseek(fp,+now_pos,SEEK_SET);return;} void lookup_then_delete_a_STUDENT(FILE *fp){//当使用此函数成功删除了某个STUDENT结构体后,文件位置指针会停留在文件尾部 int i;long id,right_pos,now_pos=ftell(fp); STUDENT a_stud;printf("为了找到您想删除的对象,您想输入id,还是姓名?(y:使用id/n:使用姓名)\n");i=user_choice();if(i==1){//使用ID擦找 printf("输入id:");fflush(stdin);scanf("%ld",&id);if( ( right_pos=whether_id_exist(id,fp) ) ==-1L){printf("不存在该id的相关数据!\n"); //稍后添加重新输入选项 }else{printf("已找到相关数据:\n");  fseek(fp,+right_pos,SEEK_SET);MarkTimefread(&a_stud,sizeof(STUDENT),1,fp);printf("id\tname\tenglish\tclanguage\tmath\tsum\taver\tplace\n");printf("%ld\t",a_stud.id);printf("%s\t",a_stud.name);printf("%d\t",a_stud.score[0]);printf("%d\t\t",a_stud.score[1]);printf("%d\t",a_stud.score[2]);printf("%d\t",a_stud.sum_score);printf("%d\t",a_stud.aver_score);printf("%d\n",a_stud.place);delet_a_STUDENT(fp,right_pos);printf("\n");printf("已为您删除该信息!\n");}}if(i==0){//使用姓名查找 } if( right_pos ==-1L ){fseek(fp,+now_pos,SEEK_SET); //如果没有进行有效的删除操作,那么将文件位置指针恢复到调用该函数前的地方 }else{fseek(fp,0L,SEEK_END);//如果进行了有效的删除操作那么文件指针留在原来的编号位置处已经不再有使用意义,这是我们将文件指针置于文件尾部 } return;} long whether_id_exist(long id,FILE *fp){//long *p_sum_stud //检查该学号是否存在,若存在返回文件中该学生数据块的位置 (包含0) 如果不存在返回-1 STUDENT a_stud; long now_pos=ftell(fp);long exist_pos,end_pos;fseek(fp,0L,SEEK_END);end_pos=ftell(fp);long sum_stud=end_pos/sizeof(STUDENT);//经过思考这是正确的,传进的fp在文件尾部,他的fetll值是结构体大小的整数倍; int i,whether=0;rewind(fp);for(i=0;i<sum_stud;i++){MarkTimefread(&a_stud,(long)(sizeof(STUDENT)),1,fp);if(a_stud.id==id){whether=1;fseek(fp,-(long)(sizeof(STUDENT)),SEEK_CUR);break;}}if(whether==1){exist_pos=ftell(fp);}else{exist_pos=-1L;} fseek(fp,+now_pos,SEEK_SET);return exist_pos;}void delet_a_STUDENT(FILE *fp,long delet_pos){//pos 是 需要删除的那一个数据块的地址 可以在函数外面用ftell得到 //函数产生的副作用:执行后位置指针在新文件的尾部 //FILE *p; //if( (p=fopen("tempfile","wb+"))==NULL ){//printf("Fail to new a tempfile!");//exit(1);//}STUDENT *p,*q,*m,*n;long end_pos;fseek(fp,0L,SEEK_END);end_pos=ftell(fp);m=p=(STUDENT *)malloc((unsigned)(delet_pos));rewind(fp);MarkTimefread(p,(unsigned)(delet_pos),1,fp);n=q=(STUDENT *)malloc( (unsigned)(end_pos-(delet_pos+sizeof(STUDENT))) );fseek(fp,+(delet_pos+sizeof(STUDENT)),SEEK_SET);MarkTimefread(q,(unsigned)(end_pos-(delet_pos+sizeof(STUDENT))),1,fp);fclose(fp);if( ( fp=fopen("ALL_STUDENT.dat","wb+") )==NULL ){printf("Error in %s",__func__);exit(1);}MarkTimefwrite(p,(unsigned)(delet_pos),1,fp);MarkTimefwrite(q,(unsigned)(end_pos-(delet_pos+sizeof(STUDENT))),1,fp);free(m);//如果m,n移动了,不在指向申请过来的那片区域的首地址,那么这样free成功了吗 ?怎样检验? (就像p q那样)free(n);return;} int main(){FILE *f_u,*f_a;STUDENT a_stud;STATISTICS a_stat;long size_ALL_STUDENT_dat;//long sum_stud;      //,*p_sum_stud=&sum_stud;int first_time_to_run_me=0;int whether_batch_input=99;int main_chioce;printf("\n\n");printf("     **************************************************\n");printf("                                                       \n");printf("                                                       \n");printf("                  欢迎进入学生成绩管理系统             \n");printf("                                                       \n");printf("                        Welcome!                       \n");printf("                                                       \n");printf("                                                       \n");printf("     **************************************************\n");printf("\n\n\n\n\n\n");system("pause");system("cls");fflush(stdin);if( ( f_u=fopen("ALL_STUDENT.dat","rb+") )==NULL ){//没有数据 则新建数据,系统认为这是第一次使用该成绩管理系统 if( ( f_u=fopen("ALL_STUDENT.dat","wb+") )==NULL ){printf("Can't open the file ALL_STUDENT.dat!");}first_time_to_run_me=1; }fseek(f_u,0L,SEEK_END);size_ALL_STUDENT_dat=ftell(f_u)-0L;rewind(f_u); if(first_time_to_run_me){printf("这是你第一次运行该系统!是否批量添加学生数据?(y/n)\n");whether_batch_input=user_choice();}else if(size_ALL_STUDENT_dat==0){printf("系统内暂无数据!是否批量添加学生数据?(y/n)\n");whether_batch_input=user_choice();}if(whether_batch_input==0){printf("您选择否,将带您进入主菜单。\n");}else if(whether_batch_input==1){//进入批量添加学生数据模式 printf("您已进入批量添加学生数据模式。\n");batch_input(f_u);  //自文件尾部延长文件 }while(1){printf("--------------------------------------------------\n");printf("系统主菜单:                                      \n");printf("             1:批量添加学生数据                  \n");printf("             2:添加一个学生数据                  \n");printf("             3:查找某个学生数据                  \n");printf("             4:删除某个学生数据                  \n");printf("             5:输出全部学生成绩                  \n");printf("             6:输出分数段统计结果                \n");printf("             7:退出管理系统                      \n");printf("--------------------------------------------------\n");main_menu_user_choice(&main_chioce);switch(main_chioce){case 1:batch_input(f_u);break;case 2:single_input(f_u);break;case 3:find_a_STUDENT(f_u); break;case 4:lookup_then_delete_a_STUDENT(f_u);break;case 5:print_all_student(f_u);break;case 6:break;case 7:printf("再见!\n");fclose(f_u);exit(0);}} return 0;} 


0 0