计算机实习报告

姓名:王方正

学号:20174314

一、开发任务

题目源自《程序设计实践教程》教材22题,学生基本信息管理。描述略。

二、需求分析

1.说明自己针对这个任务将完成哪些功能的设计。

学生基本信息管理任务的基本功能是:

(1)从文件中读取学生记录

(2)新增学生记录

(3)编辑学生记录各个字段

(4)删除指定学生记录

(5)按指定字段查询并显示学生详细信息

(6)按指定功能统计并显示

2.说明程序将会具有什么样的性能:

程序中有如下性能:

(1)提供精美菜单供用户选择对应功能

(2)提供详细输入提示帮助用户正确输入信息

(3)提供强力的边界保护防止非法数据影响数据库学生记录的存储使用

(4)提供身份码验证,管理员与普通用户两套身份码,管理员具有对记录增、删、改、查的权限,普通用户只具有查的权限,无身份码用户无法实用程序,身份码有试错次数限制,超出试错次数限制直接关闭程序

(5)提供即时回退机制,在任意界面,按照输入提示输入制定内容均可回退至上级菜单

(6)提供数据回显,在修改学生数据时,即时回显修改后的学生记录,便于用户进一步操作,提供良好的交互体验

(7)提供良好的统计展示,统计量为0的不必要值不会展示,优化用户查阅统计结果的体验

三、程序设计

针对需求做如下设计:

1. 数据结构设计

假设学生记录的数据结构是:学号(主键)、姓名、专业、生源地、民族、性别、政治面貌、家庭收入、学生入学4科成绩

  1. struct Student
  2. {
  3. int num;//学号
  4. char name[10];//姓名
  5. char major[20];//专业
  6. char origin[8];//生源地
  7. char ethnic[12];//民族
  8. char sex[3];//性别
  9. char politic[12];//政治面貌
  10. double income;//家庭收入
  11. double score[4];//学生成绩,score[0]~score[3]分别对应语文成绩、数学成绩、英语成绩、综合成绩
  12. };

2. 模块设计

本系统主要提供从文件中读取学生记录、新增学生记录、编辑学生记录各个字段、删除指定学生记录、按指定字段查询并显示学生详细信息、按指定功能统计并显示的功能,下面按模块说明其实现:

从文件中读取学生记录:通过Initialize_Student()获得外存文件路径,通过Load_Student()将外存文件中学生记录读入内存结构体中。

新增学生记录:通过New_Student()调用Get系函数,获得输入学生记录的各个字段并进行边界判定,将合法的学生记录信息存取内存结构体中

编辑学生记录各个字段:通过Check_Name()按姓名查找学生记录,并展示所有同名学生记录详细信息,通过Check_Number()供用户选择同名学生记录中的制定学生记录,通过Show_Student()展示数据,并展示选择待修改的字段菜单,并在每次修改结束后通过Show_Student()再次展示数据,达到数据的回显。

删除指定学生记录:通过Delete_Student()将指定位置后的所有学生记录前移一个位置,覆盖待删除学生记录。

按指定字段查询并显示详细信息:通过Menu_Check()展示选择待查询字段的菜单,用户选择待查询字段,调用Check系函数,按指定字段查询,并显示符合合法输入的全部学生记录的详细信息。

按指定功能统计并显示的功能:通过Menu_Count()展示选择统计功能,用户选择统计功能,先按实现功能必须进行制定字段调用Sort系函数进行快速排序,然后调用Count系函数实现制定功能。

3. 主程序结构

本任务的主程序结构是登陆界面,用户输入身份码,验证正确则转入对应身份的主菜单中,用户在主菜单选择对应功能,转入相应的子程序中。

四、程序实现

(1)void Print_Welcome()

输  入:无

输  出:无

返回值:无

功  能:在控制台打印欢迎字符画。

  1. void Print_Welcome()
  2. {
  3. printf("\t\t\t\t _______ _ _______ _______ _______ _______ \n");
  4. printf("\t\t\t\t|\\ /|( ____ \\( \\ ( ____ \\( ___ )( )( ____ \\\n");
  5. printf("\t\t\t\t| ) ( || ( \\/| ( | ( \\/| ( ) || () () || ( \\/\n");
  6. printf("\t\t\t\t| | _ | || (__ | | | | | | | || || || || (__ \n");
  7. printf("\t\t\t\t| |( )| || __) | | | | | | | || |(_)| || __) \n");
  8. printf("\t\t\t\t| || || || ( | | | | | | | || | | || ( \n");
  9. printf("\t\t\t\t| () () || (____/\\| (____/\\| (____/\\| (___) || ) ( || (____/\\\n");
  10. printf("\t\t\t\t(_______)(_______/(_______/(_______/(_______)|/ \\|(_______/\n\n");
  11. }

(2)void Printf_End()

输  入:无

输  出:无

返回值:无

功  能:在控制台结束字符画的打印。

  1. void Print_End()//结束程序彩蛋
  2. {
  3. system("color fc");
  4. printf("\t\t\t\t _______ _______ _______ ______ ______ _______ \n");
  5. printf("\t\t\t\t( ____ \\( ___ )( ___ )( __ \\ ( ___ \\ |\\ /|( ____ \\\n");
  6. printf("\t\t\t\t| ( \\/| ( ) || ( ) || ( \\ )| ( ) )( \\ / )| ( \\/\n");
  7. printf("\t\t\t\t| | | | | || | | || | ) || (__/ / \\ (_) / | (__ \n");
  8. printf("\t\t\t\t| | ____ | | | || | | || | | || __ ( \\ / | __) \n");
  9. printf("\t\t\t\t| | \\_ )| | | || | | || | ) || ( \\ \\ ) ( | ( \n");
  10. printf("\t\t\t\t| (___) || (___) || (___) || (__/ )| )___) ) | | | (____/\\\n");
  11. printf("\t\t\t\t(_______)(_______)(_______)(______/ |/ \\___/ \\_/ (_______/\n");
  12. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  13. printf("\t\t\t\t│ 感谢使用!! │\n");
  14. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  15. }

(3)int Length_Student(Student data[])

输  入:保存所有学生记录的结构体data

输  出:无

返回值:结构体中学生记录的个数

功能:实现计算结构体中记录个数。保存所有学生记录的结构体data作为形参输入,若记录中的学号字段不为0,计数器自增。返回值为结构体中记录的个数。

  1. int Length_Student(Student data[])//结构体长度
  2. {
  3. int i;//循环用变量
  4. for(i=0;data[i].num!=0;i++);
  5. return i;
  6. }

(4)void Load_Student(Student data[],FILE *fp)

输  入:保存所有学生记录的结构体data,以只读方式打开文件的文件指针fp

输  出:无

返回值:无

功  能:实现从外存文件将所有学生记录读入内存结构体。保存所有学生记录的结构体data、以只读方式打开文件的文件指针fp作为形参输入,文件到达底部之前,循环将外存文件中的学生记录读入内存结构体中。

  1. void Load_Student(Student data[],FILE *fp)//从文件读取学生信息
  2. {
  3. for(int i=0;!feof(fp);i++)//在文件到底之前,将文件中所有记录依次读入
  4. {
  5. fscanf(fp,"%d",&data[i].num);
  6. fscanf(fp,"%s",data[i].name);
  7. fscanf(fp,"%s",data[i].major);
  8. fscanf(fp,"%s",data[i].origin);
  9. fscanf(fp,"%s",data[i].ethnic);
  10. fscanf(fp,"%s",data[i].sex);
  11. fscanf(fp,"%s",data[i].politic);
  12. fscanf(fp,"%lf",&data[i].income);
  13. fscanf(fp,"%lf",&data[i].score[0]);
  14. fscanf(fp,"%lf",&data[i].score[1]);
  15. fscanf(fp,"%lf",&data[i].score[2]);
  16. fscanf(fp,"%lf",&data[i].score[3]);
  17. }
  18. fclose(fp);//关闭文件
  19. }

(5)void Overwrite_Student(Student data[],FILE *fp)

输  入:保存所有学生记录的结构体data,以只写方式打开文件的文件指针fp

输  出:无

返回值:无

功  能:实现从内存结构体将所有学生记录写入外存文件。保存所有学生记录的结构体data、以只写方式打开文件的文件指针fp作为形参输入,调用Length_Student函数获得结构体中学生记录条数,循环将内存结构体中的学生记录写入外存文件中。

  1. void Overwrite_Student(Student data[],FILE *fp)//覆盖文件中的记录
  2. {
  3. for(int i=0;i<Length_Student(data);i++)//将内存结构体中的记录置入文件
  4. {
  5. fprintf(fp,"%d\t%s\t%s\t%s\t%s\t%s\t%s\t%.1lf\t%.1lf\t%.1lf\t%.1lf\t%.1lf\t\n",
  6. data[i].num,data[i].name,data[i].major,data[i].origin,data[i].ethnic,data[i].sex,data[i].politic,
  7. data[i].income,data[i].score[0],data[i].score[1],data[i].score[2],data[i].score[3]);
  8. }
  9. fclose(fp);
  10. }

(6)void Initialize_Student(Student data[])

输  入:保存所有学生记录的结构体data,外存文件路径address

输  出:无

返回值:无

功  能:实现内存结构体的初始化。保存所有学生记录的结构体data作为形参输入。输入外存文件路径address,若输入-1,退出程序。若文件打开成功,调用Load_Student将学生记录从外存文件读入内存结构体,将address储存在结构体中有学生记录的末尾的下一个位置,方便文件路径在函数间传递,同时不会影响正常学生记录的存储读取。

  1. void Initialize_Student(Student data[])//初始化结构体
  2. {
  3. system("cls");
  4. char address[20];//记录文件名的字符串
  5. FILE *fp=NULL;//文件指针置空
  6. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  7. printf("\t\t\t\t│ 选择文件路径 │\n");
  8. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  9. printf("\t\t\t\t请输入文件路径(完整路径,输入-1退出程序):");
  10. scanf("%s",address);
  11. if(strcmp(address,"-1")==0)//输入-1退出程序
  12. {
  13. system("cls");//清屏
  14. Print_End();//展示结束画面
  15. exit(0);//关闭程序
  16. }
  17. else if((fp=fopen(address, "a"))==NULL)//无法打开文件,递归重新输入文件名
  18. {
  19. printf("\n\t\t\t\t文件打开失败...\n\t\t\t\t");
  20. system("pause");
  21. Initialize_Student(data);//递归重新输入文件名
  22. return;
  23. }
  24. else//文件打开成功
  25. {
  26. printf("\n\t\t\t\t文件打开成功!");
  27. system("pause");
  28. fp=fopen(address, "r");
  29. Load_Student(data,fp);//从文件中读取记录到内存中的结构体
  30. strcpy(data[Length_Student(data)].major,address);//利用结构体的末尾存储空间存储文件名字符串
  31. }
  32. }

(7)void Get_Number(Student *data,Student stu[])

输  入:临时保存学生记录的结构体指针*data,保存所有学生记录的结构体stu,学生学号

输  出:无

返回值:无

功  能:实现获得输入学生学号及边界判断。临时保存学生记录的结构体指针*data,保存所有学生记录的结构体stu作为形参输入。声明整形变量tmp临时保存输入学生学号。使用fflush(stdin)清除缓冲区,输入学生学号。若学生学号为-1,将tmp临时保存的值传入data*对应结构体的学号字段。若学生学号不为-1,判断若学生学号对应年级超出合法范围,提示错误,递归获得学生学号。若学生学号对应年级符合合法范围,遍历stu,若输入学号与stu中学号重复,提示错误,递归获得学生学号。若学生学号不与stu中的任何一个学生记录的学生学号重复,将tmp临时保存的值传入*data对应的结构体的学号字段。通过一系列判断,最终将合法学生学号或-1传入*data对应的结构体的学号字段,实现了输入的边界判断。

  1. void Get_Number(Student *data,Student stu[])//获取学号的函数,前者为临时结构体,后者为已录入外存记录的结构体
  2. {
  3. printf("\t\t\t\t请输入学号(八位数字,输入-1返回上级菜单):");
  4. int tmp=-2;//临时变量,保存输入值,置为非法置,防止输入字符时错误跳转
  5. int length=Length_Student(stu);//计算结构体总长度
  6. fflush(stdin);//清空缓存区
  7. scanf("%d",&tmp);
  8. if(tmp!=-1)//输入-1,返回上级菜单
  9. {
  10. if(tmp/10000<1977||tmp/10000>2020)//超出学生年级范围
  11. {
  12. printf("\t\t\t\t学号输入错误!\n");
  13. Get_Number(data,stu);//递归
  14. return;//函数此处结束
  15. }
  16. for(int i=0;i<=length;i++)//在原学号库中查重
  17. {
  18. if(stu[i].num==tmp)//输入学号重复
  19. {
  20. printf("\t\t\t\t学号输入重复!\n");
  21. Get_Number(data,stu);//递归
  22. return;//函数此处结束
  23. }
  24. }
  25. }
  26. data->num=tmp;//最终将合法值或-1传入临时结构体
  27. return;
  28. }

(8)void Get_Name(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生姓名

输  出:无

返回值:无

功  能:实现获得输入学生姓名及边界判断。临时保存学生记录的结构体指针*data作为形参传入。声明字符串tmp临时保存输入学生姓名。输入学生姓名。若学生姓名为-1,将tmp临时保存的值传入*data对应结构体的姓名字段。若学生姓名不为-1,通过strlen获得输入学生姓名长度,按位比对tmp中每个位置的ASCII码值,若任意一个字符ACSII值的范围在1~127之外,即任意字符非英文、数字、标点符号,则学生姓名输入正确,将tmp临时保存的值*data对应的结构体的姓名字段。否则提示错误,递归获得学生姓名。通过一系列判断,最终将合法学生姓名或-1传入*data对应的结构体姓名字段,实现了输入的边界判断。

  1. void Get_Name(Student *data)
  2. {
  3. printf("\t\t\t\t请输入姓名(中文名,输入-1返回上级菜单):");
  4. char tmp[10];//临时变量,保存输入值
  5. scanf("%s",tmp);
  6. int length=strlen(tmp);//获取字符串长度
  7. if(strcmp(tmp,"-1")!=0)//输入-1,返回上级菜单
  8. {
  9. for(int i=0;i<=length;i++)
  10. {
  11. if(tmp[i]>=1&&tmp[i]<=127)//如果输入了非中文字符,判断为输入错误
  12. {
  13. printf("\t\t\t\t姓名输入错误!\n");
  14. Get_Name(data);
  15. return;
  16. }
  17. }
  18. }
  19. strcpy(data->name,tmp);//将合法值传入临时结构体
  20. return;
  21. }

(9)void Get_Major(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生专业

输  出:无

返回值:无

功  能:实现获得输入学生专业及边界判断。临时保存学生记录的结构体指针*data作为形参传入。声明整型变量flag指示专业,是否存在,初始值置0。声明字符串tmp临时保存输入学生专业。声明二维字符数组majorlist,储存所有合法学生专业。输入学生专业。若学生专业为-1,将tmp临时保存的值传入*data对应结构体的专业字段。若学生专业不为-1,顺序比对输入学生专业与majorlist中合法专业,若输入专业合法,flag置1,停止比对。若flag为1,将tmp临时保存的值传入*data对应的结构体的专业字段。若flag为0提示错误,递归获得学生专业。通过一系列判断,最终将合法学生专业或-1传入*data对应的结构体专业字段,实现了输入的边界判断。

  1. void Get_Major(Student *data)
  2. {
  3. printf("\t\t\t\t请输入专业\n\t\t\t\t(信息与计算科学/信息安全/计算机科学与技术/信息管理与信息系统/电子信息工程/通信工程/行政管理/保密管理,输入-1返回上级菜单):");
  4. int flag=0;//指示专业是否存在
  5. char tmp[20];//临时变量,保存输入值
  6. char majorlist[8][20]={"信息与计算科学","信息安全","计算机科学与技术","信息管理与信息系统","电子信息工程",
  7. "通信工程","行政管理","保密管理"};//比对专业信息的库
  8. scanf("%s",tmp);
  9. if(strcmp(tmp,"-1")!=0)//输入-1,返回上级菜单
  10. {
  11. for(int i=0;i<8;i++)
  12. if(strcmp(tmp,majorlist[i])==0)
  13. {
  14. flag=1;
  15. break;
  16. }
  17. if(flag==0)//没有找到库中的专业
  18. {
  19. printf("\t\t\t\t专业输入错误!\n");
  20. Get_Major(data);//递归
  21. return;
  22. }
  23. }
  24. strcpy(data->major,tmp);
  25. return;
  26. }

(10)void Get_Origin(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生生源地

输  出:无

返回值:无

功  能:实现获得输入学生生源地及边界判断。具体实现思路与Get_Major基本一致。

  1. void Get_Origin(Student *data)
  2. {
  3. printf("\t\t\t\t请输入生源地(省份名称,输入-1返回上级菜单):");
  4. int flag;
  5. char tmp[8];
  6. char originlist[34][8]={"北京","天津","上海","重庆","河北","山西","辽宁","吉林","黑龙江",
  7. "江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东","海南","四川","贵州",
  8. "云南","陕西","甘肃","青海","台湾","内蒙古","广西","西藏","宁夏","新疆","香港","澳门"};
  9. scanf("%s",tmp);
  10. if(strcmp(tmp,"-1")!=0)
  11. {
  12. for(int i=0;i<34;i++)
  13. if(strcmp(tmp,originlist[i])==0)
  14. {
  15. flag=1;
  16. break;
  17. }
  18. if(flag==0)//没有找到库中的省份
  19. {
  20. printf("\t\t\t\t生源地输入错误!\n");
  21. Get_Origin(data);//递归
  22. return;
  23. }
  24. }
  25. strcpy(data->origin,tmp);
  26. return;
  27. }

(11)void Get_Sex(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生性别

输  出:无

返回值:无

功  能:实现获得输入学生性别及边界判断。具体实现思路与Get_Major基本一致。

  1. void Get_Sex(Student *data)
  2. {
  3. printf("\t\t\t\t请输入性别(男/女,输入-1返回上级菜单):");
  4. char male[3]="男",female[3]="女",tmp[3];
  5. scanf("%s",tmp);
  6. if(strcmp(tmp,"-1")!=0)
  7. {
  8. if(strcmp(tmp,male)*strcmp(tmp,female)!=0)//如果输入的性别不是男或女中的任一个,输入错误
  9. {
  10. printf("\t\t\t\t性别输入错误!\n");
  11. Get_Sex(data);
  12. return;
  13. }
  14. }
  15. strcpy(data->sex,tmp);
  16. return;
  17. }

(12)void Get_Ethnic(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生民族

输  出:无

返回值:无

功  能:实现获得输入学生民族及边界判断。具体实现思路与Get_Major基本一致。

  1. void Get_Ethnic(Student *data)
  2. {
  3. printf("\t\t\t\t请输入民族(民族名称,输入-1返回上级菜单):");
  4. int flag=0;
  5. char tmp[12];
  6. char ethniclist[56][12]={"汉族","蒙古族","回族","藏族","维吾尔族","苗族","彝族","壮族",
  7. "布依族","朝鲜族","满族","侗族","瑶族","白族","土家族","哈尼族","哈萨克族","傣族","黎族",
  8. "僳僳族","佤族","畲族","高山族","拉祜族","水族","东乡族","纳西族","景颇族","柯尔克孜族",
  9. "土族","达斡尔族","仫佬族","羌族","布朗族","撒拉族","毛南族","仡佬族","锡伯族","阿昌族",
  10. "普米族","塔吉克族","怒族","乌孜别克族","俄罗斯族","鄂温克族","德昂族","保安族","裕固族",
  11. "京族","塔塔尔族","独龙族", "鄂伦春族","赫哲族","门巴族","珞巴族","基诺族"};
  12. scanf("%s",tmp);
  13. if(strcmp(tmp,"-1")!=0)
  14. {
  15. for(int i=0;i<57;i++)
  16. if(strcmp(tmp,ethniclist[i])==0){
  17. flag=1;
  18. break;
  19. }
  20. if(flag==0)
  21. {
  22. printf("\t\t\t\t民族输入错误!\n");
  23. Get_Ethnic(data);//递归
  24. return;
  25. }
  26. }
  27. strcpy(data->ethnic,tmp);
  28. return;
  29. }

(13)void Get_Politic(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生政治面貌

输  出:无

返回值:无

功  能:实现获得输入学生政治面貌及边界判断。具体实现思路与Get_Major基本一致。

  1. void Get_Politic(Student *data)
  2. {
  3. printf("\t\t\t\t请输入政治面貌\n\t\t\t\t(群众/无党派人士/共青团员/入党积极分子/中共预备党员/中共党员,输入-1返回上级菜单):");
  4. int flag=0;
  5. char tmp[20];
  6. char politiclist[6][20]={"群众","无党派人士","共青团员","入党积极分子","中共预备党员","中共党员"};
  7. scanf("%s",tmp);
  8. if(strcmp(tmp,"-1")!=0)
  9. {
  10. for(int i=0;i<8;i++)
  11. if(strcmp(tmp,politiclist[i])==0)
  12. {
  13. flag=1;
  14. break;
  15. }
  16. if(flag==0)
  17. {
  18. printf("\t\t\t\t政治面貌输入错误!\n");
  19. Get_Politic(data);//递归
  20. return;
  21. }
  22. }
  23. strcpy(data->politic,tmp);
  24. return;
  25. }

(14)void Get_Income(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生家庭收入

输  出:无

返回值:无

功  能:实现获得输入学生家庭收入及边界判断。临时保存学生记录的结构体指针*data作为形参传入。声明双精度浮点变量tmp临时保存输入学生家庭收入,初始置非法值,防止输入字符时将初始化的错误合法值传入,无法提示错误。使用fflush(stdin)清除缓冲区,输入学生家庭收入。若输入-1,将tmp临时保存的值传入*data对应结构体的家庭收入字段。若输入不为-1,判断tmp临时保存的学生家庭收入是否属于合法范围(0~99999),若输入合法,将tmp临时保存的值传入*data对应结构体的家庭收入字段。否则提示错误,递归获得学生家庭收入。通过一系列判断,最终将合法学生家庭收入或-1传入*data对应的结构体家庭收入字段,实现了输入的边界判断。

  1. void Get_Income(Student *data)
  2. {
  3. printf("\t\t\t\t请输入家庭收入(0~99999,输入-1返回上级菜单):");
  4. double tmp=-2;//初始值非法值,防止输入字符产生错误
  5. fflush(stdin);
  6. scanf("%lf",&tmp);
  7. if(tmp!=-1)
  8. {
  9. if(tmp<0||tmp>=100000)//输入的家庭收入超出范围
  10. {
  11. printf("\t\t\t\t家庭收入输入错误!\n");
  12. Get_Income(data);
  13. return;
  14. }
  15. }
  16. data->income=tmp;
  17. }

(15)void Get_Chinese(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生语文成绩。

输  出:无

返回值:无

功  能:实现获得输入学生语文成绩及边界判断。具体实现思路与Get_Income基本一致。

  1. void Get_Chinese(Student *data)
  2. {
  3. printf("\t\t\t\t请输入语文成绩(0~150,输入-1返回上级菜单):");
  4. double tmp=-2;//初始置非法值
  5. fflush(stdin);
  6. scanf("%lf",&tmp);
  7. if(tmp!=-1)
  8. {
  9. if(tmp<0||tmp>150)
  10. {
  11. printf("\t\t\t\t语文成绩输入错误!\n");
  12. Get_Chinese(data);
  13. return;
  14. }
  15. }
  16. data->score[0]=tmp;
  17. }

(16)void Get_Math(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生数学成绩

输  出:无

返回值:无

功  能:实现获得输入学生数学成绩及边界判断。具体实现思路与Get_Income基本一致。

  1. void Get_Math(Student *data)
  2. {
  3. printf("\t\t\t\t请输入数学成绩(0~150,输入-1返回上级菜单):");
  4. double tmp=-2;
  5. fflush(stdin);
  6. scanf("%lf",&tmp);
  7. if(tmp!=-1)
  8. {
  9. if(tmp<0||tmp>150){
  10. printf("\t\t\t\t数学成绩输入错误!\n");
  11. Get_Math(data);
  12. return;
  13. }
  14. }
  15. data->score[1]=tmp;
  16. }

(17)void Get_English(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生英语成绩

输  出:无

返回值:无

功  能:实现获得输入学生英语成绩及边界判断。具体实现思路与Get_Income基本一致。

  1. void Get_English(Student *data)
  2. {
  3. printf("\t\t\t\t请输入英语成绩(0~150,输入-1返回上级菜单):");
  4. double tmp=-2;
  5. fflush(stdin);
  6. scanf("%lf",&tmp);
  7. if(tmp!=-1)
  8. {
  9. if(tmp<0||tmp>150){
  10. printf("\t\t\t\t英语成绩输入错误!\n");
  11. Get_English(data);
  12. return;
  13. }
  14. }
  15. data->score[2]=tmp;
  16. }

(18)void Get_Compre(Student *data)

输  入:临时保存学生记录的结构体指针*data,学生综合成绩

输  出:无

返回值:无

功  能:实现获得输入学生综合成绩及边界判断。具体实现思路与Get_Income基本一致。

  1. void Get_Compre(Student *data)
  2. {
  3. printf("\t\t\t\t请输入综合成绩(0~300,输入-1返回上级菜单):");
  4. double tmp=-2;
  5. fflush(stdin);
  6. scanf("%lf",&tmp);
  7. if(tmp!=-1)
  8. {
  9. if(tmp<0||tmp>300)
  10. {
  11. printf("\t\t\t\t综合成绩输入错误!\n");
  12. Get_Compre(data);
  13. return;
  14. }
  15. }
  16. data->score[3]=tmp;
  17. }

(19)void New_Student(Student *data,Student stu[])

输  入:临时保存学生记录的结构体指针*data,保存所有学生记录的结构体stu,所有学生记录字段

输  出:无

返回值:无

功  能:实现新建学生记录,并存入保存所有学生记录的结构体stu的末尾。临时保存学生记录的结构体指针*data,保存所有学生记录的结构体stu作为形参输入。临时保存学生记录的结构体指针*data,保存所有学生记录的结构体stu作为形参输入。依次调用Get_学生记录字段()函数,修改*data对应结构体的字段,并每次进行判断,若*data中字段为-1,调用Menu_Admin()返回管理员主菜单。若新学生记录所有字段均成功录入,将stu的中保存的外部文件路径向后移动一个位置,将*data对应的结构体中临时保存的学生记录置入stu中保存外部文件路径的签一个位置。提示用户是否继续新建学生记录,若“是”,递归继续新建学生记录;若“否”调用Menu_Admin()返回管理员主菜单。

  1. void New_Student(Student *data,FILE *fp,Student stu[])//添加新的学生记录
  2. {
  3. int length=Length_Student(stu);//计算内存结构体记录个数
  4. system("cls");
  5. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  6. printf("\t\t\t\t│ 新建学生档案 │\n");
  7. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  8. Get_Number(data,stu);//获得学号,函数将临时结构体data中的num字段改为-1或合法值
  9. if(data->num==-1) Menu_Admin(stu);//若临时结构体data中的num字段为-1,调用函数返回上级菜单
  10. //若临时结构体data中的num字段为合法值,进入程序继续获得下一个字段的值
  11. Get_Name(data);
  12. if(strcmp(data->name,"-1")==0) Menu_Admin(stu);
  13. Get_Major(data);
  14. if(strcmp(data->major,"-1")==0) Menu_Admin(stu);
  15. Get_Sex(data);
  16. if(strcmp(data->sex,"-1")==0) Menu_Admin(stu);
  17. Get_Origin(data);
  18. if(strcmp(data->origin,"-1")==0) Menu_Admin(stu);
  19. Get_Ethnic(data);
  20. if(strcmp(data->ethnic,"-1")==0) Menu_Admin(stu);
  21. Get_Politic(data);
  22. if(strcmp(data->politic,"-1")==0) Menu_Admin(stu);
  23. Get_Income(data);
  24. if(data->income==-1) Menu_Admin(stu);
  25. Get_Chinese(data);
  26. if(data->score[0]==-1) Menu_Admin(stu);
  27. Get_Math(data);
  28. if(data->score[1]==-1) Menu_Admin(stu);
  29. Get_English(data);
  30. if(data->score[2]==-1) Menu_Admin(stu);
  31. Get_Compre(data);
  32. if(data->score[3]==-1) Menu_Admin(stu);
  33. strcpy(stu[length+1].major,stu[length].major);//将之前存放的文件名置入结构体末的下一个位置
  34. stu[Length_Student(stu)]=*data;//将新的记录从临时结构体data中置入原结构体stu末
  35. printf("\t\t\t\t是否继续录入?(Y/N)");
  36. char key;
  37. getchar();//从键盘读取字符,保证key正常录入
  38. scanf("%c",&key);
  39. if(key=='Y') New_Student(data,fp,stu);//递归
  40. else Menu_Admin(stu);//返回上级菜单
  41. }

(20)void Delete_Student(Student data[],int i)

输  入:保存所有学生记录的结构体stu,待删除学生记录位置i

输  出:无

返回值:无

功  能:实现删除学生记录。保存所有学生记录的结构体stu,待删除学生记录位置i作为形参输入。提示是否确认删除。确认删除将stu中i位置后的所有学生记录前移,覆盖i位置的学生记录。成功删除后,调用Menu_Admin()返回管理员主菜单。

  1. void Delete_Student(Student data[],int i)//删除学生档案记录
  2. {
  3. printf("\n\t\t\t\t确认删除?(Y/N)");
  4. char ch;
  5. Student tmp;//临时结构体,传入更改学生档案函数,用于临时记录修改值
  6. getchar();//清空字符缓冲区
  7. scanf("%c",&ch);
  8. if(ch=='Y')
  9. {
  10. for(int j=i;j<Length_Student(data);j++) data[j]=data[j+1];//将内存结构体中待删除位置后的所有记录前移,覆盖待删除位置的记录
  11. printf("\n\t\t\t\t档案删除成功!\n\t\t\t\t");
  12. system("pause");
  13. Menu_Admin(data);//删除成功,返回管理员主菜单
  14. }
  15. else Menu_Change(tmp,data,i);//不执行删除,返回删除/更改学生档案子菜单
  16. }

(21)void Change_Student(Student data,Student stu[],int i)

输  入:待修改的保存所有学生记录的结构体stu,学号查重的保存所有学生记录的结构体stu,待修改学生记录位置i

输  出:无

返回值:无

功  能:实现修改学生记录。待修改的保存所有学生记录的结构体stu,学号查重的保存所有学生记录的结构体stu,待修改学生记录位置i作为形参输入,其中stu,data指向同一内存空间。展示菜单,输入菜单选项,选择修改的字段,调用Get_学生记录字段,修改data的对应字段,非法输入递归重新输入菜单选项。

  1. void Change_Student(Student data,Student stu[],int i)//修改学生信息
  2. {
  3. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  4. printf("\t\t\t\t│ │\n");
  5. printf("\t\t\t\t│ #1.修改学号字段 │\n");
  6. printf("\t\t\t\t│ │\n");
  7. printf("\t\t\t\t│ #2.修改姓名字段 │\n");
  8. printf("\t\t\t\t│ │\n");
  9. printf("\t\t\t\t│ #3.修改专业字段 │\n");
  10. printf("\t\t\t\t│ │\n");
  11. printf("\t\t\t\t│ #4.修改民族字段 │\n");
  12. printf("\t\t\t\t│ │\n");
  13. printf("\t\t\t\t│ #5.修改生源地字段 │\n");
  14. printf("\t\t\t\t│ │\n");
  15. printf("\t\t\t\t│ #6.修改性别字段 │\n");
  16. printf("\t\t\t\t│ │\n");
  17. printf("\t\t\t\t│ #7.修改政治面貌字段 │\n");
  18. printf("\t\t\t\t│ │\n");
  19. printf("\t\t\t\t│ #8.修改家庭收入字段 │\n");
  20. printf("\t\t\t\t│ │\n");
  21. printf("\t\t\t\t│ #9.修改语文成绩字段 │\n");
  22. printf("\t\t\t\t│ │\n");
  23. printf("\t\t\t\t│ #10.修改数学成绩字段 │\n");
  24. printf("\t\t\t\t│ │\n");
  25. printf("\t\t\t\t│ #11.修改英语成绩字段 │\n");
  26. printf("\t\t\t\t│ │\n");
  27. printf("\t\t\t\t│ #12.修改综合成绩字段 │\n");
  28. printf("\t\t\t\t│ │\n");
  29. printf("\t\t\t\t│ #0.返回上级菜单 │\n");
  30. printf("\t\t\t\t│ │\n");
  31. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  32. printf("\t\t\t\t请键入功能编号:");
  33. int key=-1;//初始置非法值,防止输入字符产生错误
  34. fflush(stdin);//清空缓存区
  35. scanf("%d",&key);
  36. switch(key)
  37. {
  38. case 0:
  39. Menu_Change(data,stu,i);//取消修改操作,返回删除/更改子菜单,选择删除或更改的操作
  40. case 1:
  41. Get_Number(&data,stu);//复用,获得学号
  42. if(data.num!=-1) stu[i].num=data.num;
  43. break;
  44. case
  45. 2:Get_Name(&data);
  46. if(strcmp(data.name,"-1")!=0) strcpy(stu[i].name,data.name);
  47. break;
  48. case 3:
  49. Get_Major(&data);
  50. if(strcmp(data.major,"-1")!=0) strcpy(stu[i].major,data.major);
  51. break;
  52. case 4:
  53. Get_Ethnic(&data);
  54. if(strcmp(data.ethnic,"-1")!=0) strcpy(stu[i].ethnic,data.ethnic);
  55. break;
  56. case 5:
  57. Get_Origin(&data);
  58. if(strcmp(data.origin,"-1")!=0) strcpy(stu[i].origin,data.origin);
  59. break;
  60. case 6:
  61. Get_Sex(&data);
  62. if(strcmp(data.sex,"-1")!=0) strcpy(stu[i].sex,data.sex);
  63. break;
  64. case 7:
  65. Get_Politic(&data);
  66. if(strcmp(data.politic,"-1")!=0) strcpy(stu[i].politic,data.politic);
  67. break;
  68. case 8:
  69. Get_Income(&data);
  70. if(data.income!=-1) stu[i].income=data.income;
  71. break;
  72. case 9:
  73. Get_Chinese(&data);
  74. if(data.score[0]!=-1) stu[i].score[0]=data.score[0];
  75. break;
  76. case 10:
  77. Get_Math(&data);
  78. if(data.score[1]!=-1) stu[i].score[1]=data.score[1];
  79. break;
  80. case 11:
  81. Get_English(&data);
  82. if(data.score[2]!=-1) stu[i].score[2]=data.score[2];
  83. break;
  84. case 12:
  85. Get_Compre(&data);
  86. if(data.score[3]!=-1) stu[i].score[3]=data.score[3];
  87. break;
  88. default:
  89. printf("输入错误!");//非法输入的提示
  90. Change_Student(data,stu,i);//递归跳转
  91. break;
  92. }
  93.  
  94. }

(22)void Show_Student(Student data[],int i)

输  入:保存所有学生记录的结构体data,待展示学生记录的位置i

输  出:指定位置学生记录的详细信息

返回值:无

功  能:实现展示指定位置学生记录详细信息。保存所有学生记录的结构体data,待展示学生记录的位置i作为形参输入。在控制台展示stu中i位置学生记录的详细信息。

  1. void Show_Student(Student data[],int i)//展示学生全部信息
  2. {
  3. printf("#####################################################################################################################################\n");
  4. printf("\t学号:%d\t\t姓名:%s\t\t年级:%d\t\t班级:%d\t\t专业:%s\n",
  5. data[i].num,data[i].name,data[i].num/10000,data[i].num/100,data[i].major);
  6. printf("\t生源地:%s\t\t民族:%s\t\t性别:%s\t\t家庭收入:%.0lf\t\t政治面貌:%s\n"
  7. ,data[i].origin,data[i].ethnic,data[i].sex,data[i].income,data[i].politic);
  8. printf("\t语文成绩:%.1lf\t\t数学成绩:%.1lf\t\t英语成绩:%.1lf\t\t综合成绩:%.1lf\t\t总分:%.1lf\n",
  9. data[i].score[0],data[i].score[1],data[i].score[2],data[i].score[3],
  10. data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]);
  11. printf("#####################################################################################################################################\n\n");
  12. }

(23)void Sort_Number(Student data[],int front,int rear)

输  入:保存所有学生记录的结构体data

输  出:无

返回值:无

功  能:实现对所有学生记录按学号由小至大进行快速排序。

  1. void Sort_Number(Student data[],int front,int rear)//对全部学生信息按学号快速排序
  2. {
  3. if(front>=rear)
  4. {
  5. return;
  6. }
  7. int i=front;
  8. int j=rear;
  9. Student tmp=data[front];//轴
  10. while(i<j)
  11. {
  12. while(i<j&&tmp.num<=data[j].num)//找比轴小的记录
  13. {
  14. j--;
  15. }
  16. data[i]=data[j];//放到轴前面
  17. while(i<j&&tmp.num>=data[i].num)//找比轴大的记录
  18. {
  19. i++;
  20. }
  21. data[j]=data[i];//放到轴后面
  22. }
  23. data[i]=tmp;//轴置入中间
  24. Sort_Number(data,front,i-1);//轴的前一半,递归
  25. Sort_Number(data,i+1,rear);//轴的后一半,递归
  26. }

(24)void Sort_Origin(Student data[],int front,int rear)

输  入:保存所有学生记录的结构体data

输  出:无

返回值:无

功  能:实现对所有学生记录按生源地进行快速排序。

  1. void Sort_Origin(Student data[],int front,int rear)//对全部学生信息按生源地快速排序
  2. {
  3. if(front>=rear)
  4. {
  5. return;
  6. }
  7. int i=front;
  8. int j=rear;
  9. Student tmp=data[front];
  10. while(i<j)
  11. {
  12. while(i<j&&strcmp(tmp.origin,data[j].origin)<=0)
  13. {
  14. j--;
  15. }
  16. data[i]=data[j];
  17. while(i<j&&strcmp(tmp.origin,data[i].origin)>=0)
  18. {
  19. i++;
  20. }
  21. data[j]=data[i];
  22. }
  23. data[i]=tmp;
  24. Sort_Origin(data,front,i-1);
  25. Sort_Origin(data,i+1,rear);
  26. }

(25)void Sort_Ethnic(Student data[],int front,int rear)

输  入:保存所有学生记录的结构体data

输  出:无

返回值:无

功  能:实现对所有学生记录按民族进行快速排序。

  1. void Sort_Ethnic(Student data[],int front,int rear)//对全部学生信息按民族快速排序
  2. {
  3. if(front>=rear)
  4. {
  5. return;
  6. }
  7. int i=front;
  8. int j=rear;
  9. Student tmp=data[front];
  10. while(i<j){
  11. while(i<j&&strcmp(tmp.ethnic,data[j].ethnic)<=0)
  12. {
  13. j--;
  14. }
  15. data[i]=data[j];
  16. while(i<j&&strcmp(tmp.ethnic,data[i].ethnic)>=0)
  17. {
  18. i++;
  19. }
  20. data[j]=data[i];
  21. }
  22. data[i]=tmp;
  23. Sort_Ethnic(data,front,i-1);
  24. Sort_Ethnic(data,i+1,rear);
  25. }

(26)void Sort_Major(Student data[],int front,int rear)

输  入:保存所有学生记录的结构体data

输  出:无

返回值:无

功  能:实现对所有学生记录按专业进行快速排序。

(27)int Check_Number(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查学号

输  出:无

返回值:待查学号在data中的位置或-1

功  能:实现按学号查找学生记录。保存所有学生记录的结构体data,指示上级菜单的menuflag作为形参输入。输入待查学号,若输入为-1,函数返回-1。若输入不为-1,用二分法对学号进行查找,若找到返回学号对应学生记录的位置。若未找到,声明整形变量check记录内层函数的返回值,递归继续查找学号,函数返回check。通过一系列判断,函数最终返回合法待查询学号在stu中的位置或-1。

(28)void Check_Name(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查姓名

输  出:符合待查姓名的所有学生记录

返回值:无

功  能:实现按姓名查找学生记录。保存所有学生记录的结构体data,指示上级菜单的menuflag作为形参输入。声明整形变量flag指示是否找到待查记录,初始值置0。输入待查姓名,若输入为-1,依照menuflag指示调用函数返回上级菜单:若menuflag为1,调用Menu_Admin()返回管理员主菜单,若menuflag为0,调用Menu_User()返回用户主菜单。

若输入姓名不为-1,遍历data,若找到符合待查姓名的学生记录,flag置1,调用Show_Student展示学生记录详细信息。若flag最终为0,提示未找到符合待查姓名的学生记录,递归继续查找。

(29)void Check_Grade(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查年级

输  出:符合待查年级的所有学生记录

返回值:无

功  能:实现按年级查找学生记录。具体实现思路与Check_Name()基本一致,其中年级的通过数学方法获得。如:

  1. int num=;
  2.  
  3. int grade=num/; //grade=2017

(30)void Check_Class(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查班级

输  出:符合待查班级的所有学生记录

返回值:无

功  能:实现按班级查找学生记录。具体实现思路与Check_Name()基本一致,其中班级的通过数学方法获得。如:

  1. int num=;
  2.  
  3. int classnum=(num/)%; //classnum=1743

(31)void Check_Major(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查专业

输  出:符合待查专业的所有学生记录

返回值:无

功  能:实现按专业查找学生记录。具体实现思路与Check_Name()基本一致。

(32)void Check_Origin(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查生源地

输  出:符合待查生源地的所有学生记录

返回值:无

功  能:实现按生源地查找学生记录。具体实现思路与Check_Name()基本一致。

(33)void Check_Ethnic(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查民族

输  出:符合待查民族的所有学生记录

返回值:无

功  能:实现按民族查找学生记录。具体实现思路与Check_Name()基本一致。

(34)void Check_Politic(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查政治面貌

输  出:符合待查政治面貌的所有学生记录

返回值:无

功  能:实现按政治面貌查找学生记录。具体实现思路与Check_Name()基本一致。

(35)void Check_Sex(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查性别

输  出:符合待查性别的所有学生记录

返回值:无

功  能:实现按性别查找学生记录。具体实现思路与Check_Name()基本一致。

(36)void Check_Income(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查家庭收入最低值minincome,待查家庭收入最高值maxincome

输  出:符合家庭收入范围的所有学生记录

返回值:无

功  能:实现按家庭收入范围查找学生记录。保存所有学生记录的结构体data,指示上级菜单的menuflag作为形参输入。声明整形变量flag指示是否找到范围内的学生记录,初始值置0。输入待查家庭收入最低值minincome,若输入-1,返回上级菜单,若输入超出合法范围,递归重新获得家庭收入范围。若输入合法,继续输入待查家庭收入最高值maxincome,若输入-1,返回上级菜单,若输入超出合法值,递归重新获得家庭收入范围,若maxincome小于minincome,递归重新获得家庭收入范围。minincome和maxincome输入均合法,遍历data,若找到符合输入家庭收入范围的学生记录,调用Show_Student()展示学生记录,flag置1。若flag最终为0,提示未查找到记录,结束。

(37)void Check_Chinese(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查语文成绩最低值minchinese,待查语文成绩最高值maxchinese

输  出:符合语文成绩范围的所有学生记录

返回值:无

功  能:实现按语文成绩范围查找学生记录。具体实现思路与Check_Income()基本一致。

(38)void Check_Math(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查数学成绩最低值minmath,待查数学成绩最高值maxmath

输  出:符合数学成绩范围的所有学生记录

返回值:无

功  能:实现按数学成绩范围查找学生记录。具体实现思路与Check_Income()基本一致。

(39)void Check_English(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查英语成绩最低值minenglish,待查英语成绩最高值maxenglish

输  出:符合英语成绩范围的所有学生记录

返回值:无

功  能:实现按英语成绩范围查找学生记录。具体实现思路与Check_Income()基本一致。

(40)void Check_Compre(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查综合成绩最低值mincompre,待查综合成绩最高值maxcompre

输  出:符合综合成绩范围的所有学生记录

返回值:无

功  能:实现按综合成绩范围查找学生记录。具体实现思路与Check_Income()基本一致。

(41)void Check_Score(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查入学总成绩最低值minscore,待查入学总成绩最高值maxscore

输  出:符合入学总成绩范围的所有学生记录

返回值:无

功  能:实现按入学总成绩范围查找学生记录。具体实现思路与Check_Income()基本一致,其中入学总成绩通过score[0]+ score[1]+ score[2]+ score[3]获得。

(42)void Count_Class_Score(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查班级

输  出:按输入班级,统计各个学生的入学总成绩,班级各科最高分、最低分,班级入学平均成绩

返回值:无

功  能:实现按输入班级,统计各个学生的入学总成绩,班级各科最高分、最低分,班级入学平均成绩。保存所有学生记录的结构体data,指示上级菜单的menuflag作为形参输入。要实现此功能,需要先对data的学生记录按照学号进行排序。声明以下整形变量:classflag指示待查班号是否找到,初始值置0;classsize指示班级人数。声明各科目最高值与最低值的初始整形变量,最低值置满分,最高值置0分。声明双精度浮点型变量classavg指示班级入学平均成绩。输入待查班级,若输入-1,返回上级菜单。若输入不为-1,遍历data,每当找到学生记录符合待查班级,classflag置1,classsize自增,将此学生记录中语文、数学、英语、综合成绩一同累加置classavg,并依次比较各科成绩最高值与最低值,即时更新。遍历结束,classavg=classacg/classsize得到班级入学总成绩平均值。若classflag为1,展示各科最高分、最低分、班级平均成绩,否则提示班级未找到,递归重新获得待查班级

(43)void Count_Grade_Major(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查年级

输  出:待查年级统计各专业的人数

返回值:无

功  能:实现按年级统计各专业的人数。保存所有学生记录的结构体data,指示上级菜单的menuflag作为形参输入。要实现此功能,需要先对data的数据按照专业排序。声明整形变量gradeflag指示待查年级是否找到。声明字符串tmp记录已查询完毕的专业。遍历data,若学生记录符合待查年纪,且学生专业非已查询完毕的专业,此位置记为i,gradeflag置1。由i向后遍历,若查找到专业与i位置的专业不同,此位置记为j。由于已经按照专业进行排序,故专业是连续排列的,i指示某专业中符合待查年级的第一个位置,j指示此专业末尾位置的下一个位置。在i~j之间计数,若学生记录符合待查年级,计数器自增。若最终gradeflag为0,提示未找到,递归重新获得待查年级。

(44)void Count_Class_Origin(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查班级

输  出:待查班级统计各个省市人数

返回值:无

功  能:实现按班级统计各个省市人数。实现具体思路与Count_Grade_Major()基本一致。

(45)void Count_Grade_Ethnic(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查年级

输  出:待查年级各个少数民族的人数

返回值:无

功  能:实现按年级统计各个少数民族人数。实现具体思路与Count_Grade_Major()基本一致。

(46)void Count_Major_Sex(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查专业

输  出:待查专业各个年级男女人数

返回值:无

功  能:实现按专业统计年级男女分布。保存所有学生记录的结构体data,指示上级菜单的menuflag作为形参输入。输入待查性别,若输入-1,返回上级菜单。遍历data,若学生记录的年级与上一个学生记录的年级不同,由此向后遍历,若找到男生,则男生计数器自增,若找到女生,则女生计数器自增。若学生记录与正查询年级不同,跳出循环,输入本年级男女人数,男女计数器归0。

(47)void Count_Grade_ClassPoor(Student data[],int menuflag)

输  入:保存所有学生记录的结构体data,指示上级菜单的menuflag,待查年级

输  出:待查年级所有班级中家庭收入低于班级平均的学生人数

返回值:无

功  能:实现按年级统计所有班级中家庭收入低于班级平均的学生人数。实现具体思路与Count_Grade_Major()基本一致。

(48)void Login(Student data[],int count)

输  入:剩余试错次数count,身份码

输  出:无

返回值:无

功  能:实现验证身份码登陆。利用getch()函数实现不回显录入字符,每当输入字符则打印“*”,实现密文输入。对于回退,设置判断条件,当输入回退是,打印“/b /b”,同时指示字符串位置的变量自减,实现密文回退。从外部文件读取管理员身份码和普通用户身份码,若比对成功,则进行对应跳转,否则剩余试错次数-1,递归。当剩余试错次数为0时,退出程序。

(49)void Change_Code(Student data[])

输  入:新身份码

输  出:无

返回值:无

功  能:实现身份码的更改。若管理员身份码与普通用户身份码重用,提示错误,递归重新获得新身份码。若管理员身份码或普通用户身份码超过限制长度,提示错误,递归重新获得新身份码。

(50)void Menu_Admin(Student stu[])

输  入:菜单选项

输  出:对应子菜单

返回值:无

功  能:展示管理员主菜单并提供子菜单选择。

(51)void Menu_User(Student stu[])

输  入:菜单选项

输  出:对应子菜单

返回值:无

功  能:展示普通用户主菜单并提供子菜单选择。

(52)void Menu_Change(Student stu[])

输  入:菜单选项

输  出:对应子菜单

返回值:无

功  能:展示删除/更改学生记录子菜单并提供菜单选择。

(53)void Menu_Check(Student stu[])

输  入:菜单选项

输  出:对应功能

返回值:无

功  能:展示查询功能自菜单并提供子菜单选择。

(54)void Menu_Count(Student stu[])

输  入:菜单选项

输  出:对应功能

返回值:无

功  能:展示统计功能子菜单并提供子菜单选择。

五、程序测试

图1 管理员登陆

图2 普通用户登陆

图3 登陆失败

图4 成功打开文件

图5 管理员主菜单

图6 普通用户主菜单

图7 管理员主菜单边界

图8 新建学生边界

图9 删除/更改学生档案

图10 更改名字

图11 更改名字成功

图12 查询与显示

图13 查询边界

图14 统计与显示

图15 按班级统计分数情况

图16 按年级统计专业人数

图17 按班级统计省市人数

图18 按年级统计少数民族人数

图19 按年级统计家庭收入低于平均人数

图20 更改身份码过长

图21 更改身份码重用

图22 结束字符画

六、设计小结

本任务设计的代码完成基本功能,但是有几个缺点:

1. 读入文件路径设置画蛇添足

在读入文件路径时,我将打开文件的指针设置为了只读方式打开文件,没有考虑新建空数据源的情况。我将代码修改为以附加的方式打开只写文件,实现了若文件不存在则新建文件的功能。

2. 从学号中提取班级的算法有缺陷

由于在数据结构中学生记录的学号字段我采用了整形变量存储,故学生的年级,班级我都是通过数学方法从学号中提取:

  1. int num=;
  2.  
  3. int grade=num/; //grade=2017
  4.  
  5. int classnum=num/- //classnum=17

但是若学号为1999开头的,即学生记录拓展到90年代入学的学生,则我的代码不具有适用性,因此,我将代码修改如下:

  1. int num=;
  2.  
  3. int classnum=)num/)% //classnum=17

这样从学号中提取班级的代码就具有了通用性。但是,最好的解决方案是将数据结构体进行修改,学号字段用字符串储存,在提取年级,班级时提取字串即可稳定解决。但相对应的,其边界判断将变得复杂。两种方式各有利弊,但是利用字符串进行存储相对更能保证运行的稳定,这是程序实现的最终目的,贪图简单轻松则可能出错。

七、使用说明

本程序提交的是cpp源代码,所以用DEV-CPP打开直接编译运行,然后按照程序提示操作即可。

八、附录

程序源代码参见C语言程序文件main.cpp。

  1. #include "stdio.h"
  2. #include "string.h"
  3. #include "stdlib.h"
  4. #include "conio.h"
  5.  
  6. //作者:20174314-王方正
  7. //题目:《程序设计实践教程》教材22题
  8. //完成时间:2019年9月11日
  9. //指导老师:徐小青老师、李晓东老师
  10.  
  11. struct Student
  12. {
  13. int num;//学号
  14. char name[10];//姓名
  15. char major[20];//专业
  16. char origin[8];//生源地
  17. char ethnic[12];//民族
  18. char sex[3];//性别
  19. char politic[12];//政治面貌
  20. double income;//家庭收入
  21. double score[4];//学生成绩
  22. };
  23.  
  24. void Menu_Admin(Student stu[]);//管理员账号主菜单
  25. void Menu_User(Student stu[]);//用户账号主菜单
  26. void Menu_Change(Student data,Student stu[],int check);//删除/修改学生档案子菜单
  27. void Menu_Check(Student stu[],int menuflag);//查询与显示子菜单
  28. void Menu_Count(Student stu[],int menuflag);//统计与显示子菜单
  29.  
  30. void Print_Welcome()
  31. {
  32. printf("\t\t\t\t _______ _ _______ _______ _______ _______ \n");
  33. printf("\t\t\t\t|\\ /|( ____ \\( \\ ( ____ \\( ___ )( )( ____ \\\n");
  34. printf("\t\t\t\t| ) ( || ( \\/| ( | ( \\/| ( ) || () () || ( \\/\n");
  35. printf("\t\t\t\t| | _ | || (__ | | | | | | | || || || || (__ \n");
  36. printf("\t\t\t\t| |( )| || __) | | | | | | | || |(_)| || __) \n");
  37. printf("\t\t\t\t| || || || ( | | | | | | | || | | || ( \n");
  38. printf("\t\t\t\t| () () || (____/\\| (____/\\| (____/\\| (___) || ) ( || (____/\\\n");
  39. printf("\t\t\t\t(_______)(_______/(_______/(_______/(_______)|/ \\|(_______/\n\n");
  40. }
  41.  
  42. void Print_End()//结束程序彩蛋
  43. {
  44. system("color fc");
  45. printf("\t\t\t\t _______ _______ _______ ______ ______ _______ \n");
  46. printf("\t\t\t\t( ____ \\( ___ )( ___ )( __ \\ ( ___ \\ |\\ /|( ____ \\\n");
  47. printf("\t\t\t\t| ( \\/| ( ) || ( ) || ( \\ )| ( ) )( \\ / )| ( \\/\n");
  48. printf("\t\t\t\t| | | | | || | | || | ) || (__/ / \\ (_) / | (__ \n");
  49. printf("\t\t\t\t| | ____ | | | || | | || | | || __ ( \\ / | __) \n");
  50. printf("\t\t\t\t| | \\_ )| | | || | | || | ) || ( \\ \\ ) ( | ( \n");
  51. printf("\t\t\t\t| (___) || (___) || (___) || (__/ )| )___) ) | | | (____/\\\n");
  52. printf("\t\t\t\t(_______)(_______)(_______)(______/ |/ \\___/ \\_/ (_______/\n");
  53. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  54. printf("\t\t\t\t│ 感谢使用!! │\n");
  55. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  56. }
  57.  
  58. int Length_Student(Student data[])//结构体长度
  59. {
  60. int i;//循环用变量
  61. for(i=0;data[i].num!=0;i++);
  62. return i;
  63. }
  64.  
  65. void Load_Student(Student data[],FILE *fp)//从文件读取学生信息
  66. {
  67. for(int i=0;!feof(fp);i++)//在文件到底之前,将文件中所有记录依次读入
  68. {
  69. fscanf(fp,"%d",&data[i].num);
  70. fscanf(fp,"%s",data[i].name);
  71. fscanf(fp,"%s",data[i].major);
  72. fscanf(fp,"%s",data[i].origin);
  73. fscanf(fp,"%s",data[i].ethnic);
  74. fscanf(fp,"%s",data[i].sex);
  75. fscanf(fp,"%s",data[i].politic);
  76. fscanf(fp,"%lf",&data[i].income);
  77. fscanf(fp,"%lf",&data[i].score[0]);
  78. fscanf(fp,"%lf",&data[i].score[1]);
  79. fscanf(fp,"%lf",&data[i].score[2]);
  80. fscanf(fp,"%lf",&data[i].score[3]);
  81. }
  82. fclose(fp);//关闭文件
  83. }
  84.  
  85. void Overwrite_Student(Student data[],FILE *fp)//覆盖文件中的记录
  86. {
  87. for(int i=0;i<Length_Student(data);i++)//将内存结构体中的记录置入文件
  88. {
  89. fprintf(fp,"%d\t%s\t%s\t%s\t%s\t%s\t%s\t%.1lf\t%.1lf\t%.1lf\t%.1lf\t%.1lf\t\n",
  90. data[i].num,data[i].name,data[i].major,data[i].origin,data[i].ethnic,data[i].sex,data[i].politic,
  91. data[i].income,data[i].score[0],data[i].score[1],data[i].score[2],data[i].score[3]);
  92. }
  93. fclose(fp);
  94. }
  95.  
  96. void Initialize_Student(Student data[])//初始化结构体
  97. {
  98. system("cls");
  99. char address[20];//记录文件名的字符串
  100. FILE *fp=NULL;//文件指针置空
  101. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  102. printf("\t\t\t\t│ 选择文件路径 │\n");
  103. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  104. printf("\t\t\t\t请输入文件路径(完整路径,输入-1退出程序):");
  105. scanf("%s",address);
  106. if(strcmp(address,"-1")==0)//输入-1退出程序
  107. {
  108. system("cls");//清屏
  109. Print_End();//展示结束画面
  110. exit(0);//关闭程序
  111. }
  112. else if((fp=fopen(address, "a"))==NULL)//无法打开文件,递归重新输入文件名
  113. {
  114. printf("\n\t\t\t\t文件打开失败...\n\t\t\t\t");
  115. system("pause");
  116. Initialize_Student(data);//递归重新输入文件名
  117. return;
  118. }
  119. else//文件打开成功
  120. {
  121. printf("\n\t\t\t\t文件打开成功!");
  122. system("pause");
  123. fp=fopen(address, "r");
  124. Load_Student(data,fp);//从文件中读取记录到内存中的结构体
  125. strcpy(data[Length_Student(data)].major,address);//利用结构体的末尾存储空间存储文件名字符串
  126. }
  127. }
  128.  
  129. void Get_Number(Student *data,Student stu[])//获取学号的函数,前者为临时结构体,后者为已录入外存记录的结构体
  130. {
  131. printf("\t\t\t\t请输入学号(八位数字,输入-1返回上级菜单):");
  132. int tmp=-2;//临时变量,保存输入值,置为非法置,防止输入字符时错误跳转
  133. int length=Length_Student(stu);//计算结构体总长度
  134. fflush(stdin);//清空缓存区
  135. scanf("%d",&tmp);
  136. if(tmp!=-1)//输入-1,返回上级菜单
  137. {
  138. if(tmp/10000<1977||tmp/10000>2020)//超出学生年级范围
  139. {
  140. printf("\t\t\t\t学号输入错误!\n");
  141. Get_Number(data,stu);//递归
  142. return;//函数此处结束
  143. }
  144. for(int i=0;i<=length;i++)//在原学号库中查重
  145. {
  146. if(stu[i].num==tmp)//输入学号重复
  147. {
  148. printf("\t\t\t\t学号输入重复!\n");
  149. Get_Number(data,stu);//递归
  150. return;//函数此处结束
  151. }
  152. }
  153. }
  154. data->num=tmp;//最终将合法值或-1传入临时结构体
  155. return;
  156. }
  157.  
  158. void Get_Name(Student *data)
  159. {
  160. printf("\t\t\t\t请输入姓名(中文名,输入-1返回上级菜单):");
  161. char tmp[10];//临时变量,保存输入值
  162. scanf("%s",tmp);
  163. int length=strlen(tmp);//获取字符串长度
  164. if(strcmp(tmp,"-1")!=0)//输入-1,返回上级菜单
  165. {
  166. for(int i=0;i<=length;i++)
  167. {
  168. if(tmp[i]>=1&&tmp[i]<=127)//如果输入了非中文字符,判断为输入错误
  169. {
  170. printf("\t\t\t\t姓名输入错误!\n");
  171. Get_Name(data);
  172. return;
  173. }
  174. }
  175. }
  176. strcpy(data->name,tmp);//将合法值传入临时结构体
  177. return;
  178. }
  179.  
  180. void Get_Major(Student *data)
  181. {
  182. printf("\t\t\t\t请输入专业\n\t\t\t\t(信息与计算科学/信息安全/计算机科学与技术/信息管理与信息系统/电子信息工程/通信工程/行政管理/保密管理,输入-1返回上级菜单):");
  183. int flag=0;//指示专业是否存在
  184. char tmp[20];//临时变量,保存输入值
  185. char majorlist[8][20]={"信息与计算科学","信息安全","计算机科学与技术","信息管理与信息系统","电子信息工程",
  186. "通信工程","行政管理","保密管理"};//比对专业信息的库
  187. scanf("%s",tmp);
  188. if(strcmp(tmp,"-1")!=0)//输入-1,返回上级菜单
  189. {
  190. for(int i=0;i<8;i++)
  191. if(strcmp(tmp,majorlist[i])==0)
  192. {
  193. flag=1;
  194. break;
  195. }
  196. if(flag==0)//没有找到库中的专业
  197. {
  198. printf("\t\t\t\t专业输入错误!\n");
  199. Get_Major(data);//递归
  200. return;
  201. }
  202. }
  203. strcpy(data->major,tmp);
  204. return;
  205. }
  206.  
  207. void Get_Origin(Student *data)
  208. {
  209. printf("\t\t\t\t请输入生源地(省份名称,输入-1返回上级菜单):");
  210. int flag;
  211. char tmp[8];
  212. char originlist[34][8]={"北京","天津","上海","重庆","河北","山西","辽宁","吉林","黑龙江",
  213. "江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东","海南","四川","贵州",
  214. "云南","陕西","甘肃","青海","台湾","内蒙古","广西","西藏","宁夏","新疆","香港","澳门"};
  215. scanf("%s",tmp);
  216. if(strcmp(tmp,"-1")!=0)
  217. {
  218. for(int i=0;i<34;i++)
  219. if(strcmp(tmp,originlist[i])==0)
  220. {
  221. flag=1;
  222. break;
  223. }
  224. if(flag==0)//没有找到库中的省份
  225. {
  226. printf("\t\t\t\t生源地输入错误!\n");
  227. Get_Origin(data);//递归
  228. return;
  229. }
  230. }
  231. strcpy(data->origin,tmp);
  232. return;
  233. }
  234.  
  235. void Get_Sex(Student *data)
  236. {
  237. printf("\t\t\t\t请输入性别(男/女,输入-1返回上级菜单):");
  238. char male[3]="男",female[3]="女",tmp[3];
  239. scanf("%s",tmp);
  240. if(strcmp(tmp,"-1")!=0)
  241. {
  242. if(strcmp(tmp,male)*strcmp(tmp,female)!=0)//如果输入的性别不是男或女中的任一个,输入错误
  243. {
  244. printf("\t\t\t\t性别输入错误!\n");
  245. Get_Sex(data);
  246. return;
  247. }
  248. }
  249. strcpy(data->sex,tmp);
  250. return;
  251. }
  252.  
  253. void Get_Ethnic(Student *data)
  254. {
  255. printf("\t\t\t\t请输入民族(民族名称,输入-1返回上级菜单):");
  256. int flag=0;
  257. char tmp[12];
  258. char ethniclist[56][12]={"汉族","蒙古族","回族","藏族","维吾尔族","苗族","彝族","壮族",
  259. "布依族","朝鲜族","满族","侗族","瑶族","白族","土家族","哈尼族","哈萨克族","傣族","黎族",
  260. "僳僳族","佤族","畲族","高山族","拉祜族","水族","东乡族","纳西族","景颇族","柯尔克孜族",
  261. "土族","达斡尔族","仫佬族","羌族","布朗族","撒拉族","毛南族","仡佬族","锡伯族","阿昌族",
  262. "普米族","塔吉克族","怒族","乌孜别克族","俄罗斯族","鄂温克族","德昂族","保安族","裕固族",
  263. "京族","塔塔尔族","独龙族", "鄂伦春族","赫哲族","门巴族","珞巴族","基诺族"};
  264. scanf("%s",tmp);
  265. if(strcmp(tmp,"-1")!=0)
  266. {
  267. for(int i=0;i<57;i++)
  268. if(strcmp(tmp,ethniclist[i])==0){
  269. flag=1;
  270. break;
  271. }
  272. if(flag==0)
  273. {
  274. printf("\t\t\t\t民族输入错误!\n");
  275. Get_Ethnic(data);//递归
  276. return;
  277. }
  278. }
  279. strcpy(data->ethnic,tmp);
  280. return;
  281. }
  282.  
  283. void Get_Politic(Student *data)
  284. {
  285. printf("\t\t\t\t请输入政治面貌\n\t\t\t\t(群众/无党派人士/共青团员/入党积极分子/中共预备党员/中共党员,输入-1返回上级菜单):");
  286. int flag=0;
  287. char tmp[20];
  288. char politiclist[6][20]={"群众","无党派人士","共青团员","入党积极分子","中共预备党员","中共党员"};
  289. scanf("%s",tmp);
  290. if(strcmp(tmp,"-1")!=0)
  291. {
  292. for(int i=0;i<8;i++)
  293. if(strcmp(tmp,politiclist[i])==0)
  294. {
  295. flag=1;
  296. break;
  297. }
  298. if(flag==0)
  299. {
  300. printf("\t\t\t\t政治面貌输入错误!\n");
  301. Get_Politic(data);//递归
  302. return;
  303. }
  304. }
  305. strcpy(data->politic,tmp);
  306. return;
  307. }
  308.  
  309. void Get_Income(Student *data)
  310. {
  311. printf("\t\t\t\t请输入家庭收入(0~99999,输入-1返回上级菜单):");
  312. double tmp=-2;//初始值非法值,防止输入字符产生错误
  313. fflush(stdin);
  314. scanf("%lf",&tmp);
  315. if(tmp!=-1)
  316. {
  317. if(tmp<0||tmp>=100000)//输入的家庭收入超出范围
  318. {
  319. printf("\t\t\t\t家庭收入输入错误!\n");
  320. Get_Income(data);
  321. return;
  322. }
  323. }
  324. data->income=tmp;
  325. }
  326.  
  327. void Get_Chinese(Student *data)
  328. {
  329. printf("\t\t\t\t请输入语文成绩(0~150,输入-1返回上级菜单):");
  330. double tmp=-2;//初始置非法值
  331. fflush(stdin);
  332. scanf("%lf",&tmp);
  333. if(tmp!=-1)
  334. {
  335. if(tmp<0||tmp>150)
  336. {
  337. printf("\t\t\t\t语文成绩输入错误!\n");
  338. Get_Chinese(data);
  339. return;
  340. }
  341. }
  342. data->score[0]=tmp;
  343. }
  344.  
  345. void Get_Math(Student *data)
  346. {
  347. printf("\t\t\t\t请输入数学成绩(0~150,输入-1返回上级菜单):");
  348. double tmp=-2;
  349. fflush(stdin);
  350. scanf("%lf",&tmp);
  351. if(tmp!=-1)
  352. {
  353. if(tmp<0||tmp>150){
  354. printf("\t\t\t\t数学成绩输入错误!\n");
  355. Get_Math(data);
  356. return;
  357. }
  358. }
  359. data->score[1]=tmp;
  360. }
  361.  
  362. void Get_English(Student *data)
  363. {
  364. printf("\t\t\t\t请输入英语成绩(0~150,输入-1返回上级菜单):");
  365. double tmp=-2;
  366. fflush(stdin);
  367. scanf("%lf",&tmp);
  368. if(tmp!=-1)
  369. {
  370. if(tmp<0||tmp>150){
  371. printf("\t\t\t\t英语成绩输入错误!\n");
  372. Get_English(data);
  373. return;
  374. }
  375. }
  376. data->score[2]=tmp;
  377. }
  378.  
  379. void Get_Compre(Student *data)
  380. {
  381. printf("\t\t\t\t请输入综合成绩(0~300,输入-1返回上级菜单):");
  382. double tmp=-2;
  383. fflush(stdin);
  384. scanf("%lf",&tmp);
  385. if(tmp!=-1)
  386. {
  387. if(tmp<0||tmp>300)
  388. {
  389. printf("\t\t\t\t综合成绩输入错误!\n");
  390. Get_Compre(data);
  391. return;
  392. }
  393. }
  394. data->score[3]=tmp;
  395. }
  396.  
  397. void New_Student(Student *data,FILE *fp,Student stu[])//添加新的学生记录
  398. {
  399. int length=Length_Student(stu);//计算内存结构体记录个数
  400. system("cls");
  401. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  402. printf("\t\t\t\t│ 新建学生档案 │\n");
  403. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  404. Get_Number(data,stu);//获得学号,函数将临时结构体data中的num字段改为-1或合法值
  405. if(data->num==-1) Menu_Admin(stu);//若临时结构体data中的num字段为-1,调用函数返回上级菜单
  406. //若临时结构体data中的num字段为合法值,进入程序继续获得下一个字段的值
  407. Get_Name(data);
  408. if(strcmp(data->name,"-1")==0) Menu_Admin(stu);
  409. Get_Major(data);
  410. if(strcmp(data->major,"-1")==0) Menu_Admin(stu);
  411. Get_Sex(data);
  412. if(strcmp(data->sex,"-1")==0) Menu_Admin(stu);
  413. Get_Origin(data);
  414. if(strcmp(data->origin,"-1")==0) Menu_Admin(stu);
  415. Get_Ethnic(data);
  416. if(strcmp(data->ethnic,"-1")==0) Menu_Admin(stu);
  417. Get_Politic(data);
  418. if(strcmp(data->politic,"-1")==0) Menu_Admin(stu);
  419. Get_Income(data);
  420. if(data->income==-1) Menu_Admin(stu);
  421. Get_Chinese(data);
  422. if(data->score[0]==-1) Menu_Admin(stu);
  423. Get_Math(data);
  424. if(data->score[1]==-1) Menu_Admin(stu);
  425. Get_English(data);
  426. if(data->score[2]==-1) Menu_Admin(stu);
  427. Get_Compre(data);
  428. if(data->score[3]==-1) Menu_Admin(stu);
  429. strcpy(stu[length+1].major,stu[length].major);//将之前存放的文件名置入结构体末的下一个位置
  430. stu[Length_Student(stu)]=*data;//将新的记录从临时结构体data中置入原结构体stu末
  431. printf("\t\t\t\t是否继续录入?(Y/N)");
  432. char key;
  433. getchar();//从键盘读取字符,保证key正常录入
  434. scanf("%c",&key);
  435. if(key=='Y') New_Student(data,fp,stu);//递归
  436. else Menu_Admin(stu);//返回上级菜单
  437. }
  438.  
  439. void Delete_Student(Student data[],int i)//删除学生档案记录
  440. {
  441. printf("\n\t\t\t\t确认删除?(Y/N)");
  442. char ch;
  443. Student tmp;//临时结构体,传入更改学生档案函数,用于临时记录修改值
  444. getchar();//清空字符缓冲区
  445. scanf("%c",&ch);
  446. if(ch=='Y')
  447. {
  448. for(int j=i;j<Length_Student(data);j++) data[j]=data[j+1];//将内存结构体中待删除位置后的所有记录前移,覆盖待删除位置的记录
  449. printf("\n\t\t\t\t档案删除成功!\n\t\t\t\t");
  450. system("pause");
  451. Menu_Admin(data);//删除成功,返回管理员主菜单
  452. }
  453. else Menu_Change(tmp,data,i);//不执行删除,返回删除/更改学生档案子菜单
  454. }
  455.  
  456. void Change_Student(Student data,Student stu[],int i)//修改学生信息
  457. {
  458. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  459. printf("\t\t\t\t│ │\n");
  460. printf("\t\t\t\t│ #1.修改学号字段 │\n");
  461. printf("\t\t\t\t│ │\n");
  462. printf("\t\t\t\t│ #2.修改姓名字段 │\n");
  463. printf("\t\t\t\t│ │\n");
  464. printf("\t\t\t\t│ #3.修改专业字段 │\n");
  465. printf("\t\t\t\t│ │\n");
  466. printf("\t\t\t\t│ #4.修改民族字段 │\n");
  467. printf("\t\t\t\t│ │\n");
  468. printf("\t\t\t\t│ #5.修改生源地字段 │\n");
  469. printf("\t\t\t\t│ │\n");
  470. printf("\t\t\t\t│ #6.修改性别字段 │\n");
  471. printf("\t\t\t\t│ │\n");
  472. printf("\t\t\t\t│ #7.修改政治面貌字段 │\n");
  473. printf("\t\t\t\t│ │\n");
  474. printf("\t\t\t\t│ #8.修改家庭收入字段 │\n");
  475. printf("\t\t\t\t│ │\n");
  476. printf("\t\t\t\t│ #9.修改语文成绩字段 │\n");
  477. printf("\t\t\t\t│ │\n");
  478. printf("\t\t\t\t│ #10.修改数学成绩字段 │\n");
  479. printf("\t\t\t\t│ │\n");
  480. printf("\t\t\t\t│ #11.修改英语成绩字段 │\n");
  481. printf("\t\t\t\t│ │\n");
  482. printf("\t\t\t\t│ #12.修改综合成绩字段 │\n");
  483. printf("\t\t\t\t│ │\n");
  484. printf("\t\t\t\t│ #0.返回上级菜单 │\n");
  485. printf("\t\t\t\t│ │\n");
  486. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  487. printf("\t\t\t\t请键入功能编号:");
  488. int key=-1;//初始置非法值,防止输入字符产生错误
  489. fflush(stdin);//清空缓存区
  490. scanf("%d",&key);
  491. switch(key)
  492. {
  493. case 0:
  494. Menu_Change(data,stu,i);//取消修改操作,返回删除/更改子菜单,选择删除或更改的操作
  495. case 1:
  496. Get_Number(&data,stu);//复用,获得学号
  497. if(data.num!=-1) stu[i].num=data.num;
  498. break;
  499. case
  500. 2:Get_Name(&data);
  501. if(strcmp(data.name,"-1")!=0) strcpy(stu[i].name,data.name);
  502. break;
  503. case 3:
  504. Get_Major(&data);
  505. if(strcmp(data.major,"-1")!=0) strcpy(stu[i].major,data.major);
  506. break;
  507. case 4:
  508. Get_Ethnic(&data);
  509. if(strcmp(data.ethnic,"-1")!=0) strcpy(stu[i].ethnic,data.ethnic);
  510. break;
  511. case 5:
  512. Get_Origin(&data);
  513. if(strcmp(data.origin,"-1")!=0) strcpy(stu[i].origin,data.origin);
  514. break;
  515. case 6:
  516. Get_Sex(&data);
  517. if(strcmp(data.sex,"-1")!=0) strcpy(stu[i].sex,data.sex);
  518. break;
  519. case 7:
  520. Get_Politic(&data);
  521. if(strcmp(data.politic,"-1")!=0) strcpy(stu[i].politic,data.politic);
  522. break;
  523. case 8:
  524. Get_Income(&data);
  525. if(data.income!=-1) stu[i].income=data.income;
  526. break;
  527. case 9:
  528. Get_Chinese(&data);
  529. if(data.score[0]!=-1) stu[i].score[0]=data.score[0];
  530. break;
  531. case 10:
  532. Get_Math(&data);
  533. if(data.score[1]!=-1) stu[i].score[1]=data.score[1];
  534. break;
  535. case 11:
  536. Get_English(&data);
  537. if(data.score[2]!=-1) stu[i].score[2]=data.score[2];
  538. break;
  539. case 12:
  540. Get_Compre(&data);
  541. if(data.score[3]!=-1) stu[i].score[3]=data.score[3];
  542. break;
  543. default:
  544. printf("输入错误!");//非法输入的提示
  545. Change_Student(data,stu,i);//递归跳转
  546. break;
  547. }
  548.  
  549. }
  550.  
  551. void Show_Student(Student data[],int i)//展示学生全部信息
  552. {
  553. printf("#####################################################################################################################################\n");
  554. printf("\t学号:%d\t\t姓名:%s\t\t年级:%d\t\t班级:%d\t\t专业:%s\n",
  555. data[i].num,data[i].name,data[i].num/10000,data[i].num/100,data[i].major);
  556. printf("\t生源地:%s\t\t民族:%s\t\t性别:%s\t\t家庭收入:%.0lf\t\t政治面貌:%s\n"
  557. ,data[i].origin,data[i].ethnic,data[i].sex,data[i].income,data[i].politic);
  558. printf("\t语文成绩:%.1lf\t\t数学成绩:%.1lf\t\t英语成绩:%.1lf\t\t综合成绩:%.1lf\t\t总分:%.1lf\n",
  559. data[i].score[0],data[i].score[1],data[i].score[2],data[i].score[3],
  560. data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]);
  561. printf("#####################################################################################################################################\n\n");
  562. }
  563.  
  564. void Sort_Number(Student data[],int front,int rear)//对全部学生信息按学号快速排序
  565. {
  566. if(front>=rear)
  567. {
  568. return;
  569. }
  570. int i=front;
  571. int j=rear;
  572. Student tmp=data[front];//轴
  573. while(i<j)
  574. {
  575. while(i<j&&tmp.num<=data[j].num)//找比轴小的记录
  576. {
  577. j--;
  578. }
  579. data[i]=data[j];//放到轴前面
  580. while(i<j&&tmp.num>=data[i].num)//找比轴大的记录
  581. {
  582. i++;
  583. }
  584. data[j]=data[i];//放到轴后面
  585. }
  586. data[i]=tmp;//轴置入中间
  587. Sort_Number(data,front,i-1);//轴的前一半,递归
  588. Sort_Number(data,i+1,rear);//轴的后一半,递归
  589. }
  590.  
  591. void Sort_Origin(Student data[],int front,int rear)//对全部学生信息按生源地快速排序
  592. {
  593. if(front>=rear)
  594. {
  595. return;
  596. }
  597. int i=front;
  598. int j=rear;
  599. Student tmp=data[front];
  600. while(i<j)
  601. {
  602. while(i<j&&strcmp(tmp.origin,data[j].origin)<=0)
  603. {
  604. j--;
  605. }
  606. data[i]=data[j];
  607. while(i<j&&strcmp(tmp.origin,data[i].origin)>=0)
  608. {
  609. i++;
  610. }
  611. data[j]=data[i];
  612. }
  613. data[i]=tmp;
  614. Sort_Origin(data,front,i-1);
  615. Sort_Origin(data,i+1,rear);
  616. }
  617.  
  618. void Sort_Ethnic(Student data[],int front,int rear)//对全部学生信息按民族快速排序
  619. {
  620. if(front>=rear)
  621. {
  622. return;
  623. }
  624. int i=front;
  625. int j=rear;
  626. Student tmp=data[front];
  627. while(i<j){
  628. while(i<j&&strcmp(tmp.ethnic,data[j].ethnic)<=0)
  629. {
  630. j--;
  631. }
  632. data[i]=data[j];
  633. while(i<j&&strcmp(tmp.ethnic,data[i].ethnic)>=0)
  634. {
  635. i++;
  636. }
  637. data[j]=data[i];
  638. }
  639. data[i]=tmp;
  640. Sort_Ethnic(data,front,i-1);
  641. Sort_Ethnic(data,i+1,rear);
  642. }
  643.  
  644. void Sort_Major(Student data[],int front,int rear)//对全部学生信息按民族快速排序
  645. {
  646. if(front>=rear)
  647. {
  648. return;
  649. }
  650. int i=front;
  651. int j=rear;
  652. char key[8];
  653. Student tmp=data[front];
  654. while(i<j){
  655. while(i<j&&strcmp(tmp.major,data[j].major)<=0)
  656. {
  657. j--;
  658. }
  659. data[i]=data[j];
  660. while(i<j&&strcmp(tmp.major,data[i].major)>=0)
  661. {
  662. i++;
  663. }
  664. data[j]=data[i];
  665. }
  666. data[i]=tmp;
  667. Sort_Major(data,front,i-1);
  668. Sort_Major(data,i+1,rear);
  669. }
  670.  
  671. int Check_Number(Student data[],int menuflag)//按学号查询学生,二分查找
  672. {
  673. int length=Length_Student(data)-1;//获得内存结构体记录个数
  674. int front=0;//起始位置
  675. int rear=length;//末尾位置
  676. int mid;//中间点
  677. int flag=0;//指示查找是否成功
  678. int tmp;
  679. printf("\t\t\t\t请输入待查询学号(八位学号,输入-1返回上级菜单):");
  680. fflush(stdin);
  681. scanf("%d",&tmp);
  682. if(tmp==-1) return -1;//若输入-1,返回值为-1,返回上级菜单
  683. while(front<=rear)
  684. {
  685. mid=(front+rear)/2;//二分
  686. if(tmp<data[mid].num)//目标值在前一半
  687. rear=mid-1;//末尾位置置为二分前一个位置
  688. else if(tmp>data[mid].num)//目标在后一半
  689. front=mid+1;//起始置为二分后一个位置
  690. else if(tmp==data[mid].num)//找到目标值
  691. {
  692. flag=1;//指示找到目标值
  693. return mid;//若查找成功,返回值为目标位置
  694. }
  695. }
  696. if(flag==0)//未找到目标值
  697. {
  698. printf("\t\t\t\t非法输入或学号不存在!\n");
  699. int check=Check_Number(data,menuflag);//递归,将内层的返回值传出外层函数
  700. return check;//返回值为目标位置
  701. }
  702. }
  703.  
  704. void Check_Name(Student data[],int menuflag)//按专业查询学生,menuflag指示上级菜单
  705. {
  706. int length=Length_Student(data)-1;//获得记录个数
  707. int flag=0;
  708. char tmp[10];
  709. printf("\t\t\t\t请输入待查询姓名(中文名,输入-1返回上级菜单):");
  710. scanf("%s",tmp);
  711. if(strcmp(tmp,"-1")==0&&menuflag==1) Menu_Check(data,menuflag);//menuflag为1,返回查询与显示的子菜单
  712. if(strcmp(tmp,"-1")==0&&menuflag==0) Menu_Admin(data);//menuflag为0,返回管理员主菜单
  713. for(int i=0;i<=length;i++)
  714. {
  715. if(strcmp(data[i].name,tmp)==0)//找到目标记录
  716. {
  717. flag=1;//指示找到目标记录
  718. Show_Student(data,i);//展示目标记录详细信息
  719. }
  720. }
  721. if(flag==0)//未找到目标记录
  722. {
  723. printf("\t\t\t\t非法输入或姓名不存在!\n");
  724. Check_Name(data,menuflag);//递归
  725. }
  726. return;
  727. }
  728.  
  729. void Check_Grade(Student data[],int menuflag)//按年级查询学生
  730. {
  731. int length=Length_Student(data)-1;
  732. int flag=0;
  733. int tmp;
  734. printf("\t\t\t\t请输入待查询年级(四位年级,输入-1返回上级菜单):");
  735. fflush(stdin);
  736. scanf("%d",&tmp);
  737. if(tmp==-1) Menu_Check(data,menuflag);
  738. for(int i=0;i<=length;i++)
  739. {
  740. if(data[i].num/10000==tmp)
  741. {
  742. Show_Student(data,i);
  743. flag=1;
  744. if(data[i].num/10000!=data[i+1].num/10000) break;
  745. //按照学号顺序排序,下一个位置的年级与此位置年级不同时,同一个年级的记录已经全部展示
  746. }
  747.  
  748. }
  749. if(flag==0)
  750. {
  751. printf("\t\t\t\t非法输入或年级不存在!\n");
  752. Check_Grade(data,menuflag);
  753. }
  754. }
  755.  
  756. void Check_Class(Student data[],int menuflag)//按班级查询学生
  757. {
  758. int length=Length_Student(data)-1;
  759. int flag=0;
  760. int tmp;
  761. printf("\t\t\t\t请输入待查询班级(四位班号,输入-1返回上级菜单):");
  762. fflush(stdin);
  763. scanf("%d",&tmp);
  764. if(tmp==-1) Menu_Check(data,menuflag);
  765. for(int i=0;i<=length;i++)
  766. {
  767. if((data[i].num/100)%10000==tmp)
  768. {
  769. Show_Student(data,i);
  770. flag=1;
  771. if((data[i].num/100)%10000!=(data[i+1].num/100)%10000) break;
  772. }
  773. }
  774. if(flag==0)
  775. {
  776. printf("\t\t\t\t非法输入或班级不存在!\n");
  777. Check_Class(data,menuflag);
  778. }
  779. }
  780.  
  781. void Check_Major(Student data[],int menuflag)//按专业查询学生
  782. {
  783. int length=Length_Student(data)-1;
  784. int flag=0;
  785. char tmp[20];
  786. printf("\t\t\t\t请输入待查询专业\n\t\t\t\t(信息与计算科学/信息安全/计算机科学与技术/信息管理与信息系统/电子信息工程/通信工程/行政管理/保密管理,输入-1返回上级菜单):");
  787. scanf("%s",tmp);
  788. if(strcmp(tmp,"-1")==0) Menu_Check(data,menuflag);
  789. for(int i=0;i<=length;i++)
  790. {
  791. if(strcmp(data[i].major,tmp)==0)
  792. {
  793. flag=1;
  794. Show_Student(data,i);
  795. }
  796. }
  797. if(flag==0)
  798. {
  799. printf("\t\t\t\t非法输入或专业不存在!\n");
  800. Check_Major(data,menuflag);
  801. }
  802. }
  803.  
  804. void Check_Origin(Student data[],int menuflag)//按生源地查询学生
  805. {
  806. int length=Length_Student(data)-1;
  807. int flag=0;
  808. char origin[20];
  809. printf("\t\t\t\t请输入待查询生源地(省份名称,输入-1返回上级菜单):");
  810. scanf("%s",origin);
  811. if(strcmp(origin,"-1")==0) Menu_Check(data,menuflag);
  812. for(int i=0;i<=length;i++)
  813. {
  814. if(strcmp(data[i].origin,origin)==0)
  815. {
  816. flag=1;
  817. Show_Student(data,i);
  818. }
  819. }
  820. if(flag==0){
  821. printf("\t\t\t\t非法输入或生源地不存在!\n");
  822. Check_Origin(data,menuflag);
  823. }
  824. }
  825.  
  826. void Check_Ethnic(Student data[],int menuflag)//按民族查询学生
  827. {
  828. int length=Length_Student(data)-1;
  829. int flag=0;
  830. char ethnic[20];
  831. printf("\t\t\t\t请输入待查询民族(民族名称,输入-1返回上级菜单):");
  832. scanf("%s",ethnic);
  833. if(strcmp(ethnic,"-1")==0) Menu_Check(data,menuflag);
  834. for(int i=0;i<=length;i++)
  835. {
  836. if(strcmp(data[i].ethnic,ethnic)==0)
  837. {
  838. flag=1;
  839. Show_Student(data,i);
  840. }
  841. }
  842. if(flag==0)
  843. {
  844. printf("\t\t\t\t非法输入或民族不存在!\n");
  845. Check_Ethnic(data,menuflag);
  846. }
  847. }
  848.  
  849. void Check_Politic(Student data[],int menuflag)//按政治面貌查询学生
  850. {
  851. int length=Length_Student(data)-1;
  852. int flag=0;
  853. char politic[20];
  854. printf("\t\t\t\t请输入政治面貌\n\t\t\t\t(群众/无党派人士/共青团员/入党积极分子/中共预备党员/中共党员,输入-1返回上级菜单):");
  855. scanf("%s",politic);
  856. if(strcmp(politic,"-1")==0) Menu_Check(data,menuflag);
  857. for(int i=0;i<=length;i++)
  858. {
  859. if(strcmp(data[i].politic,politic)==0)
  860. {
  861. flag=1;
  862. Show_Student(data,i);
  863. }
  864. }
  865. if(flag==0)
  866. {
  867. printf("\t\t\t\t非法输入!\n");
  868. Check_Politic(data,menuflag);
  869. }
  870. }
  871.  
  872. void Check_Sex(Student data[],int menuflag)//按性别查询学生
  873. {
  874. int length=Length_Student(data)-1;
  875. int flag=0;
  876. char sex[20];
  877. printf("\t\t\t\t请输入待查询性别(男/女,输入-1返回上级菜单):");
  878. scanf("%s",sex);
  879. if(strcmp(sex,"-1")==0) Menu_Check(data,menuflag);
  880. for(int i=0;i<=length;i++)
  881. {
  882. if(strcmp(data[i].sex,sex)==0)
  883. {
  884. flag=1;
  885. Show_Student(data,i);
  886. }
  887. }
  888. if(flag==0)
  889. {
  890. printf("\t\t\t\t非法输入!\n");
  891. Check_Sex(data,menuflag);
  892. }
  893. }
  894.  
  895. void Check_Income(Student data[],int menuflag)//按家庭收入查询学生
  896. {
  897. int length=Length_Student(data)-1;
  898. int flag=0;//指示是否找到记录
  899. int minincome=-2,maxincome=100000;
  900. fflush(stdin);
  901. printf("\t\t\t\t请输入待查询家庭收入最低值:");
  902. scanf("%d",&minincome);//输入家庭收入最低值
  903. if(minincome==-1)
  904. {
  905. Menu_Check(data,menuflag);//输入-1返回上级菜单
  906. return;
  907. }
  908. else if(minincome<0||minincome>99999)//输入越界
  909. {
  910. printf("\t\t\t\t非法输入!\n");
  911. Check_Income(data,menuflag);//递归
  912. return;
  913. }
  914. fflush(stdin);
  915. printf("\t\t\t\t请输入待查询家庭收入最高值:");
  916. scanf("%d",&maxincome);//输入家庭收入最高值
  917. if(maxincome==-1)
  918. {
  919. Menu_Check(data,menuflag);//输入-1返回上级菜单
  920. return;
  921. }
  922. else if(maxincome<minincome||maxincome<0||maxincome>99999)
  923. //家庭收入最高值<家庭收入最低值,汇报错误
  924. //输入越界也报错
  925. {
  926. printf("\t\t\t\t非法输入!\n");
  927. Check_Income(data,menuflag);//递归
  928. return;
  929. }
  930. for(int i=0;i<=length;i++)//输入正确,查找家庭收入在范围内的记录
  931. if(data[i].income<=maxincome&&data[i].income>=minincome)
  932. {
  933. Show_Student(data,i);
  934. flag=1;
  935. }
  936. if(flag==0) printf("\t\t\t\t未找到记录!\n");
  937. }
  938.  
  939. void Check_Chinese(Student data[],int menuflag)//按语文成绩查询学生
  940. {
  941. int length=Length_Student(data)-1;
  942. int flag=0;
  943. int minchinese=-2,maxchinese=151;
  944. char major[20];
  945. fflush(stdin);
  946. printf("\t\t\t\t请输入待查询语文成绩最低值:");
  947. scanf("%d",&minchinese);
  948. if(minchinese==-1)
  949. {
  950. Menu_Check(data,menuflag);
  951. return;
  952. }
  953. else if(minchinese<0||minchinese>150)//输入越界
  954. {
  955. printf("\t\t\t\t非法输入!\n");
  956. Check_Chinese(data,menuflag);//递归
  957. return;
  958. }
  959. fflush(stdin);
  960. printf("\t\t\t\t请输入待查询语文成绩最高值:");
  961. scanf("%d",&maxchinese);
  962. if(maxchinese==-1)
  963. {
  964. Menu_Check(data,menuflag);
  965. return;
  966. }
  967. else if(maxchinese<minchinese||maxchinese<0||maxchinese>150)
  968. {
  969. printf("\t\t\t\t非法输入!\n");
  970. Check_Chinese(data,menuflag);
  971. return;
  972. }
  973. for(int i=0;i<=length;i++)
  974. if(data[i].score[0]<=maxchinese&&data[i].score[0]>=minchinese)
  975. {
  976. Show_Student(data,i);
  977. flag=1;
  978. }
  979. if(flag==0) printf("\t\t\t\t未找到记录!\n");
  980. }
  981.  
  982. void Check_Math(Student data[],int menuflag)//按数学成绩查询学生
  983. {
  984. int length=Length_Student(data)-1;
  985. int flag=0;
  986. int minmath=-2,maxmath=151;
  987. char major[20];
  988. fflush(stdin);
  989. printf("\t\t\t\t请输入待查询数学成绩最低值:");
  990. scanf("%d",&minmath);
  991. if(minmath==-1)
  992. {
  993. Menu_Check(data,menuflag);
  994. return;
  995. }
  996. else if(minmath<0||minmath>150)
  997. {
  998. printf("\t\t\t\t非法输入!\n");
  999. Check_Chinese(data,menuflag);
  1000. return;
  1001. }
  1002. fflush(stdin);
  1003. printf("\t\t\t\t请输入待查询数学成绩最高值:");
  1004. scanf("%d",&maxmath);
  1005. if(maxmath==-1)
  1006. {
  1007. Menu_Check(data,menuflag);
  1008. return;
  1009. }
  1010. else if(maxmath<minmath||maxmath<0||maxmath>150)
  1011. {
  1012. printf("\t\t\t\t非法输入!\n");
  1013. Check_Math(data,menuflag);
  1014. return;
  1015. }
  1016. for(int i=0;i<=length;i++)
  1017. if(data[i].score[1]<=maxmath&&data[i].score[1]>=minmath)
  1018. {
  1019. Show_Student(data,i);
  1020. flag=0;
  1021. }
  1022. if(flag==0) printf("\t\t\t\t未找到记录!\n");
  1023. }
  1024.  
  1025. void Check_English(Student data[],int menuflag)//按英语成绩查询学生
  1026. {
  1027. int length=Length_Student(data)-1;
  1028. int flag=0;
  1029. int minenglish=-2,maxenglish=151;
  1030. char major[20];
  1031. fflush(stdin);
  1032. printf("\t\t\t\t请输入待查询英语成绩最低值:");
  1033. scanf("%d",&minenglish);
  1034. if(minenglish==-1)
  1035. {
  1036. Menu_Check(data,menuflag);
  1037. return;
  1038. }
  1039. else if(minenglish<0||minenglish>150)
  1040. {
  1041. printf("\t\t\t\t非法输入!\n");
  1042. Check_English(data,menuflag);
  1043. return;
  1044. }
  1045. fflush(stdin);
  1046. printf("\t\t\t\t请输入待查询英语成绩最高值:");
  1047. scanf("%d",&maxenglish);
  1048. if(maxenglish==-1)
  1049. {
  1050. Menu_Check(data,menuflag);
  1051. return;
  1052. }
  1053. else if(maxenglish<minenglish||maxenglish<0||maxenglish>150)
  1054. {
  1055. printf("\t\t\t\t非法输入!\n");
  1056. Check_English(data,menuflag);
  1057. return;
  1058. }
  1059. for(int i=0;i<=length;i++)
  1060. if(data[i].score[2]<=maxenglish&&data[i].score[2]>=minenglish)
  1061. {
  1062. Show_Student(data,i);
  1063. flag=1;
  1064. }
  1065. if(flag==0) printf("\t\t\t\t未找到记录!\n\t\t\t\t");
  1066. }
  1067.  
  1068. void Check_Compre(Student data[],int menuflag)//按综合成绩查询学生
  1069. {
  1070. int length=Length_Student(data)-1;
  1071. Sort_Number(data,0,length);
  1072. int flag=0;
  1073. int mincompre=-2,maxcompre=301;
  1074. char major[20];
  1075. fflush(stdin);
  1076. printf("\t\t\t\t请输入待查询综合成绩最低值:");
  1077. scanf("%d",&mincompre);
  1078. if(mincompre==-1)
  1079. {
  1080. Menu_Check(data,menuflag);
  1081. return;
  1082. }
  1083. else if(mincompre<0||mincompre>150)
  1084. {
  1085. printf("\t\t\t\t非法输入!\n");
  1086. Check_Compre(data,menuflag);
  1087. return;
  1088. }
  1089. fflush(stdin);
  1090. printf("\t\t\t\t请输入待查询综合成绩最高值:");
  1091. scanf("%d",&maxcompre);
  1092. if(maxcompre==-1)
  1093. {
  1094. Menu_Check(data,menuflag);
  1095. return;
  1096. }
  1097. else if(maxcompre<mincompre||maxcompre<0||maxcompre>750)
  1098. {
  1099. printf("\t\t\t\t非法输入!\n");
  1100. Check_Compre(data,menuflag);
  1101. return;
  1102. }
  1103. for(int i=0;i<=length;i++)
  1104. if(data[i].score[3]<=maxcompre&&data[i].score[3]>=mincompre)
  1105. {
  1106. Show_Student(data,i);
  1107. flag=1;
  1108. }
  1109. if(flag==0) printf("\t\t\t\t未找到记录!\n\t\t\t\t");
  1110. }
  1111.  
  1112. void Check_Score(Student data[],int menuflag)//按入学总成绩查询学生
  1113. {
  1114. int length=Length_Student(data)-1;
  1115. Sort_Number(data,0,length);
  1116. int flag=0;
  1117. int minscore=-2,maxscore=751;
  1118. char major[20];
  1119. fflush(stdin);
  1120. printf("\t\t\t\t请输入待查询总入学成绩最低值:");
  1121. scanf("%d",&minscore);
  1122. if(minscore==-1)
  1123. {
  1124. Menu_Check(data,menuflag);
  1125. return;
  1126. }
  1127. else if(minscore<0||minscore>750)
  1128. {
  1129. printf("\t\t\t\t非法输入!\n");
  1130. Check_Score(data,menuflag);
  1131. return;
  1132. }
  1133. fflush(stdin);
  1134. printf("\t\t\t\t请输入待查询总入学成绩最高值:");
  1135. scanf("%d",&maxscore);
  1136. if(maxscore==-1)
  1137. {
  1138. Menu_Check(data,menuflag);
  1139. return;
  1140. }
  1141. if(maxscore<minscore||maxscore<0||maxscore>750)
  1142. {
  1143. printf("\t\t\t\t非法输入!\n");
  1144. Check_Score(data,menuflag);
  1145. return;
  1146. }
  1147. for(int i=0;i<=length;i++)
  1148. if(data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]<=maxscore&&
  1149. data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]>=minscore)
  1150. {
  1151. Show_Student(data,i);
  1152. flag=1;
  1153. }
  1154. if(flag==0) printf("\t\t\t\t未找到记录!\n\t\t\t\t");
  1155. }
  1156.  
  1157. void Count_Class_Score(Student data[],int menuflag)//按班级,统计分数情况
  1158. {
  1159. int MaxChinese=0,MaxMath=0,MaxEnglish=0,MaxCompre=0;//各个成绩最值初始化
  1160. int MinChinese=150,MinMath=150,MinEnglish=150,MinCompre=300;
  1161. int classnum;//待查询的班号
  1162. int classflag=0;//指示班号是否找到
  1163. int classsize=0;//班级人数
  1164. int length=Length_Student(data);//统计记录总数
  1165. double classavg;//班级平均分
  1166. printf("\t\t\t\t请输入待查询班级(四位班号,输入-1返回上级菜单):");
  1167. fflush(stdin);
  1168. scanf("%d",&classnum);
  1169. if(classnum==-1) Menu_Count(data,menuflag);//输入-1返回上级菜单
  1170. for(int i=0;i<=length;i++)
  1171. {
  1172. if((data[i].num/100)%10000==classnum)//找到待查询班号
  1173. {
  1174. printf("\t\t\t\t#学号:%d\t姓名:%s\t入学成绩:%.2lf\n",data[i].num,data[i].name,data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]);
  1175. //展示班级学生入学总成绩
  1176. classflag=1;//指示待查询班级找到
  1177. classsize++;//统计班级人数
  1178. classavg=classavg+data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3];//班级入学总成绩累加
  1179. if(data[i].score[0]>MaxChinese) MaxChinese=data[i].score[0];//比较查找各科最值
  1180. if(data[i].score[0]<MinChinese) MinChinese=data[i].score[0];
  1181. if(data[i].score[1]>MaxMath) MaxMath=data[i].score[1];
  1182. if(data[i].score[1]<MinMath) MinMath=data[i].score[1];
  1183. if(data[i].score[2]>MaxEnglish) MaxEnglish=data[i].score[2];
  1184. if(data[i].score[2]<MinEnglish) MinEnglish=data[i].score[2];
  1185. if(data[i].score[3]>MaxCompre) MaxCompre=data[i].score[3];
  1186. if(data[i].score[3]<MinCompre) MinCompre=data[i].score[3];
  1187. }
  1188. }
  1189. classavg/=classsize;//入学总成绩总和/班级人数=入学总成绩平均值
  1190. if(classflag==1)
  1191. {
  1192. printf("\n\t\t\t\t#语文最高成绩=%d\t语文最低成绩=%d\n\t\t\t\t#数学最高成绩=%d\t数学最低成绩=%d\n",MaxChinese,MinChinese,MaxMath,MinMath);
  1193. printf("\t\t\t\t#英语最高成绩=%d\t英语最低成绩=%d\n\t\t\t\t#综合最高成绩=%d\t综合最低成绩=%d\n",MaxEnglish,MinEnglish,MaxCompre,MinCompre);
  1194. printf("\t\t\t\t#平均入学成绩=%.2lf\n",classavg);
  1195. }
  1196. else//未找到待查询班号
  1197. {
  1198. printf("\t\t\t\t非法输入或班级不存在!\n");
  1199. Count_Class_Score(data,menuflag);//递归
  1200. }
  1201. }
  1202.  
  1203. void Count_Grade_Major(Student data[],int menuflag)//按年级,统计专业人数
  1204. {
  1205. int length=Length_Student(data);//记录个数
  1206. int grade;//待查询年级
  1207. int gradeflag=0;//指示是否找到待查询年级
  1208. int i,j,k;//循环用变量
  1209. char tmp[20];//记录已查询专业
  1210. printf("\t\t\t\t请输入待查询年级(四位年级,输入-1返回上级菜单):");
  1211. fflush(stdin);
  1212. scanf("%d",&grade);
  1213. if(grade==-1) Menu_Count(data,menuflag);//输入-1返回上级菜单
  1214. for(i=0;i<length;i++)
  1215. {
  1216. int count=0;
  1217. if(data[i].num/10000==grade&&strcmp(tmp,data[i].major)!=0)
  1218. //找到待查询年级,且专业非已查询过的专业,i指示未统计过的专业中待查询年级的第一个位置
  1219. {
  1220. gradeflag=1;//指示找到待查询年级
  1221. for(j=i;strcmp(data[i].major,data[j].major)==0;j++);
  1222. //循环,j指示未统计过的专业的最后一个位置的下一个位置
  1223. for(k=i;k<j;k++)
  1224. //k在i和j-1之间循环,即在未统计过的专业中待查询年级的第一个位置和未统计过的专业的最后一个位置之间循环
  1225. if(data[k].num/10000==data[i].num/10000)//符合待查询年级
  1226. count++;//计数
  1227. printf("\t\t\t\t#%d级%s专业共%d人\n",data[i].num/10000,data[i].major,count);
  1228. strcpy(tmp,data[i].major);//将未查询专业置为已查询专业
  1229. }
  1230. }
  1231. if(gradeflag==0)//待查询年级未找到
  1232. {
  1233. printf("\t\t\t\t非法输入或年级不存在!\n");
  1234. Count_Grade_Major(data,menuflag);
  1235. }
  1236. }
  1237.  
  1238. void Count_Class_Origin(Student data[],int menuflag)//按班级,统计省市人数
  1239. {
  1240. int length=Length_Student(data);
  1241. int classnum;
  1242. int classnumflag=0;
  1243. int i,j,k;
  1244. char tmp[20];
  1245. printf("\t\t\t\t请输入待查询班级(四位班号,输入-1返回上级菜单):");
  1246. fflush(stdin);
  1247. scanf("%d",&classnum);
  1248. if(classnum==-1) Menu_Count(data,menuflag);
  1249. for(i=0;i<length;i++)
  1250. {
  1251. int count=0;
  1252. if((data[i].num/100)%10000==classnum&&strcmp(tmp,data[i].origin)!=0)
  1253. {
  1254. classnumflag=1;
  1255. for(j=i;strcmp(data[i].origin,data[j].origin)==0;j++);
  1256. for(k=i;k<j;k++)
  1257. if((data[k].num/100)%10000==(data[i].num/100)%10000)
  1258. count++;
  1259. printf("\t\t\t\t#%d班%s人共%d人\n",data[i].num/100,data[i].origin,count);
  1260. strcpy(tmp,data[i].origin);
  1261. }
  1262. }
  1263. if(classnumflag==0)
  1264. {
  1265. printf("\t\t\t\t非法输入或班级不存在!\n");
  1266. Count_Class_Origin(data,menuflag);//递归
  1267. }
  1268. }
  1269.  
  1270. void Count_Grade_Ethnic(Student data[],int menuflag)//按年级,统计少数民族人数
  1271. {
  1272. int length=Length_Student(data);
  1273. int grade;
  1274. int gradeflag=0;
  1275. int i,j,k;
  1276. char tmp[20];
  1277. printf("\t\t\t\t请输入待查询年级(四位年级,输入-1返回上级菜单):");
  1278. fflush(stdin);
  1279. scanf("%d",&grade);
  1280. if(grade==-1) Menu_Count(data,menuflag);
  1281. for(int i=0;i<length;i++)
  1282. {
  1283. int count=0;
  1284. if(data[i].num/10000==grade&&strcmp(tmp,data[i].ethnic)!=0&&strcmp(data[i].ethnic,"汉族")!=0)
  1285. //不是汉族,即为少数民族
  1286. {
  1287. gradeflag=1;
  1288. for(j=i;strcmp(data[i].ethnic,data[j].ethnic)==0;j++);
  1289. for(k=i;k<j;k++)
  1290. if(data[k].num/10000==grade)
  1291. count++;
  1292. printf("\t\t\t\t#%d年级%s同胞共%d人\n",data[i].num/10000,data[i].ethnic,count);
  1293. strcpy(tmp,data[i].ethnic);
  1294. }
  1295. }
  1296. if(gradeflag==0)
  1297. {
  1298. printf("\t\t\t\t非法输入或年级不存在!\n");
  1299. Count_Grade_Ethnic(data,menuflag);
  1300. }
  1301. }
  1302.  
  1303. void Count_Major_Sex(Student data[],int menuflag)//按专业,统计年级男女分布
  1304. {
  1305. char major[20];
  1306. printf("\t\t\t\t请输入待查询专业\n\t\t\t\t(信息与计算科学/信息安全/计算机科学与技术/信息管理与信息系统/电子信息工程/通信工程/行政管理/保密管理,输入-1返回上级菜单):");
  1307. scanf("%s",major);
  1308. if(strcmp(major,"-1")==0) Menu_Count(data,menuflag);
  1309. int length=Length_Student(data);
  1310. int i,j;//循环用变量
  1311. int countmale,countfemale;//男女计数器
  1312. int majorflag=0;//指示专业是否找到
  1313. int grade;//指示正在查询的年级
  1314. for(i=0;i<length;i++)
  1315. {
  1316. countmale=0,countfemale=0;
  1317. if(data[i-1].num/10000!=data[i].num/10000)
  1318. //上一条记录的年级与此条记录的年级不同,i指示与i记录同年级的记录的起始位置
  1319. {
  1320. grade=data[i].num/10000;//正在查询的年级
  1321. for(j=i;j<length;j++)
  1322. {
  1323. if(data[j].num/10000!=grade) break; //若不是正在查询的年级,退出循环
  1324. if(strcmp(data[j].sex,"女")==0&&strcmp(data[j].major,major)==0) countfemale++;//找到女生,计数器自增
  1325. if(strcmp(data[j].sex,"男")==0&&strcmp(data[j].major,major)==0) countmale++;//找到男生,计数器自增
  1326. }
  1327. if(countmale!=0||countfemale!=0)//若找到男生或女生的记录
  1328. {
  1329. printf("\t\t\t\t#%s专业%d年级男生共%d人\n",major,data[i].num/10000,countmale);
  1330. printf("\t\t\t\t#%s专业%d年级女生共%d人\n",major,data[i].num/10000,countfemale);
  1331. majorflag=1;//指示专业找到
  1332. }
  1333. }
  1334. }
  1335. if(majorflag==0)
  1336. {
  1337. printf("\t\t\t\t非法输入或专业不存在!\n");
  1338. Count_Major_Sex(data,menuflag);//递归
  1339. }
  1340. }
  1341.  
  1342. void Count_Grade_ClassPoor(Student data[],int menuflag)
  1343. {
  1344. int grade;//待查询年级
  1345. printf("\t\t\t\t请输入待查年级(四位年级,输入-1返回上级菜单):");
  1346. fflush(stdin);
  1347. scanf("%d",&grade);
  1348. if(grade==-1) Menu_Count(data,menuflag);
  1349. int length=Length_Student(data);
  1350. int i,j,k;//循环用变量
  1351. int count;//计数器,统计收入低于班级平均人数
  1352. int flag=0;//指示是否找到
  1353. int tmp;//指示已查询班级
  1354. double incomeavg;//班级平均家庭收入
  1355. for(i=0;i<length;i++)
  1356. {
  1357. count=0;
  1358. incomeavg=0;
  1359. if(data[i].num/10000==grade&&tmp!=data[i].num/100)
  1360. //找到待查询年级,i指示待查询年级中未查询班级的起始位置
  1361. {
  1362. flag=1;//指示找到待查询年级
  1363. for(j=i;j<=length&&data[i].num/100==data[j].num/100;j++);
  1364. //循环,找到待查询年纪中该未查询班级的末尾位置
  1365. for(k=i;k<j;k++)//在该班级范围内查找
  1366. incomeavg+=data[k].income;//家庭收入累加
  1367. for(k=i;k<j;k++)
  1368. if(data[k].income<incomeavg/(j-i))//若学生家庭收入低于班级平均收入,计数器自增
  1369. count++;
  1370. printf("\t\t\t\t#%d班收入低于班级平均学生共%d人\n",data[i].num/100,count);
  1371. tmp=data[i].num/100;//为查询班级置为已查询班级
  1372. }
  1373. }
  1374. if(flag==0)
  1375. {
  1376. printf("\t\t\t\t非法输入或班级不存在!\n");
  1377. Count_Grade_ClassPoor(data,menuflag);
  1378. }
  1379. }
  1380.  
  1381. void Login(Student data[],int count)
  1382. {
  1383. system("color f0");//改变颜色
  1384. system("cls");
  1385. Print_Welcome();//展示欢迎字符画
  1386. char tmp[20];//记录输入的身份码
  1387. char code[2][20];//读入文件中的管理员身份码和用户身份码
  1388. FILE *fp=NULL;
  1389. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1390. printf("\t\t\t\t│ 欢迎使用 │\n");
  1391. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1392. printf("\t\t\t\t请输入身份码(普通用户/管理员):");
  1393. int i=0;
  1394. char ch;
  1395. while((ch=getch())!='\r')
  1396. {
  1397. if(ch=='\n') break;
  1398. if(ch=='\b')
  1399. {
  1400. i--;
  1401. printf("\b \b");
  1402. }
  1403. else
  1404. {
  1405. tmp[i++]=ch;
  1406. putchar('*');
  1407. }
  1408. }
  1409. tmp[i]='\0';
  1410. fp=fopen("code.txt","r");//从文件读取管理员身份码和用户身份码
  1411. fscanf(fp,"%s",code[0]);//普通用户
  1412. fscanf(fp,"%s",code[1]);//管理员
  1413. fclose(fp);//关闭文件
  1414. if(strcmp(tmp,code[1])==0)//若输入正确的管理员身份码
  1415. {
  1416. printf("\n\n\t\t\t\t以管理员身份使用系统...\n\t\t\t\t");
  1417. system("pause");
  1418. memset(data,0,sizeof(Student)*500);//将结构体数据归零
  1419. Initialize_Student(data);//初始化
  1420. Menu_Admin(data);//进入管理员主菜单
  1421. }
  1422. else if(strcmp(tmp,code[0])==0)//若输入正确的普通用户身份码
  1423. {
  1424. printf("\n\n\t\t\t\t以普通用户身份使用系统...\n\t\t\t\t");
  1425. system("pause");
  1426. memset(data,0,sizeof(Student)*500);
  1427. Initialize_Student(data);
  1428. Menu_User(data);
  1429. }
  1430. else
  1431. {
  1432. count--;//输入错误次数的计数器
  1433. if(count!=0)//若剩余错误次数
  1434. {
  1435. printf("\n\t\t\t\t身份码不可用,还可以尝试%d次...\n\t\t\t\t",count);
  1436. system("pause");
  1437. Login(data,count);//递归
  1438. }
  1439. else if(count==0)//若无剩余错误次数
  1440. {
  1441. printf("\n\t\t\t\t身份码不可用...\n");
  1442. exit(0);//结束程序
  1443. }
  1444. }
  1445. }
  1446.  
  1447. void Change_Code(Student data[])
  1448. {
  1449. char tmp[2][20];
  1450. FILE *fp=NULL;
  1451. system("cls");
  1452. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1453. printf("\t\t\t\t│ 更改身份码 │\n");
  1454. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1455. printf("\t\t\t\t请输入新的普通用户身份码(18位以内,输入-1返回上级菜单):");
  1456. scanf("%s",tmp[0]);
  1457. if(strcmp(tmp[0],"-1")==0) Menu_Admin(data);
  1458. else if(strlen(tmp[0])>18)
  1459. {
  1460. printf("\t\t\t\t身份码过长!\n\t\t\t\t");
  1461. system("pause");
  1462. Change_Code(data);
  1463. }
  1464. printf("\t\t\t\t请输入新的管理员身份码(20位以内,输入-1返回上级菜单):");
  1465. scanf("%s",tmp[1]);
  1466. if(strcmp(tmp[1],"-1")==0) Menu_Admin(data);
  1467. else if(strlen(tmp[1])>18) //输入身份码过长
  1468. {
  1469. printf("\t\t\t\t身份码过长!\n\t\t\t\t");
  1470. system("pause");
  1471. Change_Code(data);
  1472. return;
  1473. }
  1474. else if(strcmp(tmp[0],tmp[1])==0)
  1475. {
  1476. printf("\n\t\t\t\t身份码重用!\n\t\t\t\t");
  1477. system("pause");
  1478. Change_Code(data);
  1479. return;
  1480. }
  1481. fp=fopen("code.txt","w");//将新输入的身份码存入外存文件
  1482. fprintf(fp,"%s\n%s",tmp[0],tmp[1]);
  1483. fclose(fp);
  1484. printf("\n\t\t\t\t修改成功!\n\t\t\t\t");
  1485. system("pause");
  1486. Menu_Admin(data);//返回管理员主菜单
  1487. }
  1488.  
  1489. void Menu_Admin(Student stu[])
  1490. {
  1491. system("cls");
  1492. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1493. printf("\t\t\t\t│ 学生档案管理系统(管理员版) │\n");
  1494. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1495. printf("\t\t\t\t│ │\n");
  1496. printf("\t\t\t\t│ #1.新建学生档案 │\n");
  1497. printf("\t\t\t\t│ │\n");
  1498. printf("\t\t\t\t│ #2.删除/更改学生档案 │\n");
  1499. printf("\t\t\t\t│ │\n");
  1500. printf("\t\t\t\t│ #3.查询与显示 │\n");
  1501. printf("\t\t\t\t│ │\n");
  1502. printf("\t\t\t\t│ #4.统计与显示 │\n");
  1503. printf("\t\t\t\t│ │\n");
  1504. printf("\t\t\t\t│ #5.更改身份码 │\n");
  1505. printf("\t\t\t\t│ │\n");
  1506. printf("\t\t\t\t│ #0.保存并退出 │\n");
  1507. printf("\t\t\t\t│ │\n");
  1508. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1509. printf("\t\t\t\t#请键入功能编号:");
  1510. int n=-1;//初始置非法值
  1511. int check;
  1512. fflush(stdin);//清空缓存区,防止输入字符导致循环
  1513. scanf("%d",&n);
  1514. Student tmp;
  1515. FILE *fp;
  1516. switch(n)
  1517. {
  1518. case 0:
  1519. fp=fopen(stu[Length_Student(stu)].major, "w");//从结构体中读取文件名
  1520. Overwrite_Student(stu,fp);//将内存结构体中的记录写入外存文件
  1521. fclose(fp);
  1522. system("cls");
  1523. Print_End();//展示结束画面
  1524. exit(0);
  1525. case 1:
  1526. New_Student(&tmp,fp,stu);//调用创建新学生档案的子函数
  1527. system("pause");
  1528. Menu_Admin(stu);//创建新学生子函数结束,递归到管理员主菜单
  1529. break;
  1530. case 2:
  1531. if(Length_Student(stu)==0)//内存结构体中无记录,无法更改/删除
  1532. {
  1533. printf("\t\t\t\t数据源为空!\n\t\t\t\t");
  1534. system("pause");
  1535. Menu_Admin(stu);
  1536. break;
  1537. }
  1538. system("cls");
  1539. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1540. printf("\t\t\t\t│ 删除/更改学生档案 │\n");
  1541. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1542. Sort_Number(stu,0,Length_Student(stu)-1);
  1543. Check_Name(stu,0);
  1544. check=Check_Number(stu,1);
  1545. if(check==-1) Menu_Admin(stu);
  1546. else Menu_Change(tmp,stu,check);
  1547. break;
  1548. case 3:
  1549. if(Length_Student(stu)==0)//内存结构体中无记录,无法查询
  1550. {
  1551. printf("\t\t\t\t数据源为空!\n\t\t\t\t");
  1552. system("pause");
  1553. Menu_Admin(stu);
  1554. break;
  1555. }
  1556. Sort_Number(stu,0,Length_Student(stu)-1);//对学号进行快速排序
  1557. Menu_Check(stu,1);//指示从管理员主菜单调用,menuflag置1
  1558. break;
  1559. case 4:
  1560. if(Length_Student(stu)==0)//内存结构体中无记录,无法统计
  1561. {
  1562. printf("\t\t\t\t数据源为空!\n\t\t\t\t");
  1563. system("pause");
  1564. Menu_Admin(stu);
  1565. break;
  1566. }
  1567. Menu_Count(stu,1);//指示从管理员主菜单调用,menuflag置1
  1568. break;
  1569. case 5:
  1570. Change_Code(stu);
  1571. default:
  1572. printf("\t\t\t\t非法输入!\n\t\t\t\t");
  1573. system("pause");
  1574. Menu_Admin(stu);
  1575. break;
  1576. }
  1577. }
  1578.  
  1579. void Menu_User(Student stu[])
  1580. {
  1581. system("cls");
  1582. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1583. printf("\t\t\t\t│ 学生档案管理系统(用户版) │\n");
  1584. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1585. printf("\t\t\t\t│ │\n");
  1586. printf("\t\t\t\t│ #1.查询与显示 │\n");
  1587. printf("\t\t\t\t│ │\n");
  1588. printf("\t\t\t\t│ #2.统计与显示 │\n");
  1589. printf("\t\t\t\t│ │\n");
  1590. printf("\t\t\t\t│ #0.退出 │\n");
  1591. printf("\t\t\t\t│ │\n");
  1592. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1593. printf("\t\t\t\t#请键入功能编号:");
  1594. int n=-1;
  1595. fflush(stdin);//清空缓存区,防止输入字符导致循环
  1596. scanf("%d",&n);
  1597. switch(n)
  1598. {
  1599. case 0:
  1600. system("cls");
  1601. Print_End();
  1602. exit(0);
  1603. break;
  1604. case 1:
  1605. if(Length_Student(stu)==0)//内存结构体中无记录,无法查找
  1606. {
  1607. printf("\t\t\t\t数据源为空!\n\t\t\t\t");
  1608. system("pause");
  1609. Menu_Admin(stu);
  1610. break;
  1611. }
  1612. Sort_Number(stu,0,Length_Student(stu));
  1613. Menu_Check(stu,0);//指示从用户主菜单调用,menuflag置0
  1614. break;
  1615. case 2:
  1616. Menu_Count(stu,0);//指示从用户主菜单调用,menuflag置0
  1617. if(Length_Student(stu)==0)//内存结构体中无记录,无法查找
  1618. {
  1619. printf("\t\t\t\t数据源为空!\n\t\t\t\t");
  1620. system("pause");
  1621. Menu_Admin(stu);
  1622. break;
  1623. }
  1624. break;
  1625. default:
  1626. printf("\t\t\t\t非法输入!\n\t\t\t\t");
  1627. system("pause");
  1628. Menu_User(stu);
  1629. break;
  1630. }
  1631. }
  1632.  
  1633. void Menu_Change(Student data,Student stu[],int check)
  1634. {
  1635. system("cls");
  1636. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1637. printf("\t\t\t\t│ 删除/更改学生档案 │\n");
  1638. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1639. Show_Student(stu,check);
  1640. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1641. printf("\t\t\t\t│ │\n");
  1642. printf("\t\t\t\t│ #1.修改学生档案 │\n");
  1643. printf("\t\t\t\t│ │\n");
  1644. printf("\t\t\t\t│ #2.删除学生档案 │\n");
  1645. printf("\t\t\t\t│ │\n");
  1646. printf("\t\t\t\t│ #0.返回上级菜单 │\n");
  1647. printf("\t\t\t\t│ │\n");
  1648. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1649. printf("\t\t\t\t请键入功能编号:");
  1650. int n=-1;
  1651. fflush(stdin);
  1652. scanf("%d",&n);
  1653. FILE *fp;
  1654. switch(n)
  1655. {
  1656. case 0:
  1657. Menu_Admin(stu);
  1658. break;
  1659. case 1:
  1660. system("cls");
  1661. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1662. printf("\t\t\t\t│ 删除/更改学生档案 │\n");
  1663. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1664. Show_Student(stu,check);//展示待更改的学生记录
  1665. Change_Student(data,stu,check);
  1666. Menu_Change(data,stu,check);
  1667. break;
  1668. case 2:
  1669. Delete_Student(stu,check);
  1670. break;
  1671. default:
  1672. printf("\t\t\t\t非法输入!\n");
  1673. system("pause");
  1674. Menu_Change(data,stu,check);
  1675. break;
  1676. }
  1677. }
  1678.  
  1679. void Menu_Check(Student stu[],int menuflag)
  1680. {
  1681. system("cls");
  1682. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1683. printf("\t\t\t\t│ 查询与显示 │\n");
  1684. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1685. printf("\t\t\t\t│ │\n");
  1686. printf("\t\t\t\t│ #1.按学号查询学生档案 │\n");
  1687. printf("\t\t\t\t│ │\n");
  1688. printf("\t\t\t\t│ #2.按姓名查询学生档案 │\n");
  1689. printf("\t\t\t\t│ │\n");
  1690. printf("\t\t\t\t│ #3.按班级查询学生档案 │\n");
  1691. printf("\t\t\t\t│ │\n");
  1692. printf("\t\t\t\t│ #4.按年级查询学生档案 │\n");
  1693. printf("\t\t\t\t│ │\n");
  1694. printf("\t\t\t\t│ #5.按专业查询学生档案 │\n");
  1695. printf("\t\t\t\t│ │\n");
  1696. printf("\t\t\t\t│ #6.按生源地查询学生档案 │\n");
  1697. printf("\t\t\t\t│ │\n");
  1698. printf("\t\t\t\t│ #7.按民族查询学生档案 │\n");
  1699. printf("\t\t\t\t│ │\n");
  1700. printf("\t\t\t\t│ #8.按性别查询学生档案 │\n");
  1701. printf("\t\t\t\t│ │\n");
  1702. printf("\t\t\t\t│ #9.按政治面貌查询学生档案 │\n");
  1703. printf("\t\t\t\t│ │\n");
  1704. printf("\t\t\t\t│ #10.按家庭收入查询学生档案 │\n");
  1705. printf("\t\t\t\t│ │\n");
  1706. printf("\t\t\t\t│ #11.按语文成绩查询学生档案 │\n");
  1707. printf("\t\t\t\t│ │\n");
  1708. printf("\t\t\t\t│ #12.按数学成绩查询学生档案 │\n");
  1709. printf("\t\t\t\t│ │\n");
  1710. printf("\t\t\t\t│ #13.按英语成绩查询学生档案 │\n");
  1711. printf("\t\t\t\t│ │\n");
  1712. printf("\t\t\t\t│ #14.按综合成绩查询学生档案 │\n");
  1713. printf("\t\t\t\t│ │\n");
  1714. printf("\t\t\t\t│ #15.按入学总成绩查询学生档案 │\n");
  1715. printf("\t\t\t\t│ │\n");
  1716. printf("\t\t\t\t│ #0.返回上级菜单 │\n");
  1717. printf("\t\t\t\t│ │\n");
  1718. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1719. printf("\t\t\t\t请键入功能编号:");
  1720. int n=-1;
  1721. int check;
  1722. fflush(stdin);
  1723. scanf("%d",&n);
  1724. switch(n)
  1725. {
  1726. case 0:
  1727. if(menuflag==1) Menu_Admin(stu);//menuflag为1,指示从管理员主菜单调用
  1728. if(menuflag==0) Menu_User(stu);//menuflag为0,指示从用户主菜单调用
  1729. break;
  1730. case 1:
  1731. system("cls");
  1732. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1733. printf("\t\t\t\t│ 按学号查询学生档案 │\n");
  1734. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1735. check=Check_Number(stu,menuflag);
  1736. if(check==-1) Menu_Check(stu,menuflag);
  1737. else
  1738. {
  1739. Show_Student(stu,check);
  1740. printf("\t\t\t\t");
  1741. system("pause");
  1742. Menu_Check(stu,menuflag);
  1743. }
  1744. break;
  1745. case 2:
  1746. system("cls");
  1747. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1748. printf("\t\t\t\t│ 按姓名查询学生档案 │\n");
  1749. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1750. Check_Name(stu,menuflag);
  1751. printf("\t\t\t\t");
  1752. system("pause");
  1753. Menu_Check(stu,menuflag);
  1754. break;
  1755. case 3:
  1756. system("cls");
  1757. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1758. printf("\t\t\t\t│ 按班级查询学生档案 │\n");
  1759. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1760. Check_Class(stu,menuflag);
  1761. printf("\t\t\t\t");
  1762. system("pause");
  1763. Menu_Check(stu,menuflag);
  1764. break;
  1765. case 4:
  1766. system("cls");
  1767. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1768. printf("\t\t\t\t│ 按年级查询学生档案 │\n");
  1769. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1770. Check_Grade(stu,menuflag);
  1771. printf("\t\t\t\t");
  1772. system("pause");
  1773. Menu_Check(stu,menuflag);
  1774. break;
  1775. case 5:
  1776. system("cls");
  1777. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1778. printf("\t\t\t\t│ 按专业查询学生档案 │\n");
  1779. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1780. Check_Major(stu,menuflag);
  1781. printf("\t\t\t\t");
  1782. system("pause");
  1783. Menu_Check(stu,menuflag);
  1784. break;
  1785. case 6:
  1786. system("cls");
  1787. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1788. printf("\t\t\t\t│ 按生源地查询学生档案 │\n");
  1789. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1790. Check_Origin(stu,menuflag);
  1791. printf("\t\t\t\t");
  1792. system("pause");
  1793. Menu_Check(stu,menuflag);
  1794. break;
  1795. case 7:
  1796. system("cls");
  1797. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1798. printf("\t\t\t\t│ 按民族查询学生档案 │\n");
  1799. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1800. Check_Ethnic(stu,menuflag);
  1801. printf("\t\t\t\t");
  1802. system("pause");
  1803. Menu_Check(stu,menuflag);
  1804. break;
  1805. case 8:
  1806. system("cls");
  1807. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1808. printf("\t\t\t\t│ 按性别查询学生档案 │\n");
  1809. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1810. Check_Sex(stu,menuflag);
  1811. printf("\t\t\t\t");
  1812. system("pause");
  1813. Menu_Check(stu,menuflag);
  1814. break;
  1815. case 9:
  1816. system("cls");
  1817. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1818. printf("\t\t\t\t│ 按政治面貌查询学生档案 │\n");
  1819. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1820. Check_Politic(stu,menuflag);
  1821. printf("\t\t\t\t");
  1822. system("pause");
  1823. Menu_Check(stu,menuflag);
  1824. break;
  1825. case 10:
  1826. system("cls");
  1827. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1828. printf("\t\t\t\t│ 按家庭收入查询学生档案 │\n");
  1829. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1830. Check_Income(stu,menuflag);
  1831. printf("\t\t\t\t");
  1832. system("pause");
  1833. Menu_Check(stu,menuflag);
  1834. break;
  1835. case 11:
  1836. system("cls");
  1837. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1838. printf("\t\t\t\t│ 按语文成绩查询学生档案 │\n");
  1839. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1840. Check_Chinese(stu,menuflag);
  1841. printf("\t\t\t\t");
  1842. system("pause");
  1843. Menu_Check(stu,menuflag);
  1844. break;
  1845. case 12:
  1846. system("cls");
  1847. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1848. printf("\t\t\t\t│ 按数学成绩查询学生档案 │\n");
  1849. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1850. Check_Math(stu,menuflag);
  1851. printf("\t\t\t\t");
  1852. system("pause");
  1853. Menu_Check(stu,menuflag);
  1854. break;
  1855. case 13:
  1856. system("cls");
  1857. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1858. printf("\t\t\t\t│ 按英语成绩查询学生档案 │\n");
  1859. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1860. Check_English(stu,menuflag);
  1861. printf("\t\t\t\t");
  1862. system("pause");
  1863. Menu_Check(stu,menuflag);
  1864. break;
  1865. case 14:
  1866. system("cls");
  1867. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1868. printf("\t\t\t\t│ 按综合成绩查询学生档案 │\n");
  1869. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1870. Check_Compre(stu,menuflag);
  1871. printf("\t\t\t\t");
  1872. system("pause");
  1873. Menu_Check(stu,menuflag);
  1874. break;
  1875. case 15:
  1876. system("cls");
  1877. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1878. printf("\t\t\t\t│ 按总入学成绩查询学生档案 │\n");
  1879. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1880. Check_Score(stu,menuflag);
  1881. printf("\t\t\t\t");
  1882. system("pause");
  1883. Menu_Check(stu,menuflag);
  1884. break;
  1885. default:
  1886. printf("\t\t\t\t非法输入!\n\t\t\t\t");
  1887. system("pause");
  1888. Menu_Check(stu,menuflag);
  1889. break;
  1890. }
  1891. }
  1892.  
  1893. void Menu_Count(Student stu[],int menuflag)
  1894. {
  1895. system("cls");
  1896. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1897. printf("\t\t\t\t│ 统计与显示 │\n");
  1898. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1899. printf("\t\t\t\t│ │\n");
  1900. printf("\t\t\t\t│ #1.按班级统计分数情况 │\n");
  1901. printf("\t\t\t\t│ │\n");
  1902. printf("\t\t\t\t│ #2.按年级统计专业人数 │\n");
  1903. printf("\t\t\t\t│ │\n");
  1904. printf("\t\t\t\t│ #3.按班级统计省市人数 │\n");
  1905. printf("\t\t\t\t│ │\n");
  1906. printf("\t\t\t\t│ #4.按年级统计少数民族人数 │\n");
  1907. printf("\t\t\t\t│ │\n");
  1908. printf("\t\t\t\t│ #5.按专业统计男女人数 │\n");
  1909. printf("\t\t\t\t│ │\n");
  1910. printf("\t\t\t\t│ #6.按年级统计家庭收入低于平均人数 │\n");
  1911. printf("\t\t\t\t│ │\n");
  1912. printf("\t\t\t\t│ #0.返回上级菜单 │\n");
  1913. printf("\t\t\t\t│ │\n");
  1914. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1915. printf("\t\t\t\t请键入功能编号:");
  1916. int n=-1;
  1917. int length=Length_Student(stu)-1;
  1918. fflush(stdin);
  1919. scanf("%d",&n);
  1920. switch(n)
  1921. {
  1922. case 0:
  1923. if(menuflag==1) Menu_Admin(stu);
  1924. if(menuflag==0) Menu_User(stu);
  1925. break;
  1926. case 1:
  1927. system("cls");
  1928. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1929. printf("\t\t\t\t│ 按班级统计分数情况 │\n");
  1930. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1931. Sort_Number(stu,0,length);//对学号进行快速排序
  1932. Count_Class_Score(stu,menuflag);
  1933. printf("\t\t\t\t");
  1934. system("pause");
  1935. Menu_Count(stu,menuflag);
  1936. break;
  1937. case 2:
  1938. system("cls");
  1939. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1940. printf("\t\t\t\t│ 按年级统计专业人数 │\n");
  1941. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1942. Sort_Major(stu,0,length);//对专业进行快速排序
  1943. Count_Grade_Major(stu,menuflag);
  1944. printf("\t\t\t\t");
  1945. system("pause");
  1946. Menu_Count(stu,menuflag);
  1947. break;
  1948. case 3:
  1949. system("cls");
  1950. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1951. printf("\t\t\t\t│ 按班级统计省市人数 │\n");
  1952. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1953. Sort_Origin(stu,0,length);//对生源地进行快速排序
  1954. Count_Class_Origin(stu,menuflag);
  1955. printf("\t\t\t\t");
  1956. system("pause");
  1957. Menu_Count(stu,menuflag);
  1958. break;
  1959. case 4:
  1960. system("cls");
  1961. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1962. printf("\t\t\t\t│ 按年级统计少数民族人数 │\n");
  1963. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1964. Sort_Ethnic(stu,0,length);//对民族进行快速排序
  1965. Count_Grade_Ethnic(stu,menuflag);
  1966. printf("\t\t\t\t");
  1967. system("pause");
  1968. Menu_Count(stu,menuflag);
  1969. break;
  1970. case 5:
  1971. system("cls");
  1972. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1973. printf("\t\t\t\t│ 按专业统计男女人数 │\n");
  1974. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1975. Sort_Number(stu,0,length);
  1976. Count_Major_Sex(stu,menuflag);
  1977. printf("\t\t\t\t");
  1978. system("pause");
  1979. Menu_Count(stu,menuflag);
  1980. break;
  1981. case 6:
  1982. system("cls");
  1983. printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
  1984. printf("\t\t\t\t│ 按年级统计家庭收入低于平均人数 │\n");
  1985. printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
  1986. Sort_Number(stu,0,length);
  1987. Count_Grade_ClassPoor(stu,menuflag);
  1988. printf("\t\t\t\t");
  1989. system("pause");
  1990. Menu_Count(stu,menuflag);
  1991. break;
  1992. default:
  1993. printf("\t\t\t\t非法输入!\n\t\t\t\t");
  1994. system("pause");
  1995. Menu_Count(stu,menuflag);
  1996. break;
  1997. }
  1998. }
  1999.  
  2000. int main()
  2001. {
  2002. Student stu[500];
  2003. Login(stu,5);
  2004. return 0;
  2005. }

Test Blog的更多相关文章

  1. 日向blog开发记录

    一点历史关于,Sonne Blog 2016.03.25springmvc + hibernate框架搭建.2016.04.21日向blog首页.2016.04.24分页实现.2016.04.30登录 ...

  2. blog (后续更新)

    设计Model(设计数据库) from django.db import models # Create your models here. class BlogsPost(models.Model) ...

  3. tensorflow 一些好的blog链接和tensorflow gpu版本安装

    pading :SAME,VALID 区别  http://blog.csdn.net/mao_xiao_feng/article/details/53444333 tensorflow实现的各种算法 ...

  4. http://blog.csdn.net/java2000_wl/article/details/8627874

    http://blog.csdn.net/java2000_wl/article/details/8627874

  5. [Android Pro] http://blog.csdn.net/wuyinlei/article/category/5773375

    http://blog.csdn.net/wuyinlei/article/category/5773375

  6. android 蓝牙 http://blog.csdn.net/u012843100/article/details/52384219

    http://blog.csdn.net/u012843100/article/details/52384219

  7. 【三】用Markdown写blog的常用操作

    本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdown+ ...

  8. django开发个人简易Blog—nginx+uwsgin+django1.6+mysql 部署到CentOS6.5

    前面说完了此项目的创建及数据模型设计的过程.如果未看过,可以到这里查看,并且项目源码已经放大到github上,可以去这里下载. 代码也已经部署到sina sea上,地址为http://fengzhen ...

  9. 使用Hexo搭建专属Blog

    喜欢折腾的自己最开始在博客园有仿写几篇Blog,虽也可以自己改变风格,可是到底不是独立的一块儿地方,要知道独立的才是自己的;有属于自己独立的域名和Blog,真真是一件很爽的存在.在各种大牛的分享下在G ...

  10. First Blog

    俗话说“笨鸟先飞”,遗憾的是我这只笨鸟直到今天才意识到个人博客的重要性. 原来记录下学习生活中的每一丝领悟与思考,可以让个人内在,对知识的理解得到更好的升华. 有梦的人很美,追梦的人更美.像我的座右铭 ...

随机推荐

  1. VMware与Centos系统安装之重置root密码

    VMware与Centos系统安装之重置root密码   今日任务 1.Linux发行版的选择 2.vmware创建一个虚拟机(centos) 3.安装配置centos7 4.xshell配置连接虚拟 ...

  2. Pikachu-Unsafe Filedownload(不安全的文件下载)

    不安全的文件下载概述 文件下载功能在很多web系统上都会出现,一般我们当点击下载链接,便会向后台发送一个下载请求,一般这个请求会包含一个需要下载的文件名称,后台在收到请求后 会开始执行下载代码,将该文 ...

  3. ng-做一个简单的通讯录--学习使用路由和HTTP

    app.module import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@ang ...

  4. BZOJ 4238: 电压 DFS树

    分类讨论一下奇环和偶环的情况. code: #include <bits/stdc++.h> #define N 200006 #define setIO(s) freopen(s&quo ...

  5. P4883 mzf的考验[平衡树]

    P4883 mzf的考验 维护一种数据结构 支持区间翻转 区间异或 区间求和- 显然 fhq treap 区间异或显然是拆位 ~~然后复杂度*20~~ 第一次先遍历一下整棵树 pushup 一下 就可 ...

  6. 洛谷【P2022 有趣的数】 题解

    题目链接 https://www.luogu.org/problem/P2022 题目描述 让我们来考虑1到N的正整数集合.让我们把集合中的元素按照字典序排列,例如当N=11时,其顺序应该为:1,10 ...

  7. CTF长久练习平台

    0x01 XCTF(攻防世界) 攻防世界是ctf爱好者很喜欢的一个平台,不仅是界面风格像大型游戏闯关,里面的各类题目涵盖的ctf题型很广,还分为新手区和进阶区两块: 并且可以在里面组队,做一道题还有相 ...

  8. 在iOS下-input[disabled] 颜色变浅兼容&& input[readonly]仍可获取焦点解决方法

    目标:在写input输入框时,想让其只读不写. 环境:在iPhone上 本来用的时readonly,可是readonly,居然可以获取焦点,不能弹出键盘:安卓手机完全木有问题,所以去用了disable ...

  9. virtual box虚拟机跨物理机迁移

    VirtualBox保存虚机数据的是vdi文件,但是直接拷贝在新的VirtualBox中不能打开,因为每个vdi文件都包含了一个uuid的数据,如果直接拷贝,uuid在新的VirtualBox中是不能 ...

  10. reids中删除某个前缀的所有key

    需求:reids中删除某个前缀的所有key 说明:代码中的0:2标识从key前缀中截取前2个字符,这里示例的时候比如“b_”前缀,使用时候根据实际情况截取对应的长度进行判断即可. 生成测试数据 #!/ ...