Test Blog

计算机实习报告

姓名:王方正

学号:20174314

 

一、开发任务

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

二、需求分析

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

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

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

2)新增学生记录

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

4)删除指定学生记录

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

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

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

程序中有如下性能:

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

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

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

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

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

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

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

三、程序设计

针对需求做如下设计:

1. 数据结构设计

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

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

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系函数实现制定功能。

Test Blog_第1张图片

3. 主程序结构

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

四、程序实现

1void Print_Welcome()

 

 :无

返回值

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

void Print_Welcome()
{
	printf("\t\t\t\t          _______  _        _______  _______  _______  _______ \n");
	printf("\t\t\t\t|\\     /|(  ____ \\( \\      (  ____ \\(  ___  )(       )(  ____ \\\n");
	printf("\t\t\t\t| )   ( || (    \\/| (      | (    \\/| (   ) || () () || (    \\/\n");
	printf("\t\t\t\t| | _ | || (__    | |      | |      | |   | || || || || (__    \n");
	printf("\t\t\t\t| |( )| ||  __)   | |      | |      | |   | || |(_)| ||  __)   \n");
	printf("\t\t\t\t| || || || (      | |      | |      | |   | || |   | || (      \n");
	printf("\t\t\t\t| () () || (____/\\| (____/\\| (____/\\| (___) || )   ( || (____/\\\n");
	printf("\t\t\t\t(_______)(_______/(_______/(_______/(_______)|/     \\|(_______/\n\n");
}

 2void Printf_End()

  

 

返回值

  在控制台结束字符画的打印

void Print_End()//结束程序彩蛋
{
	system("color fc");
	printf("\t\t\t\t _______  _______  _______  ______   ______            _______ \n");
	printf("\t\t\t\t(  ____ \\(  ___  )(  ___  )(  __  \\ (  ___ \\ |\\     /|(  ____ \\\n");
	printf("\t\t\t\t| (    \\/| (   ) || (   ) || (  \\  )| (   ) )( \\   / )| (    \\/\n");
	printf("\t\t\t\t| |      | |   | || |   | || |   ) || (__/ /  \\ (_) / | (__    \n");
	printf("\t\t\t\t| | ____ | |   | || |   | || |   | ||  __ (    \\   /  |  __)   \n");
	printf("\t\t\t\t| | \\_  )| |   | || |   | || |   ) || (  \\ \\    ) (   | (      \n");
	printf("\t\t\t\t| (___) || (___) || (___) || (__/  )| )___) )   | |   | (____/\\\n");
	printf("\t\t\t\t(_______)(_______)(_______)(______/ |/ \\___/    \\_/   (_______/\n");
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 	printf("\t\t\t\t│                       感谢使用!!                        │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
}

3int Length_Student(Student data[])

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

 :无

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

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

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

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

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

 

返回值

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

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

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

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

  

返回值

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

void Overwrite_Student(Student data[],FILE *fp)//覆盖文件中的记录
{ 
	for(int i=0;i 
 

6void Initialize_Student(Student data[])

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

  

返回值

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

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

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

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

  

返回值:无

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

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

8void Get_Name(Student *data)

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

  :无

返回值

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

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

9void Get_Major(Student *data)

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

  :无

返回值

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

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

10void Get_Origin(Student *data)

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

  :无

返回值

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

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

11void Get_Sex(Student *data)

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

  :无

返回值

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

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

12void Get_Ethnic(Student *data)

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

  :无

返回值

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

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

13void Get_Politic(Student *data)

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

  :无

返回值

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

void Get_Politic(Student *data)
{
	printf("\t\t\t\t请输入政治面貌\n\t\t\t\t(群众/无党派人士/共青团员/入党积极分子/中共预备党员/中共党员,输入-1返回上级菜单):");
    int flag=0;
    char tmp[20];
    char politiclist[6][20]={"群众","无党派人士","共青团员","入党积极分子","中共预备党员","中共党员"};
	scanf("%s",tmp);
    if(strcmp(tmp,"-1")!=0)
	{
		for(int i=0;i<8;i++)
			if(strcmp(tmp,politiclist[i])==0)
			{
				flag=1;
				break;
			}
		if(flag==0)
		{
			printf("\t\t\t\t政治面貌输入错误!\n");
			Get_Politic(data);//递归 
			return;
		}
	}
	strcpy(data->politic,tmp);
	return;	
}

14void Get_Income(Student *data)

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

  :无

返回值

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

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

15void Get_Chinese(Student *data)

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

  :无

返回值

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

void Get_Chinese(Student *data)
{
    printf("\t\t\t\t请输入语文成绩(0~150,输入-1返回上级菜单):");
    double tmp=-2;//初始置非法值 
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>150)
		{
			printf("\t\t\t\t语文成绩输入错误!\n");
			Get_Chinese(data); 
			return;
		} 
	}
	data->score[0]=tmp;
}

16void Get_Math(Student *data)

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

  :无

返回值

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

void Get_Math(Student *data)
{
    printf("\t\t\t\t请输入数学成绩(0~150,输入-1返回上级菜单):");
    double tmp=-2;
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>150){
			printf("\t\t\t\t数学成绩输入错误!\n");
			Get_Math(data); 
			return;
		} 
	}
	data->score[1]=tmp;
}

17void Get_English(Student *data)

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

  :无

返回值

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

void Get_English(Student *data)
{
    printf("\t\t\t\t请输入英语成绩(0~150,输入-1返回上级菜单):");
    double tmp=-2;
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>150){
			printf("\t\t\t\t英语成绩输入错误!\n");
			Get_English(data); 
			return;
		} 
	}
	data->score[2]=tmp;
}

18void Get_Compre(Student *data)

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

  :无

返回值

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

void Get_Compre(Student *data)
{
    printf("\t\t\t\t请输入综合成绩(0~300,输入-1返回上级菜单):");
    double tmp=-2;
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>300)
		{
			printf("\t\t\t\t综合成绩输入错误!\n");
			Get_Compre(data); 
			return;
		} 
	}
	data->score[3]=tmp;
}

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

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

  

返回值

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

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

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

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

 出:无

返回值:无

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

void Delete_Student(Student data[],int i)//删除学生档案记录 
{ 
	printf("\n\t\t\t\t确认删除?(Y/N)");
	char ch;
	Student tmp;//临时结构体,传入更改学生档案函数,用于临时记录修改值 
	getchar();//清空字符缓冲区 
	scanf("%c",&ch);
	if(ch=='Y')
	{
		for(int j=i;j 
 

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

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

 出:无

返回值:无

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

void Change_Student(Student data,Student stu[],int i)//修改学生信息 
{ 
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #1.修改学号字段                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #2.修改姓名字段                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #3.修改专业字段                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #4.修改民族字段                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                    #5.修改生源地字段                      │\n");
    printf("\t\t\t\t│                                                           │\n"); 
    printf("\t\t\t\t│                     #6.修改性别字段                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                   #7.修改政治面貌字段                     │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                   #8.修改家庭收入字段                     │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                   #9.修改语文成绩字段                     │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                   #10.修改数学成绩字段                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                   #11.修改英语成绩字段                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                   #12.修改综合成绩字段                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #0.返回上级菜单                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
	printf("\t\t\t\t请键入功能编号:");
	int key=-1;//初始置非法值,防止输入字符产生错误 
	fflush(stdin);//清空缓存区 
	scanf("%d",&key);
	switch(key)
	{
		case 0:
			Menu_Change(data,stu,i);//取消修改操作,返回删除/更改子菜单,选择删除或更改的操作 
		case 1:
			Get_Number(&data,stu);//复用,获得学号 
			if(data.num!=-1)	stu[i].num=data.num;
			break;
		case 
			2:Get_Name(&data);
			if(strcmp(data.name,"-1")!=0)	strcpy(stu[i].name,data.name);
			break;
		case 3:
			Get_Major(&data);
			if(strcmp(data.major,"-1")!=0)	strcpy(stu[i].major,data.major);
			break;
		case 4:
			Get_Ethnic(&data);
			if(strcmp(data.ethnic,"-1")!=0)	strcpy(stu[i].ethnic,data.ethnic);
			break;
		case 5:
			Get_Origin(&data);
			if(strcmp(data.origin,"-1")!=0)	strcpy(stu[i].origin,data.origin);
			break;
		case 6:
			Get_Sex(&data);
			if(strcmp(data.sex,"-1")!=0)	strcpy(stu[i].sex,data.sex);
			break;
		case 7:
			Get_Politic(&data);
			if(strcmp(data.politic,"-1")!=0)	strcpy(stu[i].politic,data.politic);
			break;
		case 8:
			Get_Income(&data);
			if(data.income!=-1)	stu[i].income=data.income;
			break;
		case 9:
			Get_Chinese(&data);
			if(data.score[0]!=-1)	stu[i].score[0]=data.score[0];
			break;
		case 10:
			Get_Math(&data);
			if(data.score[1]!=-1)	stu[i].score[1]=data.score[1];
			break;
		case 11:
			Get_English(&data);
			if(data.score[2]!=-1)	stu[i].score[2]=data.score[2];
			break;
		case 12:
			Get_Compre(&data);
			if(data.score[3]!=-1)	stu[i].score[3]=data.score[3];
			break;
		default:
			printf("输入错误!");//非法输入的提示 
			Change_Student(data,stu,i);//递归跳转 
			break;
	}
	
}

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

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

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

返回值:无

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

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

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

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

 出:无

返回值:无

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

void Sort_Number(Student data[],int front,int rear)//对全部学生信息按学号快速排序 
{ 
    if(front>=rear) 
	{
        return;
    }
    int i=front;
    int j=rear;
    Student tmp=data[front];//轴 
    while(i=data[i].num)//找比轴大的记录 
		{
            i++;
        }
        data[j]=data[i];//放到轴后面 
    }
    data[i]=tmp;//轴置入中间 
    Sort_Number(data,front,i-1);//轴的前一半,递归 
    Sort_Number(data,i+1,rear);//轴的后一半,递归 
}

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

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

 出:无

返回值:无

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

void Sort_Origin(Student data[],int front,int rear)//对全部学生信息按生源地快速排序 
{ 
    if(front>=rear)
	{
        return;
    }
    int i=front;
    int j=rear;
    Student tmp=data[front];
    while(i=0)
		{
            i++;
        }
        data[j]=data[i];
    }
    data[i]=tmp;
    Sort_Origin(data,front,i-1);
    Sort_Origin(data,i+1,rear);
}

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

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

 出:无

返回值:无

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

void Sort_Ethnic(Student data[],int front,int rear)//对全部学生信息按民族快速排序 
{ 
    if(front>=rear)
	{
        return;
    }
    int i=front;
    int j=rear;
    Student tmp=data[front];
    while(i=0)
		{
            i++;
        }
        data[j]=data[i];
    }
    data[i]=tmp;
    Sort_Ethnic(data,front,i-1);
    Sort_Ethnic(data,i+1,rear);
}

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

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

 出:无

返回值:无

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

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

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

 出:无

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

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

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

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

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

返回值:无

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

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

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

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

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

返回值:无

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

int num=20174301;

int grade=num/10000;  //grade=2017

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

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

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

返回值:无

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

int num=20174301;

int classnum=(num/100)%10000;  //classnum=1743

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

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

返回值:无

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

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

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

 出:无

返回值:无

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

49void Change_Code(Student data[])

 入:新身份码

 出:无

返回值:无

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

50void Menu_Admin(Student stu[])

 入:菜单选项

 出:对应子菜单

返回值:无

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

51void Menu_User(Student stu[])

 入:菜单选项

 出:对应子菜单

返回值:无

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

52void Menu_Change(Student stu[])

 入:菜单选项

 出:对应子菜单

返回值:无

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

53void Menu_Check(Student stu[])

 入:菜单选项

 出:对应功能

返回值:无

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

54void Menu_Count(Student stu[])

 入:菜单选项

 出:对应功能

返回值:无

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

五、程序测试

 Test Blog_第2张图片

管理员登陆

 Test Blog_第3张图片

普通用户登陆

 Test Blog_第4张图片

登陆失败

 Test Blog_第5张图片

成功打开文件

 Test Blog_第6张图片

管理员主菜单

 Test Blog_第7张图片

普通用户主菜单

Test Blog_第8张图片

管理员主菜单边界

 Test Blog_第9张图片

新建学生边界

 Test Blog_第10张图片

删除/更改学生档案

Test Blog_第11张图片

10 更改名字

Test Blog_第12张图片

11 更改名字成功

 Test Blog_第13张图片

12 查询与显示

 Test Blog_第14张图片

13 查询边界

 Test Blog_第15张图片

14 统计与显示

 Test Blog_第16张图片

15 按班级统计分数情况

 Test Blog_第17张图片

16 按年级统计专业人数

 Test Blog_第18张图片

17 按班级统计省市人数

 Test Blog_第19张图片

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

 Test Blog_第20张图片

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

 Test Blog_第21张图片

20 更改身份码过长

 Test Blog_第22张图片

21 更改身份码重用

 Test Blog_第23张图片

22 结束字符画

六、设计小结

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

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

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

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

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

int num=20174314;

int grade=num/10000; //grade=2017

int classnum=num/100-200000 //classnum=17

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

int num=20174314;

int classnum=)num/100)%10000 //classnum=17

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

七、使用说明

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

八、附录

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

#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "conio.h"

//作者:20174314-王方正
//题目:《程序设计实践教程》教材22题 
//完成时间:2019年9月11日 
//指导老师:徐小青老师、李晓东老师

struct Student
{  
	int num;//学号
	char name[10];//姓名
	char major[20];//专业
	char origin[8];//生源地 
	char ethnic[12];//民族 
	char sex[3];//性别
	char politic[12];//政治面貌 
	double income;//家庭收入  
	double score[4];//学生成绩 
};

void Menu_Admin(Student stu[]);//管理员账号主菜单 
void Menu_User(Student stu[]);//用户账号主菜单 
void Menu_Change(Student data,Student stu[],int check);//删除/修改学生档案子菜单 
void Menu_Check(Student stu[],int menuflag);//查询与显示子菜单 
void Menu_Count(Student stu[],int menuflag);//统计与显示子菜单 

void Print_Welcome()
{
	printf("\t\t\t\t          _______  _        _______  _______  _______  _______ \n");
	printf("\t\t\t\t|\\     /|(  ____ \\( \\      (  ____ \\(  ___  )(       )(  ____ \\\n");
	printf("\t\t\t\t| )   ( || (    \\/| (      | (    \\/| (   ) || () () || (    \\/\n");
	printf("\t\t\t\t| | _ | || (__    | |      | |      | |   | || || || || (__    \n");
	printf("\t\t\t\t| |( )| ||  __)   | |      | |      | |   | || |(_)| ||  __)   \n");
	printf("\t\t\t\t| || || || (      | |      | |      | |   | || |   | || (      \n");
	printf("\t\t\t\t| () () || (____/\\| (____/\\| (____/\\| (___) || )   ( || (____/\\\n");
	printf("\t\t\t\t(_______)(_______/(_______/(_______/(_______)|/     \\|(_______/\n\n");
}

void Print_End()//结束程序彩蛋
{
	system("color fc");
	printf("\t\t\t\t _______  _______  _______  ______   ______            _______ \n");
	printf("\t\t\t\t(  ____ \\(  ___  )(  ___  )(  __  \\ (  ___ \\ |\\     /|(  ____ \\\n");
	printf("\t\t\t\t| (    \\/| (   ) || (   ) || (  \\  )| (   ) )( \\   / )| (    \\/\n");
	printf("\t\t\t\t| |      | |   | || |   | || |   ) || (__/ /  \\ (_) / | (__    \n");
	printf("\t\t\t\t| | ____ | |   | || |   | || |   | ||  __ (    \\   /  |  __)   \n");
	printf("\t\t\t\t| | \\_  )| |   | || |   | || |   ) || (  \\ \\    ) (   | (      \n");
	printf("\t\t\t\t| (___) || (___) || (___) || (__/  )| )___) )   | |   | (____/\\\n");
	printf("\t\t\t\t(_______)(_______)(_______)(______/ |/ \\___/    \\_/   (_______/\n");
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 	printf("\t\t\t\t│                       感谢使用!!                        │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
}

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

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

void Overwrite_Student(Student data[],FILE *fp)//覆盖文件中的记录
{ 
	for(int i=0;i2020)//超出学生年级范围
		{ 
			printf("\t\t\t\t学号输入错误!\n");
			Get_Number(data,stu);//递归 
			return;//函数此处结束 
		}
		for(int i=0;i<=length;i++)//在原学号库中查重 
		{ 
			if(stu[i].num==tmp)//输入学号重复 
			{ 
				printf("\t\t\t\t学号输入重复!\n");
				Get_Number(data,stu);//递归 
				return;//函数此处结束 
			}
		}
	}
	data->num=tmp;//最终将合法值或-1传入临时结构体 
	return;
}

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

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

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

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

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

void Get_Politic(Student *data)
{
	printf("\t\t\t\t请输入政治面貌\n\t\t\t\t(群众/无党派人士/共青团员/入党积极分子/中共预备党员/中共党员,输入-1返回上级菜单):");
    int flag=0;
    char tmp[20];
    char politiclist[6][20]={"群众","无党派人士","共青团员","入党积极分子","中共预备党员","中共党员"};
	scanf("%s",tmp);
    if(strcmp(tmp,"-1")!=0)
	{
		for(int i=0;i<8;i++)
			if(strcmp(tmp,politiclist[i])==0)
			{
				flag=1;
				break;
			}
		if(flag==0)
		{
			printf("\t\t\t\t政治面貌输入错误!\n");
			Get_Politic(data);//递归 
			return;
		}
	}
	strcpy(data->politic,tmp);
	return;	
}

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

void Get_Chinese(Student *data)
{
    printf("\t\t\t\t请输入语文成绩(0~150,输入-1返回上级菜单):");
    double tmp=-2;//初始置非法值 
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>150)
		{
			printf("\t\t\t\t语文成绩输入错误!\n");
			Get_Chinese(data); 
			return;
		} 
	}
	data->score[0]=tmp;
}

void Get_Math(Student *data)
{
    printf("\t\t\t\t请输入数学成绩(0~150,输入-1返回上级菜单):");
    double tmp=-2;
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>150){
			printf("\t\t\t\t数学成绩输入错误!\n");
			Get_Math(data); 
			return;
		} 
	}
	data->score[1]=tmp;
}

void Get_English(Student *data)
{
    printf("\t\t\t\t请输入英语成绩(0~150,输入-1返回上级菜单):");
    double tmp=-2;
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>150){
			printf("\t\t\t\t英语成绩输入错误!\n");
			Get_English(data); 
			return;
		} 
	}
	data->score[2]=tmp;
}

void Get_Compre(Student *data)
{
    printf("\t\t\t\t请输入综合成绩(0~300,输入-1返回上级菜单):");
    double tmp=-2;
    fflush(stdin);
	scanf("%lf",&tmp);
	if(tmp!=-1)
	{
		if(tmp<0||tmp>300)
		{
			printf("\t\t\t\t综合成绩输入错误!\n");
			Get_Compre(data); 
			return;
		} 
	}
	data->score[3]=tmp;
}

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

void Delete_Student(Student data[],int i)//删除学生档案记录 
{ 
	printf("\n\t\t\t\t确认删除?(Y/N)");
	char ch;
	Student tmp;//临时结构体,传入更改学生档案函数,用于临时记录修改值 
	getchar();//清空字符缓冲区 
	scanf("%c",&ch);
	if(ch=='Y')
	{
		for(int j=i;j=rear) 
	{
        return;
    }
    int i=front;
    int j=rear;
    Student tmp=data[front];//轴 
    while(i=data[i].num)//找比轴大的记录 
		{
            i++;
        }
        data[j]=data[i];//放到轴后面 
    }
    data[i]=tmp;//轴置入中间 
    Sort_Number(data,front,i-1);//轴的前一半,递归 
    Sort_Number(data,i+1,rear);//轴的后一半,递归 
}

void Sort_Origin(Student data[],int front,int rear)//对全部学生信息按生源地快速排序 
{ 
    if(front>=rear)
	{
        return;
    }
    int i=front;
    int j=rear;
    Student tmp=data[front];
    while(i=0)
		{
            i++;
        }
        data[j]=data[i];
    }
    data[i]=tmp;
    Sort_Origin(data,front,i-1);
    Sort_Origin(data,i+1,rear);
}

void Sort_Ethnic(Student data[],int front,int rear)//对全部学生信息按民族快速排序 
{ 
    if(front>=rear)
	{
        return;
    }
    int i=front;
    int j=rear;
    Student tmp=data[front];
    while(i=0)
		{
            i++;
        }
        data[j]=data[i];
    }
    data[i]=tmp;
    Sort_Ethnic(data,front,i-1);
    Sort_Ethnic(data,i+1,rear);
}

void Sort_Major(Student data[],int front,int rear)//对全部学生信息按民族快速排序 
{ 
    if(front>=rear)
	{
        return;
    }
    int i=front;
    int j=rear;
    char key[8];
	Student tmp=data[front];
    while(i=0)
		{
            i++;
        }
        data[j]=data[i];
    }
    data[i]=tmp;
    Sort_Major(data,front,i-1);
    Sort_Major(data,i+1,rear);
}

int Check_Number(Student data[],int menuflag)//按学号查询学生,二分查找 
{ 
	int length=Length_Student(data)-1;//获得内存结构体记录个数
	int front=0;//起始位置 
	int rear=length;//末尾位置 
	int mid;//中间点 
	int flag=0;//指示查找是否成功
	int tmp;
	printf("\t\t\t\t请输入待查询学号(八位学号,输入-1返回上级菜单):");
	fflush(stdin);
	scanf("%d",&tmp);
	if(tmp==-1)	return -1;//若输入-1,返回值为-1,返回上级菜单 
	while(front<=rear)
	{
		mid=(front+rear)/2;//二分 
		if(tmpdata[mid].num)//目标在后一半 
			front=mid+1;//起始置为二分后一个位置 
		else if(tmp==data[mid].num)//找到目标值 
		{
			flag=1;//指示找到目标值 
			return mid;//若查找成功,返回值为目标位置 
		}
	}
	if(flag==0)//未找到目标值 
	{
		printf("\t\t\t\t非法输入或学号不存在!\n");
		int check=Check_Number(data,menuflag);//递归,将内层的返回值传出外层函数 
		return check;//返回值为目标位置 
	}
}

void Check_Name(Student data[],int menuflag)//按专业查询学生,menuflag指示上级菜单 
{ 
	int length=Length_Student(data)-1;//获得记录个数 
	int flag=0;
	char tmp[10];
	printf("\t\t\t\t请输入待查询姓名(中文名,输入-1返回上级菜单):");
	scanf("%s",tmp);
	if(strcmp(tmp,"-1")==0&&menuflag==1)	Menu_Check(data,menuflag);//menuflag为1,返回查询与显示的子菜单 
	if(strcmp(tmp,"-1")==0&&menuflag==0)	Menu_Admin(data);//menuflag为0,返回管理员主菜单 
	for(int i=0;i<=length;i++)
	{
		if(strcmp(data[i].name,tmp)==0)//找到目标记录 
		{
			flag=1;//指示找到目标记录 
			Show_Student(data,i);//展示目标记录详细信息 
		}
	}
	if(flag==0)//未找到目标记录 
	{
		printf("\t\t\t\t非法输入或姓名不存在!\n"); 
		Check_Name(data,menuflag);//递归 
	}
	return;
}

void Check_Grade(Student data[],int menuflag)//按年级查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	int tmp;
	printf("\t\t\t\t请输入待查询年级(四位年级,输入-1返回上级菜单):");
	fflush(stdin);
	scanf("%d",&tmp);
	if(tmp==-1)	Menu_Check(data,menuflag);
	for(int i=0;i<=length;i++)
	{
		if(data[i].num/10000==tmp)
		{
			Show_Student(data,i);
			flag=1;
			if(data[i].num/10000!=data[i+1].num/10000)	break;
			//按照学号顺序排序,下一个位置的年级与此位置年级不同时,同一个年级的记录已经全部展示 
		}
		 
	}
	if(flag==0)
	{
		printf("\t\t\t\t非法输入或年级不存在!\n");
		Check_Grade(data,menuflag);
	}
}

void Check_Class(Student data[],int menuflag)//按班级查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	int tmp;
	printf("\t\t\t\t请输入待查询班级(四位班号,输入-1返回上级菜单):");
	fflush(stdin);
	scanf("%d",&tmp);
	if(tmp==-1)	Menu_Check(data,menuflag);
	for(int i=0;i<=length;i++)
	{
		if((data[i].num/100)%10000==tmp)
		{
			Show_Student(data,i);
			flag=1;
			if((data[i].num/100)%10000!=(data[i+1].num/100)%10000)	break;
		}
	}
	if(flag==0)
	{
		printf("\t\t\t\t非法输入或班级不存在!\n");
		Check_Class(data,menuflag);
	}
}

void Check_Major(Student data[],int menuflag)//按专业查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	char tmp[20];	
	printf("\t\t\t\t请输入待查询专业\n\t\t\t\t(信息与计算科学/信息安全/计算机科学与技术/信息管理与信息系统/电子信息工程/通信工程/行政管理/保密管理,输入-1返回上级菜单):");
	scanf("%s",tmp);
	if(strcmp(tmp,"-1")==0)	Menu_Check(data,menuflag);
	for(int i=0;i<=length;i++)
	{ 
		if(strcmp(data[i].major,tmp)==0)
		{
			flag=1;
			Show_Student(data,i);
		}
	} 
	if(flag==0)
	{
		printf("\t\t\t\t非法输入或专业不存在!\n"); 
		Check_Major(data,menuflag);
	}
}

void Check_Origin(Student data[],int menuflag)//按生源地查询学生 
{
	int length=Length_Student(data)-1;
	int flag=0;
	char origin[20];
	printf("\t\t\t\t请输入待查询生源地(省份名称,输入-1返回上级菜单):");
	scanf("%s",origin);
	if(strcmp(origin,"-1")==0)	Menu_Check(data,menuflag);
	for(int i=0;i<=length;i++)
	{
		if(strcmp(data[i].origin,origin)==0)
		{
			flag=1;
			Show_Student(data,i);
		}
	}
	if(flag==0){
		printf("\t\t\t\t非法输入或生源地不存在!\n"); 
		Check_Origin(data,menuflag);
	}
}

void Check_Ethnic(Student data[],int menuflag)//按民族查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	char ethnic[20];
	printf("\t\t\t\t请输入待查询民族(民族名称,输入-1返回上级菜单):");
	scanf("%s",ethnic);
	if(strcmp(ethnic,"-1")==0)	Menu_Check(data,menuflag);
	for(int i=0;i<=length;i++)
	{
		if(strcmp(data[i].ethnic,ethnic)==0)
		{
			flag=1;
			Show_Student(data,i);
		}
	}
	if(flag==0)
	{
		printf("\t\t\t\t非法输入或民族不存在!\n"); 
		Check_Ethnic(data,menuflag);
	}
}

void Check_Politic(Student data[],int menuflag)//按政治面貌查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	char politic[20];
	printf("\t\t\t\t请输入政治面貌\n\t\t\t\t(群众/无党派人士/共青团员/入党积极分子/中共预备党员/中共党员,输入-1返回上级菜单):");
	scanf("%s",politic);
	if(strcmp(politic,"-1")==0)	Menu_Check(data,menuflag);
	for(int i=0;i<=length;i++)
	{
		if(strcmp(data[i].politic,politic)==0)
		{
			flag=1;
			Show_Student(data,i);
		}
	}
	if(flag==0)
	{
		printf("\t\t\t\t非法输入!\n"); 
		Check_Politic(data,menuflag);
	}
}

void Check_Sex(Student data[],int menuflag)//按性别查询学生 
{
	int length=Length_Student(data)-1;
	int flag=0;
	char sex[20];
	printf("\t\t\t\t请输入待查询性别(男/女,输入-1返回上级菜单):");
	scanf("%s",sex);
	if(strcmp(sex,"-1")==0)	Menu_Check(data,menuflag);
	for(int i=0;i<=length;i++)
	{
		if(strcmp(data[i].sex,sex)==0)
		{
			flag=1;
			Show_Student(data,i);
		}
	}
	if(flag==0)
	{
		printf("\t\t\t\t非法输入!\n"); 
		Check_Sex(data,menuflag);
	}
}

void Check_Income(Student data[],int menuflag)//按家庭收入查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;//指示是否找到记录 
	int minincome=-2,maxincome=100000;
	fflush(stdin);
	printf("\t\t\t\t请输入待查询家庭收入最低值:");
	scanf("%d",&minincome);//输入家庭收入最低值 
	if(minincome==-1)
	{
		Menu_Check(data,menuflag);//输入-1返回上级菜单 
		return;
	}
	else if(minincome<0||minincome>99999)//输入越界 
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Income(data,menuflag);//递归 
		return;
	} 
	fflush(stdin);
	printf("\t\t\t\t请输入待查询家庭收入最高值:");
	scanf("%d",&maxincome);//输入家庭收入最高值 
	if(maxincome==-1)
	{
		Menu_Check(data,menuflag);//输入-1返回上级菜单 
		return;
	}
	else if(maxincome99999)
	//家庭收入最高值<家庭收入最低值,汇报错误 
	//输入越界也报错 
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Income(data,menuflag);//递归 
		return;
	} 
	for(int i=0;i<=length;i++)//输入正确,查找家庭收入在范围内的记录 
		if(data[i].income<=maxincome&&data[i].income>=minincome)
		{
			Show_Student(data,i);
			flag=1;
		}
	if(flag==0)	printf("\t\t\t\t未找到记录!\n");
}

void Check_Chinese(Student data[],int menuflag)//按语文成绩查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	int minchinese=-2,maxchinese=151;
	char major[20];
	fflush(stdin);
	printf("\t\t\t\t请输入待查询语文成绩最低值:");
	scanf("%d",&minchinese);
	if(minchinese==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(minchinese<0||minchinese>150)//输入越界 
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Chinese(data,menuflag);//递归 
		return;
	} 
	fflush(stdin);
	printf("\t\t\t\t请输入待查询语文成绩最高值:");
	scanf("%d",&maxchinese);
	if(maxchinese==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(maxchinese150)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Chinese(data,menuflag);
		return;
	}
	for(int i=0;i<=length;i++)
		if(data[i].score[0]<=maxchinese&&data[i].score[0]>=minchinese)
		{
			Show_Student(data,i);
			flag=1;
		}
	if(flag==0)	printf("\t\t\t\t未找到记录!\n");
}

void Check_Math(Student data[],int menuflag)//按数学成绩查询学生 
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	int minmath=-2,maxmath=151;
	char major[20];
	fflush(stdin);
	printf("\t\t\t\t请输入待查询数学成绩最低值:");
	scanf("%d",&minmath);
	if(minmath==-1)	
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(minmath<0||minmath>150)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Chinese(data,menuflag);
		return;
	}
	fflush(stdin);
	printf("\t\t\t\t请输入待查询数学成绩最高值:");
	scanf("%d",&maxmath);
	if(maxmath==-1)	
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(maxmath150)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Math(data,menuflag);
		return;
	} 
	for(int i=0;i<=length;i++)
		if(data[i].score[1]<=maxmath&&data[i].score[1]>=minmath)
		{
			Show_Student(data,i);
			flag=0;
		}
	if(flag==0)	printf("\t\t\t\t未找到记录!\n");
}

void Check_English(Student data[],int menuflag)//按英语成绩查询学生
{ 
	int length=Length_Student(data)-1;
	int flag=0;
	int minenglish=-2,maxenglish=151;
	char major[20];
	fflush(stdin);
	printf("\t\t\t\t请输入待查询英语成绩最低值:");
	scanf("%d",&minenglish);
	if(minenglish==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(minenglish<0||minenglish>150)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_English(data,menuflag);
		return;
	}
	fflush(stdin);
	printf("\t\t\t\t请输入待查询英语成绩最高值:");
	scanf("%d",&maxenglish);
	if(maxenglish==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(maxenglish150)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_English(data,menuflag);
		return;
	} 
	for(int i=0;i<=length;i++)
		if(data[i].score[2]<=maxenglish&&data[i].score[2]>=minenglish)
		{
			Show_Student(data,i);
			flag=1;
		}
	if(flag==0)	printf("\t\t\t\t未找到记录!\n\t\t\t\t");
}

void Check_Compre(Student data[],int menuflag)//按综合成绩查询学生 
{ 
	int length=Length_Student(data)-1;
	Sort_Number(data,0,length);
	int flag=0;
	int mincompre=-2,maxcompre=301;
	char major[20];
	fflush(stdin);
	printf("\t\t\t\t请输入待查询综合成绩最低值:");
	scanf("%d",&mincompre);
	if(mincompre==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(mincompre<0||mincompre>150)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Compre(data,menuflag);
		return;
	}
	fflush(stdin);
	printf("\t\t\t\t请输入待查询综合成绩最高值:");
	scanf("%d",&maxcompre);
	if(maxcompre==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(maxcompre750)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Compre(data,menuflag);
		return;
	} 
	for(int i=0;i<=length;i++)
		if(data[i].score[3]<=maxcompre&&data[i].score[3]>=mincompre)
		{
			Show_Student(data,i);
			flag=1;
		}
	if(flag==0)	printf("\t\t\t\t未找到记录!\n\t\t\t\t");
}

void Check_Score(Student data[],int menuflag)//按入学总成绩查询学生 
{ 
	int length=Length_Student(data)-1;
	Sort_Number(data,0,length);
	int flag=0;
	int minscore=-2,maxscore=751;
	char major[20];
	fflush(stdin);
	printf("\t\t\t\t请输入待查询总入学成绩最低值:");
	scanf("%d",&minscore);
	if(minscore==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	else if(minscore<0||minscore>750)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Score(data,menuflag);
		return;
	}
	fflush(stdin);
	printf("\t\t\t\t请输入待查询总入学成绩最高值:");
	scanf("%d",&maxscore);
	if(maxscore==-1)
	{
		Menu_Check(data,menuflag);
		return;
	}
	if(maxscore750)
	{
		printf("\t\t\t\t非法输入!\n");
		Check_Score(data,menuflag);
		return;
	} 
	for(int i=0;i<=length;i++)
		if(data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]<=maxscore&&
		data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3]>=minscore)
		{
			Show_Student(data,i);
			flag=1;
		}
	if(flag==0)	printf("\t\t\t\t未找到记录!\n\t\t\t\t");
}

void Count_Class_Score(Student data[],int menuflag)//按班级,统计分数情况 
{ 
	int MaxChinese=0,MaxMath=0,MaxEnglish=0,MaxCompre=0;//各个成绩最值初始化 
	int MinChinese=150,MinMath=150,MinEnglish=150,MinCompre=300;
	int classnum;//待查询的班号 
	int classflag=0;//指示班号是否找到 
	int classsize=0;//班级人数 
	int length=Length_Student(data);//统计记录总数 
	double classavg;//班级平均分 
	printf("\t\t\t\t请输入待查询班级(四位班号,输入-1返回上级菜单):");
	fflush(stdin);
	scanf("%d",&classnum);
	if(classnum==-1)	Menu_Count(data,menuflag);//输入-1返回上级菜单 
	for(int i=0;i<=length;i++)
	{
		if((data[i].num/100)%10000==classnum)//找到待查询班号 
		{
			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]);
			//展示班级学生入学总成绩 
			classflag=1;//指示待查询班级找到 
			classsize++;//统计班级人数 
			classavg=classavg+data[i].score[0]+data[i].score[1]+data[i].score[2]+data[i].score[3];//班级入学总成绩累加 
			if(data[i].score[0]>MaxChinese)	MaxChinese=data[i].score[0];//比较查找各科最值 
			if(data[i].score[0]MaxMath)	MaxMath=data[i].score[1];
			if(data[i].score[1]MaxEnglish)	MaxEnglish=data[i].score[2];
			if(data[i].score[2]MaxCompre)	MaxCompre=data[i].score[3];
			if(data[i].score[3]18) 
	{
		printf("\t\t\t\t身份码过长!\n\t\t\t\t");
		system("pause");
		Change_Code(data);
	}
	printf("\t\t\t\t请输入新的管理员身份码(20位以内,输入-1返回上级菜单):");
	scanf("%s",tmp[1]);
	if(strcmp(tmp[1],"-1")==0)	Menu_Admin(data);
	else if(strlen(tmp[1])>18) //输入身份码过长 
	{
		printf("\t\t\t\t身份码过长!\n\t\t\t\t");
		system("pause");
		Change_Code(data);
		return; 
	}
	else if(strcmp(tmp[0],tmp[1])==0)
	{
		printf("\n\t\t\t\t身份码重用!\n\t\t\t\t");
		system("pause");
		Change_Code(data);
		return;
	}
	fp=fopen("code.txt","w");//将新输入的身份码存入外存文件 
	fprintf(fp,"%s\n%s",tmp[0],tmp[1]);
	fclose(fp);
	printf("\n\t\t\t\t修改成功!\n\t\t\t\t");
	system("pause");
	Menu_Admin(data);//返回管理员主菜单 
}

void Menu_Admin(Student stu[])
{
	system("cls");
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
    printf("\t\t\t\t│               学生档案管理系统(管理员版)                │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                    #1.新建学生档案                        │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #2.删除/更改学生档案                     │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #3.查询与显示                         │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #4.统计与显示                         │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #5.更改身份码                         │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #0.保存并退出                         │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
	printf("\t\t\t\t#请键入功能编号:");
	int n=-1;//初始置非法值 
	int check;
	fflush(stdin);//清空缓存区,防止输入字符导致循环 
	scanf("%d",&n);
	Student tmp;
	FILE *fp;
	switch(n)
	{
		case 0:
			fp=fopen(stu[Length_Student(stu)].major, "w");//从结构体中读取文件名 
			Overwrite_Student(stu,fp);//将内存结构体中的记录写入外存文件 
			fclose(fp);
			system("cls");
			Print_End();//展示结束画面 
			exit(0);
		case 1:
			New_Student(&tmp,fp,stu);//调用创建新学生档案的子函数 
			system("pause"); 
			Menu_Admin(stu);//创建新学生子函数结束,递归到管理员主菜单 
			break;
		case 2:
			if(Length_Student(stu)==0)//内存结构体中无记录,无法更改/删除 
			{
				printf("\t\t\t\t数据源为空!\n\t\t\t\t");
				system("pause");
				Menu_Admin(stu);
				break;
			}
			system("cls"); 
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                      删除/更改学生档案                    │\n");
			printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Sort_Number(stu,0,Length_Student(stu)-1);
			Check_Name(stu,0);
			check=Check_Number(stu,1);
			if(check==-1)	Menu_Admin(stu);
			else	Menu_Change(tmp,stu,check);
			break;
		case 3:
			if(Length_Student(stu)==0)//内存结构体中无记录,无法查询 
			{
				printf("\t\t\t\t数据源为空!\n\t\t\t\t");
				system("pause");
				Menu_Admin(stu);
				break;
			}
			Sort_Number(stu,0,Length_Student(stu)-1);//对学号进行快速排序 
			Menu_Check(stu,1);//指示从管理员主菜单调用,menuflag置1 
			break;
		case 4:
			if(Length_Student(stu)==0)//内存结构体中无记录,无法统计 
			{
				printf("\t\t\t\t数据源为空!\n\t\t\t\t");
				system("pause");
				Menu_Admin(stu);
				break; 
			}
			Menu_Count(stu,1);//指示从管理员主菜单调用,menuflag置1 
			break;
		case 5:
			Change_Code(stu);		
		default:
			printf("\t\t\t\t非法输入!\n\t\t\t\t"); 
			system("pause"); 
			Menu_Admin(stu);
			break;
	} 
}

void Menu_User(Student stu[])
{
	system("cls");
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
    printf("\t\t\t\t│                学生档案管理系统(用户版)                 │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #1.查询与显示                         │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #2.统计与显示                         │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                        #0.退出                            │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
	printf("\t\t\t\t#请键入功能编号:");
	int n=-1;
	fflush(stdin);//清空缓存区,防止输入字符导致循环 
	scanf("%d",&n);
	switch(n)
	{
		case 0:
			system("cls");
			Print_End();
			exit(0);
			break; 
		case 1:
			if(Length_Student(stu)==0)//内存结构体中无记录,无法查找 
			{
				printf("\t\t\t\t数据源为空!\n\t\t\t\t");
				system("pause");
				Menu_Admin(stu);
				break; 
			}
			Sort_Number(stu,0,Length_Student(stu));
			Menu_Check(stu,0);//指示从用户主菜单调用,menuflag置0 
			break;
		case 2:
			Menu_Count(stu,0);//指示从用户主菜单调用,menuflag置0 
			if(Length_Student(stu)==0)//内存结构体中无记录,无法查找 
			{
				printf("\t\t\t\t数据源为空!\n\t\t\t\t");
				system("pause");
				Menu_Admin(stu);
				break;
			}
			break;		
		default:
			printf("\t\t\t\t非法输入!\n\t\t\t\t"); 
			system("pause"); 
			Menu_User(stu);
			break;
	}
}

void Menu_Change(Student data,Student stu[],int check)
{
	system("cls"); 
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 	printf("\t\t\t\t│                      删除/更改学生档案                    │\n");
	printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
	Show_Student(stu,check);
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #1.修改学生档案                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #2.删除学生档案                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #0.返回上级菜单                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
	printf("\t\t\t\t请键入功能编号:");
	int n=-1;
	fflush(stdin); 
	scanf("%d",&n);
	FILE *fp;
	switch(n)
	{
		case 0:
			Menu_Admin(stu);
			break;
		case 1:
			system("cls"); 
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                      删除/更改学生档案                    │\n");
			printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Show_Student(stu,check);//展示待更改的学生记录 
			Change_Student(data,stu,check);
			Menu_Change(data,stu,check); 
			break;
		case 2:
			Delete_Student(stu,check);
			break; 
		default:
			printf("\t\t\t\t非法输入!\n");
			system("pause"); 
			Menu_Change(data,stu,check);
			break; 
	}
}

void Menu_Check(Student stu[],int menuflag)
{
	system("cls");
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
    printf("\t\t\t\t│                       查询与显示                          │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #1.按学号查询学生档案                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #2.按姓名查询学生档案                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #3.按班级查询学生档案                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #4.按年级查询学生档案                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #5.按专业查询学生档案                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                 #6.按生源地查询学生档案                   │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #7.按民族查询学生档案                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #8.按性别查询学生档案                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                #9.按政治面貌查询学生档案                  │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                #10.按家庭收入查询学生档案                 │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                #11.按语文成绩查询学生档案                 │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                #12.按数学成绩查询学生档案                 │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                #13.按英语成绩查询学生档案                 │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                #14.按综合成绩查询学生档案                 │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│               #15.按入学总成绩查询学生档案                │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #0.返回上级菜单                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
	printf("\t\t\t\t请键入功能编号:");
	int n=-1;
	int check;
	fflush(stdin);
	scanf("%d",&n);
	switch(n)
	{
		case 0:
			if(menuflag==1)	Menu_Admin(stu);//menuflag为1,指示从管理员主菜单调用 
			if(menuflag==0)	Menu_User(stu);//menuflag为0,指示从用户主菜单调用 
			break;
		case 1:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按学号查询学生档案                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			check=Check_Number(stu,menuflag);
			if(check==-1)	Menu_Check(stu,menuflag);
			else
			{
				Show_Student(stu,check);
				printf("\t\t\t\t");
				system("pause");
				Menu_Check(stu,menuflag);
			}
			break;
		case 2:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按姓名查询学生档案                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Name(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 3:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按班级查询学生档案                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Class(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 4:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按年级查询学生档案                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Grade(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 5:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按专业查询学生档案                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Major(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 6:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                   按生源地查询学生档案                    │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Origin(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 7:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按民族查询学生档案                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Ethnic(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 8:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按性别查询学生档案                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Sex(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 9:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                  按政治面貌查询学生档案                   │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Politic(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break; 
		case 10:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                  按家庭收入查询学生档案                   │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Income(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 11:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                  按语文成绩查询学生档案                   │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Chinese(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 12:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                  按数学成绩查询学生档案                   │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Math(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 13:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                  按英语成绩查询学生档案                   │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_English(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 14:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                  按综合成绩查询学生档案                   │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Compre(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		case 15:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                 按总入学成绩查询学生档案                  │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Check_Score(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Check(stu,menuflag);
			break;
		default:
			printf("\t\t\t\t非法输入!\n\t\t\t\t");
			system("pause"); 
			Menu_Check(stu,menuflag);
			break;
	} 
}

void Menu_Count(Student stu[],int menuflag)
{
	system("cls");
	printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
    printf("\t\t\t\t│                       统计与显示                          │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #1.按班级统计分数情况                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #2.按年级统计专业人数                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #3.按班级统计省市人数                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                #4.按年级统计少数民族人数                  │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                  #5.按专业统计男女人数                    │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│             #6.按年级统计家庭收入低于平均人数             │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t│                     #0.返回上级菜单                       │\n");
    printf("\t\t\t\t│                                                           │\n");
    printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
	printf("\t\t\t\t请键入功能编号:");
	int n=-1;
	int length=Length_Student(stu)-1; 
	fflush(stdin);
	scanf("%d",&n);
	switch(n)
	{
		case 0:
			if(menuflag==1)	Menu_Admin(stu);
			if(menuflag==0)	Menu_User(stu);
			break;
		case 1:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按班级统计分数情况                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Sort_Number(stu,0,length);//对学号进行快速排序 
			Count_Class_Score(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Count(stu,menuflag);
			break;
		case 2:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按年级统计专业人数                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Sort_Major(stu,0,length);//对专业进行快速排序 
			Count_Grade_Major(stu,menuflag);
			printf("\t\t\t\t");
			system("pause");
			Menu_Count(stu,menuflag);
			break;
		case 3:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按班级统计省市人数                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Sort_Origin(stu,0,length);//对生源地进行快速排序 
			Count_Class_Origin(stu,menuflag);
			printf("\t\t\t\t"); 
			system("pause");
			Menu_Count(stu,menuflag);
			break;
		case 4:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                  按年级统计少数民族人数                   │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Sort_Ethnic(stu,0,length);//对民族进行快速排序 
			Count_Grade_Ethnic(stu,menuflag);
			printf("\t\t\t\t"); 
			system("pause");
			Menu_Count(stu,menuflag);
			break;
		case 5:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│                    按专业统计男女人数                     │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Sort_Number(stu,0,length);
			Count_Major_Sex(stu,menuflag);
			printf("\t\t\t\t"); 
			system("pause");
			Menu_Count(stu,menuflag);
			break;
		case 6:
			system("cls");
			printf("\t\t\t\t╭-----------------------------------------------------------╮\n");
 			printf("\t\t\t\t│              按年级统计家庭收入低于平均人数               │\n");
    		printf("\t\t\t\t╰-----------------------------------------------------------╯\n");
			Sort_Number(stu,0,length);
			Count_Grade_ClassPoor(stu,menuflag);
			printf("\t\t\t\t");  
			system("pause");
			Menu_Count(stu,menuflag);
			break;
		default:
			printf("\t\t\t\t非法输入!\n\t\t\t\t");
			system("pause"); 
			Menu_Count(stu,menuflag);
			break; 
	} 
}

int main()
{
	Student stu[500];
	Login(stu,5);
	return 0; 
}

 

你可能感兴趣的:(Test Blog)