程序设计基础大作业——学生管理系统

声明:这是本人所写的程序设计期末大作业实验报告,可供大家学习和参考,也希望能得到一些建议和改正,但如果只为抄袭代码,本人必究!

目录

一、任务描述

二、代码实现

三、运行结果

四、实验体会


一、任务描述

写一个命令行交互式C语言程序。该程序需要实现下述菜单功能:

1. 数据存储。

你需要将一系列的学生期末考试信息进行存储(学生人数不会超过100)。每个学生的信息包括:姓名(由first mane和last name 两部分组成,例如Xiaoer He,first_name =“Xiaoer”,last_name =“He”);学号(12 位数字组成,开头4位为2021 、2020 、2019); C语言成绩(一个大于等于零的整数);重修信息(学号 2021………为否,其余为是);GPA等级(A+, A, B+, B, C+, C, D, F );班级排名(成绩相同需并列)。其中,姓名,学号,成绩为输入数据,其余数据需要你计算。

同时,你需要添加一些维护数据库的功能

Add(name, id, score): 新增一个学生的信息;

Adds(n, name[], id[], score[]): 批量新增n个学生的信息;

Delete(id): 根据学号删除某个学生的信息;

Search(id) :根据学号查找某个学生的信息。

2. 数据处理。

Sort_by_id(): 生成根据学号顺序排列学生信息的表格

Sort_by_score():生成根据分数由高到低顺序排列学生信息的表格

Max():返回最高分学生信息

Min(): 返回最低分学生信息

Ave(): 返回所有学生期末成绩平均分

prime(id): 返回某个学生的成绩是否为素数

coprime(id, id) :返回某两个学生的成绩是否互质/互素

char* encrypt(int key): 加密学生成绩并返回

char* decrypt(int key, char *str): 解密学生成绩并返回

加密规则:Sort_by_id()之后的学生信息里,把所有学生的成绩按顺序拼接成一个只包含数字的字符串,然后依据整数key对其进行加密。例如:数字1被key=5加密之后变成6 ;数字5被key=5加密之后变成0。单个数字加密之后仍是单个数字。

解密规则与加密规则对称。

char * multi(int m): Sort_by_id()之后的学生信息里,把所有学生的成绩按顺序拼接成一个只包含数字的字符串,然后依据整数m对其进行翻倍。例如:拼接好的成绩字符串为11111111112222222222,m=3,则你需要返回33333333336666666666。这里保证m小于10。

3. 数据分析

根据GPA对学生成绩进行考情分析:A+多少人,A多少人,以此类推。GPA等级参考SZTU评分等级。

4. 用户界面

实现一个菜单,以供用户决定要使用哪个功能。

菜单参考:

Hello, pls input a series of student information! (用户开始输入)

Okay, data upload finished. What do you what to do next? You can enter a number to

tell me.

1 add

2 adds

3 delete

4 search

5 sort by id

6 sort by score

7 best score

8 worst score

9 prime judge

10 coprime judge

11 encrypt

0 exit

(用户输入) (输出计算结果)

Do you still need my service? You can enter a number to tell me.

1 add

2 adds

3 delete

4 search

5 sort by id

6 sort by score

7 best score

8 worst score

9 prime judge

10 coprime judge

11 encrypt

0 exit

(用户输入) (输出计算结果)

二、代码实现

代码实现所需要的头文件

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>

代码实现所创建的结构体

struct student//储存单个学生信息
{
	char name[100];//学生姓名
	long long No;//学号
	int C;//C语言成绩
	long long chongxiu;//重修信息,若显示为学号则不需要重修,否则需要重修
	char GPA[2];//学生GPA等级
	int paiming;//学生班级排名
};
struct student sztu[100];//建立结构数组 
struct student* p; //建立结构指针 

函数声明

void menu(int n);//菜单
void Add(char name[100], long long id, int score);//新增n个学生的信息
void Adds(int n, char names[100][100], long long ids[100], int scores[100]);//批量新增n个学生的信息
void Delete(long long id);//根据学号删除某个学生的信息
void Search(long long id);//寻找学生信息并打印出来
void GPA();//用于补全重修信息、GPA信息、班级排名
void Sort_by_id1();//用于过渡学号顺序
void Sort_by_id();//生成根据学号顺序排列学生信息的表格
void Sort_by_score();//生成根据分数由高到低顺序排列学生信息的表格
void Max();//输出最高分的学生信息
void Min();//输出最低分学生信息  
void Ave();//输出学生期末平均分数
void prime(long long id);//返回某个学生的成绩是否为质数
void coprime(long long id, long long id2);//返回某两个学生的成绩是否互质
void analysis();//分析整体情况,输出各个GTA等级的人数
char* encrypt(int key);//加密学生成绩并返回
char* decrypt(int Key);//解密学生成绩并返回

全局变量的声明

char last_name[100], first_name[100], name[100];//用户输入的学生姓、名
long long id, id2;//用户输入的学生的学号
int score;//用户输入的学生分数
char names[100][100];//用于用户批量添加学生信息时存入学生姓名 
long long ids[100];//用于用户批量添加学生信息时存入学生学号
int Cs[100];//用于用户批量添加学生信息时存入学生C语言成绩
int Cs2[100];
long long IDs[100];//定义长数组IDs用于储存学号信息并排序 
long long temp;//定义临时长变量
int key;//加密密钥
int key2[300];//储存拼接后的成绩
int keys[300];//存储加密后的字符串
int key3;//存储加密后的字符串整数化 
int key4 = 0;//判断是否加密
int i = 0;//计算位数
int Key, a, b;//解密

主函数

int main()
{
	int i = 0;
	for (int i = 0; i < 100; i++)//使未录入前所有数据为0,代表没数据
	{
		sztu[i].No = 0;
		sztu[i].C = 0;
		sztu[i].chongxiu = 0;
	}
	printf("请以(学生姓、学生名、学号、成绩)的方式录入若干组初始学生信息,输入CTRL+Z以结束录入\n");
	while (scanf("%s %s %lld %d", last_name, first_name, &sztu[i].No, &sztu[i].C) != EOF)//分别存入学生的个人信息 同时把学生姓和名合并为一个字符串
	{
		strcat(last_name, " ");
		strcat(last_name, first_name);
		strcpy(sztu[i].name, last_name);
		i++;
	}
	GPA();//调用GPA函数,补全学生信息中的重修信息、GTA信息、班级排名
	menu(0);//调用菜单函数 
	return 0;
}

菜单函数

//菜单 
void menu(int n)
{
	int x;//用于获取用户输入的数字 
	if (n == 0)
	{
		printf("信息已成功初始化,请输入要执行的功能对应的数字以继续\n 1 新增一个学生信息\n 2 批量新增多个学生信息\n 3 根据学号删除某个学生的信息\n 4 根据学号查找某个学生的信息\n 5 生成根据学号顺序排列学生信息的表格\n 6 生成根据分数由高到低顺序排列学生信息的表格\n 7 返回最高分学生信息\n 8 返回最低分学生信息\n 9 返回所有学生期末成绩平均分\n 10 返回某个学生成绩是否为质数\n 11 返回某两个学生成绩是否互质\n 12 返回各个GPA等级的人数\n 13 对成绩进行加密\n 14 对成绩进行解密\n ...\n 0 退出\n");//首次使用调用 

	}
	else if (n == 1)
	{
		printf("\n操作已完成,请输入要执行的功能对应的数字以继续\n 1 新增一个学生信息\n 2 批量新增多个学生信息\n 3 根据学号删除某个学生的信息\n 4 根据学号查找某个学生的信息\n 5 生成根据学号顺序排列学生信息的表格\n 6 生成根据分数由高到低顺序排列学生信息的表格\n 7 返回最高分学生信息\n 8 返回最低分学生信息\n 9 返回所有学生期末成绩平均分\n 10 返回某个学生成绩是否为质数\n 11 返回某两个学生成绩是否互质\n 12 返回各个GPA等级的人数\n 13 对成绩进行加密\n 14 对成绩进行解密\n ...\n 0 退出\n");//非首次使用调用
	}
	for (int i = 0; i > (-1); i++)//不自动结束的循环,重复获取用户输入的数字 
	{
		scanf("%d", &x);//以下代码为根据用户所输入的数字执行相应功能
		if (x == 0)//用户输入0退出,程序结束
		{
			printf("成功退出\n");
			exit(0);//使用exit直接结束整个进程 
			break;
		}
		switch (x)//其他功能
		{
		case 1:
			Add(name, id, score);//调用Add函数,添加单个学生信息 
			GPA();//调用GPA函数,补全或修改学生信息中的重修信息、GPA信息、班级排名
			menu(1);//输出菜单 
			break;

		case 2:
			Adds(n, names, ids, Cs); //调用Adds函数,批量添加学生信息
			GPA(); //调用GPA函数,补全或修改学生信息中的重修信息、GPA信息、班级排名
			menu(1);//输出菜单 
			break;

		case 3:
			Delete(id);//调用Delete函数 删除某个学生的信息
			GPA();//调用GPA函数,补全或修改学生信息中的重修信息、GPA信息、班级排名
			menu(1);//输出菜单
			break;

		case 4:
			Search(id);//调用Search函数 寻找并打印学生信息
			menu(1);//输出菜单
			break;

		case 5:
			Sort_by_id();//调用Sort_by_id函数生成根据学号顺序排列学生信息的表格
			menu(1);//输出菜单
			break;

		case 6:
			Sort_by_score();//调用Sort_by_score函数生成根据分数由高到低顺序排列学生信息的表格
			menu(1);//输出菜单
			break;

		case 7:
			Max();//调用Max函数 
			menu(1);//输出菜单
			break;

		case 8:
			Min();//调用Min函数 
			menu(1);//输出菜单
			break;

		case 9:
			Ave();//调用Ave函数 
			menu(1);//输出菜单
			break;

		case 10:
			prime(id);//调用prime函数 
			menu(1);//输出菜单
			break;

		case 11:
			coprime(id, id2);//调用coprime函数 
			menu(1);//输出菜单
			break;

		case 12:
			analysis();//调用analysis函数 
			menu(1);//输出菜单
			break;

		case 13:
			encrypt(key);//调用encrypt函数 
			menu(1);//输出菜单
			break;

		case 14:
			decrypt(Key);//调用decrypt函数 
			menu(1);//输出菜单
			break;

		default:
			printf("请输入菜单前的数字!!!\n");
			break;
		}
	}
}

定义数据储存函数

功能1新增一个学生信息

void Add(char name[100], long long id, int score) //功能1新增一个学生信息
{
	int i;
	printf("请输入依次学生姓、学生名、学号、成绩:\n");
	scanf("%s %s %lld %d", last_name, first_name, &id, &score);
	strcat(last_name, " ");
	strcat(last_name, first_name);
	strcpy(name, last_name);
	p = &sztu[0];//重置指针p的位置
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == 0)
		{
			strcpy(p->name, name);
			p->No = id;
			p->C = score;
			break;
		}
	}
}

功能2量新增n个学生的信息

void Adds(int n, char names[100][100], long long ids[100], int scores[100])//功能2批量新增n个学生的信息
{
	printf("请在第一行输入要添加的学生数量n\n 然后在下面依次输入n行信息,每行包含一名学生的姓名(学生姓、学生名的形式输入)、学号、C语言成绩\n");
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%s %s %lld %d", last_name, first_name, &ids[i], &Cs[i]);
		strcat(last_name, " ");
		strcat(last_name, first_name);
		strcpy(names[i], last_name);
	}
	p = &sztu[0];//重置指针p的位置 
	int count = 0;//用于计数已经添加了几个学生
	for (int i = 0; i < 100 && count != n; i++, p++)//寻找空位进行赋值 
	{
		if (p->No == 0)//学号为0即为空位 
		{
			strcpy(p->name, names[count]);
			p->No = ids[count];
			p->C = scores[count]; //为姓名、学号、c语言成绩赋值 
			count++;//计数已经添加了几个学生的信息 
		}
	}
}

功能3根据学号删除某个学生的信息

void Delete(long long id)//功能3根据学号删除某个学生的信息
{
	printf("请输入要删除的学生的学号");
	scanf("%lld", &id);
	p = &sztu[0];//重置指针p的位置 
	int dele = 0;//用于判断所输入学号有无学生 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == id)//按照学号搜索信息 
		{
			p->No = 0;//匹配到后将学号的值改为0,视为删除
			dele++; 
			printf("已成功删除该生信息");
			break; 
		}
	}
	if(dele == 0)
	{
		printf("无该学号的学生");
	}
}

功能4寻找学生信息并打印出来

void Search(long long id)//功能4寻找学生信息并打印出来 
{
	printf("请输入学生学号:");
	scanf("%lld", &id);
	p = &sztu[0];//重置指针p的位置 
	int count = 0;
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == id && p->C != 0)//按照学号搜索信息 
		{
			printf("姓名:%-7s 学号:%-7lld C语言成绩:%-4d 重修信息(显示学号为不需要重修):%-7lld GPA等级:%-4s 排名:%-4d\n", p->name, p->No, p->C, p->chongxiu, p->GPA, p->paiming);//输出符合的学生信息 
			count++;//用来判断有无该学号的学生 
			break;
		}
	}
	if (count == 0)
	{
		printf("无该学号的学生\n");
	}
}

一个用于补全学生信息的内置函数

void GPA()//用于补全学生信息中的重修信息、GPA信息、班级排名
{
	p = &sztu[0];//重置指针p的位置 
	int a[100];//临时储存成绩信息,便于排序 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->C >= 93 && p->No != 0)
		{
			strcpy(p->GPA, "A+");//赋予学生相应的GPA等级,下同 
			p->chongxiu = p->No;//赋予学生重修信息为对应的学号意味着该生不需要重修,下同 
		}
		else if (p->C < 93 && p->C >= 85 && p->No != 0)
		{
			strcpy(p->GPA, "A");
			p->chongxiu = p->No;
		}
		else if (p->C < 85 && p->C >= 80 && p->No != 0)
		{
			strcpy(p->GPA, "B+");
			p->chongxiu = p->No;
		}
		else if (p->C < 80 && p->C >= 75 && p->No != 0)
		{
			strcpy(p->GPA, "B");
			p->chongxiu = p->No;
		}
		else if (p->C < 75 && p->C >= 70 && p->No != 0)
		{
			strcpy(p->GPA, "C+");
			p->chongxiu = p->No;
		}
		else if (p->C < 70 && p->C >= 65 && p->No != 0)
		{
			strcpy(p->GPA, "C");
			p->chongxiu = p->No;
		}
		else if (p->C < 65 && p->C >= 60 && p->No != 0)
		{
			strcpy(p->GPA, "D");
			p->chongxiu = p->No;
		}
		else if (p->C < 60 && p->No != 0)
		{
			strcpy(p->GPA, "F");
			p->chongxiu = 1;//重修信息为1则说明该学生需要重修 
		}
	}
	p = &sztu[0];//重置指针p的位置 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == 0)//学号为0说明无学生信息,则跳过 
		{
			a[i] = -1;//跳过后赋值为-1代表该位没有成绩数据
			continue;
		}
		a[i] = p->C;//将成绩信息存入a[i]中,以便后续排序 
	}
	int temp;//中间变量 用于交换数值
	for (int i = 0; i < 100; i++)
	{
		for (int j = i; j < 100; j++)//逐个比较,使成绩从大到小排列 
		{
			if (a[i] < a[j])
			{
				temp = a[i];//利用中间变量交换a[i]和a[j]的值 
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}
	p = &sztu[0];//重置指针p的位置 
	int pm = 1;//学生班级排名数
	for (int i = 0; i < 100; i++)
	{
		if (a[i] == a[i - 1] && i > 0)//两学生成绩相同时排名一样,则排名无需自增1,故跳过 
		{
			continue;
		}
		for (int j = 0; j < 100; j++, p++)//为学生的成绩等于a[j]的学生赋予相应的排名
		{
			if (p->C == a[i] && p->No != 0)
			{
				p->paiming = pm;
			}
		}
		p = &sztu[0];//重置指针p的位置 
		pm++;//为下一个成绩排名
	}
}

定义数据处理函数

一个用于排列学号的内置函数

void Sort_by_id1()//过渡函数,用于过渡学号顺序
{
	p = &sztu[0];//重置指针p的位置 
	for (int i = 0; i < 100; i++, p++)
	{
		IDs[i] = p->No;//将学生学号信息储存到数组IDs[]中 
	}
	for (int j = 0; j < 100; j++)
	{
		for (int k = j; k < 100; k++)//逐个比较,最终将其从大到小排列 
		{
			if (IDs[j] < IDs[k])
			{
				temp = IDs[j];
				IDs[j] = IDs[k];
				IDs[k] = temp;
			}
		}
	}
}

功能5生成根据学号顺序排列学生信息的表格

需要用到上一个内置函数Sort_by_id1()

void Sort_by_id()//功能5生成根据学号顺序排列学生信息的表格
{
	if (key4 == 0)//确保使用时打印出的成绩是未加密的 
	{
		Sort_by_id1();
		p = &sztu[0];//重置指针p的位置
		for (int l = 0; l < 100; l++)
		{
			if (IDs[l] == 0)//学号从大到小的顺序,如果IDs[l] == 0,则说明后面没有学号信息了 
			{
				break;
			}
			for (int t = 0; t < 100; t++, p++)
			{
				if (p->No == IDs[l] && p->No != 0)//在学号不等于0(即学号存在)的情况下逐个进行匹配,如果符合条件则输出 
				{
					printf("姓名:%-7s 学号:%-7lld C语言成绩:%-4d 重修信息(显示学号为不需要重修):%-7lld GPA等级:%-4s 排名:%-4d\n", p->name, p->No, p->C, p->chongxiu, p->GPA, p->paiming);//输出符合的学生信息
					Cs2[l] = p->C;
					p = &sztu[0];//重置指针p的位置
					break;
				}
			}
		}
		b = 1;//代表已使用功能5打印按学号排序的成绩单,同时解锁加密功能 
	}
	else if (key4 == 1)
	{
		printf("加密状态禁用该功能");
	}
}

功能6生成根据分数由高到低顺序排列学生信息的表格

void Sort_by_score() //功能6生成根据分数由高到低顺序排列学生信息的表格
{
	p = &sztu[0];//重置指针p的位置 
	for (int i = 1; i <= 100; i++)
	{
		for (int j = 0; j < 100; j++, p++)
		{
			if (p->paiming == i && p->No != 0)//在学号不等于0(为0则视为空或被删除)的情况下逐个进行匹配,如果符合则输出
			{
				printf("姓名:%-7s 学号:%-7lld C语言成绩:%-4d 重修信息(显示学号为不需要重修):%-7lld GPA等级:%-4s 排名:%-4d\n", p->name, p->No, p->C, p->chongxiu, p->GPA, p->paiming);//输出符合的学生信息 
			}
		}
		p = &sztu[0];//重置指针p的位置 
	}
}

功能7输出成绩最高分的学生的信息

void Max() //功能7输出成绩最高分的学生的信息 
{
	p = &sztu[0];//重置指针p的位置  
	int max = 0;
	for (int i = 0; i < 100; i++, p++)
	{
		if (max < p->C && p->No != 0)//使用功能3时清空学号就视为删除学生信息,其余信息还未清空, 因此在这里需要加上条件 No != 0来避免删除该生信息后仍输出成绩的情况 
		{
			max = p->C;//得到最高分 
		}
	}
	p = &sztu[0];//重置指针p的位置 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->C == max && p->No != 0)
		{
			printf("姓名:%-7s 学号:%-7lld C语言成绩:%-4d 重修信息(显示学号为不需要重修):%-7lld GPA等级:%-4s 排名:%-4d\n", p->name, p->No, p->C, p->chongxiu, p->GPA, p->paiming);//输出符合的学生信息 
		}
	}
}

功能8输出成绩最低分的学生的信息

void Min()//功能8输出成绩最低分的学生的信息 
{
	p = &sztu[0];//重置指针p的位置 
	int min;
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No != 0)//若该位置学号不为空,则为min赋一个有效的分数值
		{
			min = p->C;
			break;
		}
	}
	p = &sztu[0];//重置指针p的位置 
	for (int i = 0; i < 100; i++, p++)//循环遍历后得到整体成绩的最低分 
	{
		if (min > p->C && p->No != 0)
		{
			min = p->C;//得到最低分
		}
	}
	p = &sztu[0];//重置指针p的位置 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->C == min && p->No != 0)
		{
			printf("姓名:%-7s 学号:%-7lld C语言成绩:%-4d 重修信息(显示学号为不需要重修):%-7lld GPA等级:%-4s 排名:%-4d\n", p->name, p->No, p->C, p->chongxiu, p->GPA, p->paiming);//输出符合的学生信息 
		}
	}
}

功能9输出学生期末平均分数

void Ave()//功能9输出学生期末平均分数
{
	p = &sztu[0];//重置指针p的位置
	int count = 0;//用于统计学生人数
	double ave, sum = 0;
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == 0)
		{
			continue;//无学生信息跳过不计数
		}
		sum = p->C + sum;
		count++;
	}
	ave = sum / count;
	printf("学生期末成绩平均分为:%.6f\n", ave);
}

功能10判断学生的成绩是否为质数

void prime(long long id)//功能10判断学生的成绩是否为质数 
{
	printf("请输入学生学号:");
	scanf("%lld", &id);
	int pd = 0;//用于判断有无学生信息 
	p = &sztu[0];//重置指针p的位置 
	int flag = 0;//判断成绩是否为质数 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == id)//找到输入的学号对应的位置 
		{
			pd++; 
			break;
		}
	}
	if (p->C == 0 && pd == 1 || p->C == 1)
	{
		printf("该生的成绩不是质数"); //0和1不为质数 
	}
	else if (p->C == 2 || p->C == 3)
	{
		printf("该生的成绩是质数"); //2和3为质数 
	}
	else
	{
		for (int j = 2; j < p->C; j++)
		{
			if (p->C % j == 0)//如果成绩能被比他小的数整除,则其不为质数
			{
				flag = 1;
			}
		}
		if (flag == 0 && pd == 1)
		{
			printf("该生的成绩是质数\n");
		}
		else if(flag != 0 && pd == 1)
		{
			printf("该生的成绩不是质数\n");
		}
	}
	if(pd == 0)
	{
		printf("无该学生信息\n");
	}
}

功能11判断两个学生的成绩是否互质

void coprime(long long id, long long id2)//功能11判断两个学生的成绩是否互质 
{
	printf("请依次输入两名学生的学号1和学号2:");
	scanf("%lld %lld", &id, &id2);
	p = &sztu[0];//重置指针p的位置 
	int  score1, score2, temp;
	int pd2 = 0; 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == id)//找到输入的学号1对应的位置 
		{
			pd2++;
			break;
		}
	}
	score1 = p->C;//第一个学生对应的成绩 
	p = &sztu[0];//重置指针p的位置 
	for (int i = 0; i < 100; i++, p++)
	{
		if (p->No == id2)//找到输入的学号2对应的位置 
		{
			pd2++;
			break;
		}
	}
	score2 = p->C;//第二个学生对应的成绩 
	if (score1 < score2)//使score1>score2
	{
		temp = score1;
		score1 = score2;
		score2 = temp;//借助中间变量temp互换score1和score2的值 
	}
	while (score2 != 0)
	{
		temp = score1 % score2;
		score1 = score2;
		score2 = temp;//辗转相除法求最大公约数 (用大数除于小数)
	}
	if (score2 == 1 && pd2 == 2)//如果两数的最大公约数为1,则两数互质
	{
		printf("两学生的成绩互质\n");
	}
	else if(score2 != 1 && pd2 == 2)//反之,则不互质
	{
		printf("两学生的成绩不互质\n");
	}
	else if(pd2!=2)
	{
		printf("请输入存在的学生学号\n"); 
	}
}

下面是数据分析函数

功能12分析整体情况,输出各个GTA等级的人数

//数据分析函数
void analysis()//功能12分析整体情况,输出各个GTA等级的人数
{
	p = &sztu[0];//重置指针p的位置 
	int count_A1 = 0, count_A = 0, count_B1 = 0, count_B = 0, count_C1 = 0, count_C = 0, count_D = 0, count_F = 0;//用于统计各等级人数 
	for (int i = 0; i < 100; i++, p++)
	{
		if (strcmp(p->GPA, "A+") == 0 && p->No != 0)//统计A+人数
		{
			count_A1++;
		}
		else if (strcmp(p->GPA, "A") == 0 && p->No != 0)//统计A人数
		{
			count_A++;
		}
		else if (strcmp(p->GPA, "B+") == 0 && p->No != 0)//统计B+人数
		{
			count_B1++;
		}
		else if (strcmp(p->GPA, "B") == 0 && p->No != 0)//统计B人数
		{
			count_B++;
		}
		else if (strcmp(p->GPA, "C+") == 0 && p->No != 0)//统计C+人数
		{
			count_C1++;
		}
		else if (strcmp(p->GPA, "C") == 0 && p->No != 0)//统计C人数
		{
			count_C++;
		}
		else if (strcmp(p->GPA, "D") == 0 && p->No != 0)//统计D人数
		{
			count_D++;
		}
		else if (strcmp(p->GPA, "F") == 0 && p->No != 0)//统计F人数
		{
			count_F++;
		}
	}
	printf("成绩 A+ 的人数为:%d\n", count_A1);//分别输出各个等级的人数 
	printf("成绩 A  的人数为: %d\n", count_A);
	printf("成绩 B+ 的人数为:%d\n", count_B1);
	printf("成绩 B  的人数为: %d\n", count_B);
	printf("成绩 C+ 的人数为:%d\n", count_C1);
	printf("成绩 C  的人数为: %d\n", count_C);
	printf("成绩 D  的人数为: %d\n", count_D);
	printf("成绩 F  的人数为: %d\n", count_F);
}

功能13加密学生成绩并返回

char* encrypt(int key)//功能13加密学生成绩并返回
{
	if (b == 1)//已使用功能5打印按学号排序的成绩单,同时解锁加密功能 
	{
		if (key4 == 0)//未加密状态才能加密 
		{
			printf("请设定一个密钥:");
			scanf("%d", &key);
			a = key;
			Sort_by_id1();
			long long Score = 0;//用于储存成绩拼接 
			p = &sztu[0];//重置指针p的位置
			for (int l = 0; l < 100; l++)
			{
				if (IDs[l] == 0)//学号从大到小的顺序,如果IDs[l]==0,则说明后面没有学号信息了 
				{
					break;
				}
				for (int t = 0; t < 100; t++, p++)
				{
					if (p->No == IDs[l] && p->No != 0)//在学号不等于0(即学号存在)的情况下逐个进行匹配,对符合条件的数据进行下一步的处理 
					{
						if (p->C / 100 == 0)//用于同学成绩小于100分 
						{
							if(p->C / 10 != 0)//2位数成绩 
							{
								Score = Score * 100 + p->C;
							}
							else if(p->C / 10 == 0)//个位数成绩 
							{
								Score = Score * 10 + p->C;
							}
						}
						else if (p->C / 100 != 0)//用于同学成绩大于等于100分 
						{
							Score = Score * 1000 + p->C;
						}
						p = &sztu[0];//重置指针p的位置
						break;
					}
				}
			}//把所有学生的成绩按顺序拼接成数字的字符串,然后依据整数key对其进行加密。例如:数字1被key=5加密之后变成6 ;数字5被key=5加密之后变成0。单个数字加密之后仍是单个数字。
			int j, temp;
			while (Score != 0)
			{
				key2[i] = Score % 10;
				i++;	//记录整数位数
				Score = Score / 10;
			}
			i--;	//结束while循环后i肯定会比整数位数大1,因此需要自减1
			for (j = 0; j < i / 2 + 1; j++) //存储进数组的数据是倒序的,所以要对数据调整为正序
			{
				temp = key2[i - j];
				key2[i - j] = key2[j];
				key2[j] = temp;
			}
			for (j = 0; j <= i; j++)
			{
				keys[j] = (key2[j] + key) % 10;
			}
			int t = i;
			for (j = 0; j <= i; j++, t--)
			{
				key3 += keys[j] * pow(10, t);
			}
			p = &sztu[0];//重置指针p的位置
			printf("加密成功\n");
			key4 = 1;
			for (int l = 0; l < 100; l++)
			{
				if (IDs[l] == 0)//学号从大到小的顺序,如果IDs[l] == 0,则说明后面没有学号信息了 
				{
					break;
				}
				for (int t = 0; t < 100; t++, p++)
				{
					if (p->No == IDs[l] && p->No != 0)//在学号不等于0(即学号存在)的情况下逐个进行匹配,如果符合条件则输出
					{
						p->C = key3;
						printf("姓名:%-7s 学号:%-7lld C语言成绩:%-4d 重修信息(显示学号为不需要重修):%-7lld GPA等级:%-4s 排名:%-4d\n", p->name, p->No, p->C, p->chongxiu, p->GPA, p->paiming);//输出符合的学生信息
						p = &sztu[0];//重置指针p的位置
						break;
					}
				}
			}
		}
		else if (key4 == 1)
		{
			printf("已加密,不能重复加密!");
		}
	}
	else
	{
		printf("请先使用功能5");//加密前要打印按学号排序的成绩单 
	}
}

功能14解密学生成绩并返回

char* decrypt(int Key)//功能14解密学生成绩并返回 
{
	if (key4 == 0)//判断是否加密 
	{
		printf("成绩未加密\n");
	}
	else if (key4 == 1)//若已加密则输入密码 
	{
		printf("请输入密钥以解码:");
		scanf("%d", &Key);
		if (Key == a)//密码正确则继续解密 
		{
			p = &sztu[0];//重置指针p的位置
			for (int l = 0; l < 100; l++)
			{
				if (IDs[l] == 0)//学号从大到小的顺序,如果IDs[l] == 0,则说明后面没有学号信息了 
				{
					break;
				}
				for (int t = 0; t < 100; t++, p++)
				{
					if (p->No == IDs[l] && p->No != 0)//在学号不等于0(即学号存在)的情况下逐个进行匹配,对符合条件的数据进行下一步的处理 
					{
						p->C = Cs2[l];
						p = &sztu[0];//重置指针p的位置
						break;
					}
				}
			}
			printf("已成功解密,结果如下:\n");
			key4 = 0;//解密完成 成绩单恢复为未加密状态 
			for (int l = 0; l < 100; l++)
			{
				if (IDs[l] == 0)//学号从大到小的顺序,如果IDs[l] == 0,则说明后面没有学号信息了
				{
					break;
				}
				for (int t = 0; t < 100; t++, p++)
				{
					if (p->No == IDs[l] && p->No != 0)//在学号不等于0(即学号存在)的情况下逐个进行匹配,如果符合条件则输出
					{
						printf("姓名:%-7s 学号:%-7lld C语言成绩:%-4d 重修信息(显示学号为不需要重修):%-7lld GPA等级:%-4s 排名:%-4d\n", p->name, p->No, p->C, p->chongxiu, p->GPA, p->paiming);//输出符合的学生信息
						p = &sztu[0];//重置指针p的位置
						break;
					}
				}
			}
		}
		else//密码错误 未能成功解密 
		{
			printf("密码错误");
		}
	}
}

三、运行结果

初始化学生信息数据

使用功能1新增一个学生信息

使用功能2批量新增学生信息

使用功能3删除已添加的学生信息

情况1:无该学号的学生的情况

情况2:成功删除

功能4查找对应学号的学生信息

情况1:无该学号的学生存在

情况2:成功查找

功能5生成按学号顺序排列的表格

功能6生成按成绩顺序排列的表格

功能7返回最高分的学生信息

功能8返回最低分的学生信息

功能9返回使用学生期末考试成绩平均分

功能10判断学生的成绩是否为质数

情况1:学号存在

情况2:无该学号学生

功能11判断两个学生的成绩是否互质

情况1:有学号不存在

情况2:学号信息有效

功能12分析整体情况,输出各个GTA等级的人数

功能13加密学生成绩并返回

情况1:成功加密

情况2:已经加密,不能重复操作

功能14解密学生成绩并返回

情况1:密码错误

情况2:成功解密

情况3:成绩未加密

输入菜单前不存在的数字时需要重新输入

退出程序

 

四、实验体会

这次实验是写入学生的各种信息,并对学生的信息进行一系列处理。在明确大方向后,我选择用结构的方法来表示一名学生的所有信息,同时建立一个结构数组来存入多名学生的信息数据。

在编写菜单menu()函数时,因为该函数所需要实现的功能是通过用户从键盘输入对应的值来调用其他的功能函数,同时不能让程序自主结束,而是通过用户的选择来结束。因此我选择了for (int i = 0; i > (-1); i++)来实现一个不会自主结束的循环和menu()函数自我嵌套来供用户无限使用,同时使用switch使用户输入的数字能实现到对应的功能函数上。然后退出程序上,起初我选择的是用return来退出,但随后就发现了问题,因为在用户实现相应功能的同时menu函数也在自我调用,因此用户输入0时并不能马上退出程序,而是在多次输入0后,才能结束程序,这是因为在输入0时退出的是当前调用的menu函数,而这个当前调用的menu函数是通过上menu函数调用出来的,因此还需要再输入0来退出上个menu函数,以此类推共需要用户输入X次0才能结束进程,X为用户通过menu使用功能的次数。在思考过后,我就在想有没有一个函数能在调用时结束整个进程,然后我想起了exit()函数,然后我就对代码进行了进一步的完善,加上头文件stdlib.h以调用exit函数。由此菜单menu()函数的就能达到所需要的效果了

然后是定义数据储存函数,新增一个学生信息的Add()函数只需要一个简单的循环遍历,然后在无学生数据的地方将用户所输入的数据进行存储就可以了,然后是Adds()函数,其基本思想与Add函数是一样的,只是具体实现上多了个批量,使用户可以在一次性存入多名学生数据,因此在Add的基础上写多一个循环遍历同时将临时存储的一维数组改为二维数组就可以实现相应功能了。对于删除函数Delete()思路和上面两个是一样的,区别在于循环遍历的同时添加判断语句,然后根据符合的条件来进行下一步操作。查找函数Search()与Delete()思路基本相同,区别只是在判断过程中输出的结果不同。然后就是GPA()函数了,这个函数你会发现菜单上是没有的,因为在操作过程中用到最多的是学号,其次是在添加信息时会用到姓名和成绩,而重修信息、GPA信息、班级排名这些是需要系统来计算出来的,因此需要一个函数在每次用户执行完增减学生信息后,能及时更新学生的重修信息、GPA信息、班级排名。而这个功能的实现我选择了先对整个结构数组进行循环遍历,同时对相应的学生的成绩进行条件判断从而给他的GPA信息和重修信息进行赋值。然后通过一个临时的数组,将学生的成绩临时存储进去同时通过循环判断将其从大到小排序,然后据此在对学生的成绩继续循环判断来赋予相应排名。

然后就是定义数据处理函数了, Sort_by_id函数需要先将学生成绩按学号排序,再据此生成相应的学生成绩表格,因此我选择先定义一个过渡函数Sort_by_id1用于将学号按从大到小的顺序排列并存储到全局变量IDs[100]里,然后在Sort_by_id函数里调用过渡函数,紧接着就是对结构数组循环遍历了,在找到与IDs对应学号相同的学生成绩就可以将其输出了,最后就会得到一个按学号排序的学生信息表格;然后对于生成根据分数由高到低顺序排列的学生信息的表格的Sort_by_score函数只需要通过简单的循环遍历就能实现。Max()和Min()函数的基本思想就是通过在循环遍历的同时不断比较各值的大小,最后输出就可以了。Ave()函数也是通过循环遍历将各学生的成绩相加后除于学生人数就可以实现。Prime()函数判断学生的成绩是否为质数,只需要判断其能否被比他小的数整除,若能则其不为质数,因此需要条件判断就可以。Coprime函数判断两个学生的成绩是否互质,使用辗转相除法的算法就能实现。

加密函数encrypt(int key)要在按学号顺序排序后再加密,因此定义时,先用到过渡函数Sort_by_id1()将学号按由大到小的顺序排序,接着就是写入一个条件判断,来判断成绩是否已经加密,若已加密则输出“已加密,不能重复加密!”;若未加密,则进行下一步的加密操作,主要核心是判断;最后是解密函数decrypt(int Key),其核心还是对判断语句的应用。

最后,在这次的程序设计实验中,我对自身感到疑惑的点进行了相关的资料查询以达到扩宽自己的编程思路的目的。同时在实验过程中也对所学习到的编程知识进行更进一步的巩固和提升。总的来说,这是一次不错的体验。

  • 10
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值