超详细之C语言实现学生信息管理系统(含文件读写)

C语言实现学生信息管理系统(含文件读写)

注:最后有完整代码。
用来应付期末作业那是大大的足够了…
要建立一个学生管理系统,我们需要一些特定的操作,在本次的作业中,我们的学管系统将包含以下功能:
先是菜单的展示:
		"***学生管理系统*******\n"
		"**************************\n"
		"***系统功能菜单*******\n"
		"--------------------------\n"
		"**************************\n"
		"***   1.增加学生信息   ***\n"//ok
		"***   2.查询学生信息   ***\n"//ok
		"***   3.删除学生信息   ***\n"//ok
		"***   4.修改学生信息   ***\n"//ok
		"*****   5.读取文件   *****\n"//ok
		"***   6.显示学生信息   ***\n"//ok
		"*****   7.总分详情   *****\n"//ok
		"******  8.菜单帮助   *****\n"//ok
		"        9.不合格检索   \n"//ok
		"        10.学科详情   \n"//ok
		"        11.学校主页   \n"//ok
		"*****   0.退出系统   *****\n"//ok
为了避免频繁的调用菜单,所以菜单只会在第一次自动输出,其它次的输出需要手动调用case 8。
再看看结构体的定义:
struct course {
	int math;
	int computer;
	int English;
	int PE;
};
struct stu {
	char name[100];
	int age;
	char sex;
	struct course subject;
	struct stu* next;
	char number[20];
	int all_scores;
	int average_scores;
	int idx;
};

下面来具体看看:

一:读取信息库,并存入链表。

	FILE* fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "a+");
	int n;
	struct stu* head = (struct stu*)malloc(sizeof(struct stu));
	head->next = NULL;
	menu();
	fseek(fp, 0, SEEK_SET);
	int frequency = 1;
	printf("\n请您先读取文件!!!\n");
	printf("\n请您先读取文件!!!\n");
	printf("\n请您先读取文件!!!\n");
FILE* fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "a+");:这行代码打开一个名为“无标题.txt”的文件,该文件位于“D:\Shelly\OneDrive\桌面”目录下。"a+"表示以追加模式打开文件,在追加模式下,写入的数据会被添加到文件的末尾,而不会覆盖原有的内容。”+"表示文件可以读取和写入。如果文件不存在,则创建一个新文件。
fseek(fp, 0, SEEK_SET);:这行代码将文件指针fp移动到文件的开始位置,避免文字被覆盖。
注意:我们要确保在程序启动后第一步就是进行一次文件读入,防止后续创建学生信息时会使学生信息重复化。

二:读取文件

case 5: {
	if (frequency) {
		FILE* ffp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "r");
		fseek(fp, 0, SEEK_SET);
		struct stu student;
		while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
			student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
			&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
			int k = student.number;
			struct stu* p;
			p = head;
			int index = 0;
			for (p; p; p = p->next) {
				if (p->number == k) {
					index = 1;
					break;
				}
			}
			if (index) {
				continue;
			}
			else
			{
				struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
				strcpy(new_stu->name, student.name);
				strcpy(new_stu->number, student.number);
				new_stu->age = student.age;
				new_stu->sex = student.sex;
				new_stu->subject.math = student.subject.math;
				new_stu->subject.computer = student.subject.computer;
				new_stu->subject.English = student.subject.English;
				new_stu->subject.PE = student.subject.PE;
				new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
				new_stu->average_scores = (new_stu->all_scores) / 4.0;
				new_stu->next = head->next;
				head->next = new_stu;
			}
		}
		fclose(ffp);
		printf("本次文件读取成功,请勿重复读取文件!!!\n");
		frequency = 0;
	}
	else
		printf("请勿多次读取文件!!!\n");
	break;
}
这部分代码的主要功能是从一个文件中读取学生的信息,并将这些信息添加到链表中。以下是详细的步骤:
  1. if (frequency) { ... }:这个if语句检查frequency变量的值。如果frequency为非零值(在这个代码中,它被初始化为1),则执行大括号内的代码。这意味着文件只能被读取一次。一旦文件被读取,frequency就会被设置为0,以防止再次读取。
  2. FILE* ffp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "r");:这行代码打开一个名为“无标题.txt”的文件,该文件位于“D:\Shelly\OneDrive\桌面”目录下。"r"表示以只读模式打开文件。
  3. fseek(fp, 0, SEEK_SET);:这行代码将文件指针fp移动到文件的开始位置。
  4. struct stu student;:这行代码声明了一个stu结构体的实例student
  5. while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n", ... ) != EOF) { ... }:这个while循环从文件中读取学生的信息,直到到达文件的末尾。每次循环,它都会读取一个学生的所有信息,并将这些信息存储在student结构体中。
  6. int k = student.number;:这行代码将学生的学号存储在变量k中。
  7. struct stu* p; p = head;:这两行代码声明了一个指向stu结构体的指针p,并将其初始化为指向链表的头部。
  8. for (p; p; p = p->next) { ... }:这个for循环遍历链表,查找是否已经存在学号为k的学生。
  9. if (index) { continue; } else { ... }:如果找到了学号为k的学生(即index为1),则跳过当前循环,不会将该学生的信息添加到链表中。否则,将创建一个新的stu结构体实例,并将其添加到链表的开头。
  10. fclose(ffp);:这行代码关闭了文件。
  11. printf("本次文件读取成功,请勿重复读取文件!!!\n");:这行代码打印出一条消息,告知用户文件已经成功读取。
  12. frequency = 0;:这行代码将frequency设置为0,以防止再次读取文件。
事实上,为了防止重复读取文件时信息重复化,它被设置为了只允许读一次。

三:增加学生信息

case 1:
{
	struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
	printf("请输入学生姓名:");
	scanf("%s", new_stu->name);
	printf("请输入学生学号:");
	scanf("%s", &(new_stu->number));
	printf("请输入学生年龄:");
	scanf("%d", &(new_stu->age));
	printf("请输入学生性别(M/F):");
	scanf(" %c", &(new_stu->sex));
	printf("请输入数学成绩:");
	scanf("%d", &(new_stu->subject.math));
	printf("请输入计算机成绩:");
	scanf("%d", &(new_stu->subject.computer));
	printf("请输入英语成绩:");
	scanf("%d", &(new_stu->subject.English));
	printf("请输入体育成绩:");
	scanf("%d", &(new_stu->subject.PE));
	new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
	new_stu->average_scores = (new_stu->all_scores) / 4;
	new_stu->next = head->next;
	head->next = new_stu;
	fprintf(fp, "姓名:%s ", new_stu->name);
	fprintf(fp, "学号:%s ", new_stu->number);
	fprintf(fp, "年龄:%d ", new_stu->age);
	fprintf(fp, "性别:%c ", new_stu->sex);
	fprintf(fp, "数学成绩:%d ", new_stu->subject.math);
	fprintf(fp, "计算机成绩:%d ", new_stu->subject.computer);
	fprintf(fp, "英语成绩:%d ", new_stu->subject.English);
	fprintf(fp, "体育成绩:%d ", new_stu->subject.PE);
	fprintf(fp, "总分:%d ", new_stu->all_scores);
	fprintf(fp, "平均分:%d \n", new_stu->average_scores);
	fseek(fp, 0, SEEK_SET);
	system("cls");
	printf("添加学生成功!!!\n");
	break;
}
  1. struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));:这行代码创建了一个新的stu结构体实例new_stu
  2. printf("请输入学生姓名:"); scanf("%s", new_stu->name);等:这些行代码从用户那里获取学生的信息,包括姓名、学号、年龄、性别和各科成绩,并将这些信息存储在new_stu结构体中。
  3. new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;:这行代码计算了学生的总成绩。
  4. new_stu->average_scores = (new_stu->all_scores) / 4;:这行代码计算了学生的平均成绩。
  5. new_stu->next = head->next; head->next = new_stu;:这两行代码将new_stu添加到链表的开头。
  6. fprintf(fp, "姓名:%s ", new_stu->name);等:这些行代码将学生的信息写入一个文件。
  7. fseek(fp, 0, SEEK_SET);:这行代码将文件指针fp移动到文件的开始位置,防止覆盖。
  8. system("cls");:这行代码清除了控制台的屏幕。
  9. printf("添加学生成功!!!\n");:这行代码打印出一条消息,告知用户学生的信息已经成功添加。

四:查询学生信息

case 2:
{
	fseek(fp, 0, SEEK_SET);
	printf("请选择你的查询方式:\n");
	printf("C(学号查询)||N(姓名查询)\n");
	char c;
	int index = 0;
	scanf(" %c", &c);
	struct stu student;
	if (c == 'C') {
		printf("请输入要查找学生的学号:\n");
		char k[20];
		scanf("%s", k);
		while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
			student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
			&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
			if (strcmp(student.number, k) == 0) {
				index = 1;
				break;
			}
		}

}
if (c == 'N') {
	char search_name[100];
	printf("请输入要查找的学生姓名:");
	scanf("%s", search_name);
	while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
		student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
		&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
		if (strcmp(student.name, search_name) == 0) {
			index = 1;
			break;
		}
	}
}
if (index == 0) {
	printf("该学生不存在\n");
	break;
}
else {
	printf("姓名:%s ", student.name);
	printf("学号:%s ", student.number);
	printf("年龄:%d ", student.age);
	printf("性别:%c ", student.sex);
	printf("数学成绩:%d ", student.subject.math);
	printf("计算机成绩:%d ", student.subject.computer);
	printf("英语成绩:%d ", student.subject.English);
	printf("体育成绩:%d ", student.subject.PE);
	printf("总分:%d ", student.all_scores);
	printf("平均分:%d\n", student.average_scores);
	break;
}
}
  1. fseek(fp, 0, SEEK_SET);:这行代码将文件指针fp移动到文件的开始位置,防止遗漏。
  2. printf("请选择你的查询方式:\n"); printf("C(学号查询)||N(姓名查询)\n");:这两行代码打印出一个提示,让用户选择查询方式,可以通过学号(C)或姓名(N)进行查询。
  3. char c; int index = 0; scanf(" %c", &c);:这些代码声明了一个字符变量c和一个整型变量index,然后从用户那里获取一个字符输入并存储在c中。index被初始化为0,用于标记是否找到了学生。
  4. struct stu student;:这行代码声明了一个stu结构体的实例student
  5. if (c == 'C') { ... }:如果用户输入的是’C’,则执行大括号内的代码。这部分代码从文件中读取学生的信息,直到找到学号与用户输入相匹配的学生或到达文件的末尾。
  6. if (c == 'N') { ... }:如果用户输入的是’N’,则执行大括号内的代码。这部分代码从文件中读取学生的信息,直到找到姓名与用户输入相匹配的学生或到达文件的末尾。
  7. if (index == 0) { ... } else { ... }:如果index仍为0,说明没有找到匹配的学生,打印出“该学生不存在”。否则,打印出找到的学生的所有信息。

五:删除学生信息

case 3:
{
	printf("请确保在删除前读取过文件!!!\n");
	printf("请输入您想要删除学生的学号:\n");
	char del_number[20];
	getchar();
	gets(del_number);
	struct stu* p = head;
	struct stu* temp;
	int index = 0;
	for (p; p->next; p = p->next) {
		if (strcmp(p->next->number, del_number) == 0) {
			temp = p->next;
			p->next = p->next->next;
			free(temp);
			index = 1;
			break;
		}
	}
	if (index == 0) {
		printf("该学生不存在!");
	}
	else {
		fclose(fp);
		fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
		if (fp == NULL) {
			printf("文件打开失败!\n");
			return;
		}
		for (p = head->next; p != NULL; p = p->next) {
			fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
				p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
			fflush(fp);
		}
	}
	system("cls");
	printf("删除学生成功!!!\n");
	break;
}
  1. printf("请确保在删除前读取过文件!!!\n");:这行代码打印出一条消息,提醒用户在删除学生信息前需要先读取文件。
  2. printf("请输入您想要删除学生的学号:\n");:这行代码打印出一条消息,提示用户输入要删除的学生的学号。
  3. char del_number[20]; getchar(); gets(del_number);:这些代码声明了一个字符数组del_number,然后从用户那里获取一个字符串输入并存储在del_number中。
  4. struct stu* p = head; struct stu* temp; int index = 0;:这些代码声明了两个指向stu结构体的指针ptemp,以及一个整型变量indexp被初始化为指向链表的头部,index被初始化为0,用于标记是否找到了学生。
  5. for (p; p->next; p = p->next) { ... }:这个for循环遍历链表,查找学号与用户输入相匹配的学生。
  6. if (strcmp(p->next->number, del_number) == 0) { ... }:如果找到了学号与用户输入相匹配的学生,则执行大括号内的代码。这部分代码删除了找到的学生节点,并释放了其占用的内存。
  7. if (index == 0) { ... } else { ... }:如果index仍为0,说明没有找到匹配的学生,打印出“该学生不存在”。否则,关闭并重新打开文件,然后将链表中剩余的学生信息写入文件。
  8. system("cls");:这行代码清除了控制台的屏幕。

六:修改学生信息

case 4:
{
	printf("请确保在修改前读取过文件!!!\n");
	printf("请输入您想要修改学生信息的学号:\n");
	char mod_number[20];
	getchar();
	gets(mod_number);
	struct stu* p = head;
	struct stu* temp;
	int index = 0;
	for (p; p->next; p = p->next) {
		if (strcmp(p->next->number, mod_number) == 0) {
			temp = p->next;
			p->next = p->next->next;
			free(temp);
			index = 1;
			break;
		}
	}
	if (index == 0) {
		printf("该学生不存在!");
	}
	else {
		printf("请输入修改后的信息:\n");
		struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
		printf("请输入学生姓名:");
		scanf("%s", new_stu->name);
		printf("请输入学生学号:");
		scanf("%s", &(new_stu->number));
		printf("请输入学生年龄:");
		scanf("%d", &(new_stu->age));
		printf("请输入学生性别(M/F):");
		scanf(" %c", &(new_stu->sex));
		printf("请输入数学成绩:");
		scanf("%d", &(new_stu->subject.math));
		printf("请输入计算机成绩:");
		scanf("%d", &(new_stu->subject.computer));
		printf("请输入英语成绩:");
		scanf("%d", &(new_stu->subject.English));
		printf("请输入体育成绩:");
		scanf("%d", &(new_stu->subject.PE));
		new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
		new_stu->average_scores = (new_stu->all_scores) / 4;
		new_stu->next = head->next;
		head->next = new_stu;
		fclose(fp);
		fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
		for (p = head->next; p != NULL; p = p->next) {
			fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
				p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
		}
	}
break;
}
本质上就是删除再添加,就不再赘述了。

七:显示学生信息

case 6: {
	system("cls");
	struct stu* p = head->next;
	while (p != NULL) {
		printf("姓名:%s ", p->name);
		printf("学号:%s ", p->number);
		printf("年龄:%d ", p->age);
		printf("性别:%c ", p->sex);
		printf("数学成绩:%d ", p->subject.math);
		printf("计算机成绩:%d ", p->subject.computer);
		printf("英语成绩:%d ", p->subject.English);
		printf("体育成绩:%d ", p->subject.PE);
		printf("总分:%d ", p->all_scores);
		printf("平均分:%d\n", p->average_scores);
		p = p->next;
	}
	break;
}
按照链表顺序(无排序)输出。

八:按照总分排序:

链表的排序较为复杂,所以我们采用其他方式:
case 7: {
	system("cls");
	struct stu* p = head->next;
	if (p == NULL) {
		printf("学生信息为空!请检查是否读入文件!!!\n");
}
else {
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->all_scores;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->all_scores == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("数学成绩:%d ", p->subject.math);
				printf("计算机成绩:%d ", p->subject.computer);
				printf("英语成绩:%d ", p->subject.English);
				printf("体育成绩:%d ", p->subject.PE);
				printf("总分:%d ", p->all_scores);
				printf("平均分:%d\n", p->average_scores);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}
	break;
}
}
  1. system("cls");:这行代码清除了控制台的屏幕。
  2. struct stu* p = head->next;:这行代码声明了一个指向stu结构体的指针p,并将其初始化为指向链表的第一个节点。
  3. if (p == NULL) { ... } else { ... }:这个if语句检查链表是否为空。如果链表为空(即p为NULL),则打印出一条消息,提示用户检查是否已经读取了文件。否则,执行大括号内的代码。
  4. int k = 0; int arr[1000] = { 0 };:这两行代码声明了一个整型变量k和一个整型数组arrk被初始化为0,用于记录链表中的学生数量。arr被初始化为全0,用于存储学生的总分。
  5. while (p) { ... }:这个while循环遍历链表,将每个学生的总分存储在arr数组中,并将每个学生的idx字段设置为1。
  6. while (q) { ... }:这个while循环对arr数组进行冒泡排序,使得数组中的元素按照降序排列。
  7. while (j) { ... }:这个while循环遍历链表,并按照arr数组中的顺序打印出学生的信息。
  8. if (p->idx == 1 && p->all_scores == arr[i]) { ... }:如果找到了总分与arr[i]相等的学生(即p->idx为1),则打印出该学生的所有信息,并将p->idx设置为0。

九:不合格检索

case 9: {
	struct stu* p = head->next;
	int k = 1;
	while (p) {
		if (p->subject.math < 90||p->subject.computer<90||p->subject.PE<60||p->subject.English<90) {
			k = 0;
			printf("姓名:%s 学号:%s ", p->name, p->number);
			if (p->subject.math < 90) {
				printf("数学成绩:%d ", p->subject.math);
			}
			if (p->subject.computer < 90) {
				printf("计算机成绩:%d ", p->subject.computer);
			}
			if (p->subject.PE < 60) {
				printf("体育成绩:%d ", p->subject.PE);
			}
			if (p->subject.English < 90) {
				printf("英语成绩:%d ", p->subject.English);
			}
			printf("\n");
		}
p = p->next;
}
if (k) {
	printf("未检索到不合格学生信息!!!\n");
}
break;
}
  1. struct stu* p = head->next;:这行代码声明了一个指向stu结构体的指针p,并将其初始化为指向链表的第一个节点。
  2. int k = 1;:这行代码声明了一个整型变量k,并将其初始化为1。k用于标记是否所有学生都合格。
  3. while (p) { ... }:这个while循环遍历链表中的每个学生。
  4. if (p->subject.math < 90||p->subject.computer<90||p->subject.PE<60||p->subject.English<90) { ... }:这个if语句检查学生是否不合格。如果学生的数学、计算机、体育或英语成绩低于一定的分数线,则认为学生不合格。
  5. printf("姓名:%s 学号:%s ", p->name, p->number);等:这些行代码打印出不合格学生的姓名、学号和不合格的科目成绩。
  6. p = p->next;:这行代码将p移动到链表的下一个节点。
  7. if (k) { ... }:如果所有学生都合格(即k仍为1),则打印出一条消息,告知用户未检索到不合格学生信息。

十:学科详情

case 10: {
	system("cls");
	struct stu* p = head->next;
	printf("请选择你要查看的学科:\n");
	printf("1.math   2.computer  3.English  4.PE\n");
	int a;
	scanf("%d", &a);
	if (a != 1 && a != 2 && a != 3 && a != 4) {
		printf("您的输入不规范!!!\n");
		break;
	}
	if (p == NULL) {
		printf("学生信息为空!请检查是否读入文件!!!\n");

}
switch (a) {
case 1: {
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->subject.math;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->subject.math == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("数学成绩:%d \n", p->subject.math);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}
	break;
}
case 2: {
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->subject.computer;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->subject.computer == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("计算机成绩:%d \n", p->subject.computer);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}

break;

}
case 3: {
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->subject.English;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->subject.English == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("英语成绩:%d \n", p->subject.English);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}

break;

}
case 4:{
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->subject.PE;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->subject.PE == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("体育成绩:%d \n", p->subject.PE);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}
	break;

}
}
	break;
}
  1. system("cls");:这行代码清除了控制台的屏幕。
  2. struct stu* p = head->next;:这行代码声明了一个指向stu结构体的指针p,并将其初始化为指向链表的第一个节点。
  3. printf("请选择你要查看的学科:\n"); printf("1.math 2.computer 3.English 4.PE\n");:这两行代码打印出一个提示,让用户选择要查看的学科。
  4. int a; scanf("%d", &a);:这两行代码声明了一个整型变量a,然后从用户那里获取一个整数输入并存储在a中。
  5. if (a != 1 && a != 2 && a != 3 && a != 4) { ... }:这个if语句检查用户的输入是否规范。如果用户输入的不是1、2、3或4,则打印出一条消息,提示用户输入不规范,并跳出switch语句。
  6. if (p == NULL) { ... }:这个if语句检查链表是否为空。如果链表为空(即p为NULL),则打印出一条消息,提示用户检查是否已经读取了文件。
  7. switch (a) { ... }:这个switch语句根据用户的输入选择要查看的学科。
  8. case 1: { ... }等:这些case语句处理不同的学科。对于每个学科,都会遍历链表,将学生的成绩存储在arr数组中,并将每个学生的idx字段设置为1。然后,对arr数组进行冒泡排序,使得数组中的元素按照降序排列。最后,再次遍历链表,并按照arr数组中的顺序打印出学生的信息。

十一:一些小彩蛋

case 11: {
	printf("请输入指令:\n");
	char str[10];
	getchar();
	gets(str);
	if (strcmp(str, "SWPU") == 0) {
		ShellExecuteA(0, "open", "https://www.swpu.edu.cn/", 0, 0, 1);
	}
	else
	{
		printf("您的指令不正确哦!!!\n");
	}
break;
}
在这个case中,程序首先会提示用户输入指令,然后使用gets函数获取用户输入的字符串。接着程序会使用strcmp函数比较用户输入的字符串是否等于"SWPU",如果相等则会调用ShellExecuteA函数打开西南石油大学的官方网站。如果用户输入的字符串不等于"SWPU",则会输出提示信息"您的指令不正确哦!!!"。
当然,要是放个原神网页在这里也可以哦。

十二:退出系统与输入判别

case 0:
{
	fclose(fp);
	printf("正在为您退出系统.\n");
	return 0;
}
default:{
	printf("您的输入无效,请重新输入:\n");
	break;
        }

最后是完整的代码:

ps:不会有人不会改文件路径吧(doge)
用来应付期末作业那是大大的足够了:
#include 
#include 
#include 
#include 
struct course {
	int math;
	int computer;
	int English;
	int PE;
};
struct stu {
	char name[100];
	int age;
	char sex;
	struct course subject;
	struct stu* next;
	char number[20];
	int all_scores;
	int average_scores;
	int idx;
};
void menu(void) {
	printf("**************************\n"
		"***学生管理系统*******\n"
		"**************************\n"
		"***系统功能菜单*******\n"
		"--------------------------\n"
		"**************************\n"
		"***   1.增加学生信息   ***\n"//ok
		"***   2.查询学生信息   ***\n"//ok
		"***   3.删除学生信息   ***\n"//ok
		"***   4.修改学生信息   ***\n"//ok
		"*****   5.读取文件   *****\n"//ok
		"***   6.显示学生信息   ***\n"//ok
		"*****   7.总分详情   *****\n"//ok
		"******  8.菜单帮助   *****\n"//ok
		"   9.不合格检索   \n"//ok
		"    10.学科详情   \n"//ok
		"    11.学校主页   \n"//ok
		"*****   0.退出系统   *****\n"//ok
	);
}
int main() {
	FILE* fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "a+");
	int n;
	struct stu* head = (struct stu*)malloc(sizeof(struct stu));
	head->next = NULL;
	menu();
	fseek(fp, 0, SEEK_SET);
	int frequency = 1;
	printf("\n请您先读取文件!!!\n");
	printf("\n请您先读取文件!!!\n");
	printf("\n请您先读取文件!!!\n");
	while (1) {
printf("\n请输入菜单编号:\n");
scanf("%d", &n);
switch (n) {
case 1:
{
	struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
	printf("请输入学生姓名:");
	scanf("%s", new_stu->name);
	printf("请输入学生学号:");
	scanf("%s", &(new_stu->number));
	printf("请输入学生年龄:");
	scanf("%d", &(new_stu->age));
	printf("请输入学生性别(M/F):");
	scanf(" %c", &(new_stu->sex));
	printf("请输入数学成绩:");
	scanf("%d", &(new_stu->subject.math));
	printf("请输入计算机成绩:");
	scanf("%d", &(new_stu->subject.computer));
	printf("请输入英语成绩:");
	scanf("%d", &(new_stu->subject.English));
	printf("请输入体育成绩:");
	scanf("%d", &(new_stu->subject.PE));
	new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
	new_stu->average_scores = (new_stu->all_scores) / 4;
	new_stu->next = head->next;
	head->next = new_stu;
	fprintf(fp, "姓名:%s ", new_stu->name);
	fprintf(fp, "学号:%s ", new_stu->number);
	fprintf(fp, "年龄:%d ", new_stu->age);
	fprintf(fp, "性别:%c ", new_stu->sex);
	fprintf(fp, "数学成绩:%d ", new_stu->subject.math);
	fprintf(fp, "计算机成绩:%d ", new_stu->subject.computer);
	fprintf(fp, "英语成绩:%d ", new_stu->subject.English);
	fprintf(fp, "体育成绩:%d ", new_stu->subject.PE);
	fprintf(fp, "总分:%d ", new_stu->all_scores);
	fprintf(fp, "平均分:%d \n", new_stu->average_scores);
	fseek(fp, 0, SEEK_SET);
	system("cls");
	printf("添加学生成功!!!\n");
	break;
}
case 2:
{
	fseek(fp, 0, SEEK_SET);
	printf("请选择你的查询方式:\n");
	printf("C(学号查询)||N(姓名查询)\n");
	char c;
	int index = 0;
	scanf(" %c", &c);
	struct stu student;
	if (c == 'C') {
		printf("请输入要查找学生的学号:\n");
		char k[20];
		scanf("%s", k);
		while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
			student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
			&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
			if (strcmp(student.number, k) == 0) {
				index = 1;
				break;
			}
		}

}
if (c == 'N') {
	char search_name[100];
	printf("请输入要查找的学生姓名:");
	scanf("%s", search_name);
	while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
		student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
		&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
		if (strcmp(student.name, search_name) == 0) {
			index = 1;
			break;
		}
	}
}
if (index == 0) {
	printf("该学生不存在\n");
	break;
}
else {
	printf("姓名:%s ", student.name);
	printf("学号:%s ", student.number);
	printf("年龄:%d ", student.age);
	printf("性别:%c ", student.sex);
	printf("数学成绩:%d ", student.subject.math);
	printf("计算机成绩:%d ", student.subject.computer);
	printf("英语成绩:%d ", student.subject.English);
	printf("体育成绩:%d ", student.subject.PE);
	printf("总分:%d ", student.all_scores);
	printf("平均分:%d\n", student.average_scores);
	break;
}
}
case 3:
{
	printf("请确保在删除前读取过文件!!!\n");
	printf("请输入您想要删除学生的学号:\n");
	char del_number[20];
	getchar();
	gets(del_number);
	struct stu* p = head;
	struct stu* temp;
	int index = 0;
	for (p; p->next; p = p->next) {
		if (strcmp(p->next->number, del_number) == 0) {
			temp = p->next;
			p->next = p->next->next;
			free(temp);
			index = 1;
			break;
		}
	}
	if (index == 0) {
		printf("该学生不存在!");
	}
	else {
		fclose(fp);
		fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
		if (fp == NULL) {
			printf("文件打开失败!\n");
			return;
		}
		for (p = head->next; p != NULL; p = p->next) {
			fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
				p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
			fflush(fp);
		}
	}
	system("cls");
	printf("删除学生成功!!!\n");
	break;
}

case 4:
{
	printf("请确保在修改前读取过文件!!!\n");
	printf("请输入您想要修改学生信息的学号:\n");
	char mod_number[20];
	getchar();
	gets(mod_number);
	struct stu* p = head;
	struct stu* temp;
	int index = 0;
	for (p; p->next; p = p->next) {
		if (strcmp(p->next->number, mod_number) == 0) {
			temp = p->next;
			p->next = p->next->next;
			free(temp);
			index = 1;
			break;
		}
	}
	if (index == 0) {
		printf("该学生不存在!");
	}
	else {
		printf("请输入修改后的信息:\n");
		struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
		printf("请输入学生姓名:");
		scanf("%s", new_stu->name);
		printf("请输入学生学号:");
		scanf("%s", &(new_stu->number));
		printf("请输入学生年龄:");
		scanf("%d", &(new_stu->age));
		printf("请输入学生性别(M/F):");
		scanf(" %c", &(new_stu->sex));
		printf("请输入数学成绩:");
		scanf("%d", &(new_stu->subject.math));
		printf("请输入计算机成绩:");
		scanf("%d", &(new_stu->subject.computer));
		printf("请输入英语成绩:");
		scanf("%d", &(new_stu->subject.English));
		printf("请输入体育成绩:");
		scanf("%d", &(new_stu->subject.PE));
		new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
		new_stu->average_scores = (new_stu->all_scores) / 4;
		new_stu->next = head->next;
		head->next = new_stu;
		fclose(fp);
		fp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "w+");
		for (p = head->next; p != NULL; p = p->next) {
			fprintf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
				p->name, p->number, p->age, p->sex, p->subject.math, p->subject.computer, p->subject.English, p->subject.PE, p->all_scores, p->average_scores);
		}
	}

	break;

}
case 5: {
	if (frequency) {
		FILE* ffp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "r");
		fseek(fp, 0, SEEK_SET);
		struct stu student;
		while (fscanf(fp, "姓名:%s 学号:%s 年龄:%d 性别:%c 数学成绩:%d 计算机成绩:%d 英语成绩:%d 体育成绩:%d 总分:%d 平均分:%d\n",
			student.name, &(student.number), &(student.age), &(student.sex), &(student.subject.math), &(student.subject.computer),
			&(student.subject.English), &(student.subject.PE), &(student.all_scores), &(student.average_scores)) != EOF) {
			int k = student.number;
			struct stu* p;
			p = head;
			int index = 0;
			for (p; p; p = p->next) {
				if (p->number == k) {
					index = 1;
					break;
				}
			}
			if (index) {
				continue;
			}
			else
			{
				struct stu* new_stu = (struct stu*)malloc(sizeof(struct stu));
				strcpy(new_stu->name, student.name);
				strcpy(new_stu->number, student.number);
				new_stu->age = student.age;
				new_stu->sex = student.sex;
				new_stu->subject.math = student.subject.math;
				new_stu->subject.computer = student.subject.computer;
				new_stu->subject.English = student.subject.English;
				new_stu->subject.PE = student.subject.PE;
				new_stu->all_scores = new_stu->subject.math + new_stu->subject.computer + new_stu->subject.PE + new_stu->subject.English;
				new_stu->average_scores = (new_stu->all_scores) / 4.0;
				new_stu->next = head->next;
				head->next = new_stu;
			}
		}
		fclose(ffp);
		printf("本次文件读取成功,请勿重复读取文件!!!\n");
		frequency = 0;
	}
	else
		printf("请勿多次读取文件!!!\n");
	break;
}
case 6: {
	system("cls");
	struct stu* p = head->next;
	while (p != NULL) {
		printf("姓名:%s ", p->name);
		printf("学号:%s ", p->number);
		printf("年龄:%d ", p->age);
		printf("性别:%c ", p->sex);
		printf("数学成绩:%d ", p->subject.math);
		printf("计算机成绩:%d ", p->subject.computer);
		printf("英语成绩:%d ", p->subject.English);
		printf("体育成绩:%d ", p->subject.PE);
		printf("总分:%d ", p->all_scores);
		printf("平均分:%d\n", p->average_scores);
		p = p->next;
	}
	break;
}
case 7: {
	system("cls");
	struct stu* p = head->next;
	if (p == NULL) {
		printf("学生信息为空!请检查是否读入文件!!!\n");

}
else {
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->all_scores;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->all_scores == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("数学成绩:%d ", p->subject.math);
				printf("计算机成绩:%d ", p->subject.computer);
				printf("英语成绩:%d ", p->subject.English);
				printf("体育成绩:%d ", p->subject.PE);
				printf("总分:%d ", p->all_scores);
				printf("平均分:%d\n", p->average_scores);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}
	break;
}}

case 8: {
	menu();
	break;
}
case 9: {
	struct stu* p = head->next;
	int k = 1;
	while (p) {
		if (p->subject.math < 90||p->subject.computer<90||p->subject.PE<60||p->subject.English<90) {
			k = 0;
			printf("姓名:%s 学号:%s ", p->name, p->number);
			if (p->subject.math < 90) {
				printf("数学成绩:%d ", p->subject.math);
			}
			if (p->subject.computer < 90) {
				printf("计算机成绩:%d ", p->subject.computer);
			}
			if (p->subject.PE < 60) {
				printf("体育成绩:%d ", p->subject.PE);
			}
			if (p->subject.English < 90) {
				printf("英语成绩:%d ", p->subject.English);
			}
			printf("\n");
		}
​	p = p->next;
}
if (k) {printf("未检索到不合格学生信息!!!\n");
}
break;
}
case 10: {
	system("cls");
	struct stu* p = head->next;
	printf("请选择你要查看的学科:\n");
	printf("1.math   2.computer  3.English  4.PE\n");
	int a;
	scanf("%d", &a);
	if (a != 1 && a != 2 && a != 3 && a != 4) {
		printf("您的输入不规范!!!\n");
		break;
	}
	if (p == NULL) {
		printf("学生信息为空!请检查是否读入文件!!!\n");

}
switch (a) {
case 1: {
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->subject.math;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->subject.math == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("数学成绩:%d \n", p->subject.math);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}
	break;
}
case 2: {
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->subject.computer;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->subject.computer == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("计算机成绩:%d \n", p->subject.computer);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}break;
}
case 3: {int k = 0;int arr[1000] = { 0 };while (p) {
​		arr[k] = p->subject.English;
​		p->idx = 1;
​		p = p->next;
​		k++;}int q = k;while (q) {for (int i = 0; i < q - 1; i++) {if (arr[i] < arr[i + 1]) {int c = arr[i];
​				arr[i] = arr[i + 1];
​				arr[i + 1] = c;}}
​		q--;}int j = k, i = 0;while (j) {
​		p = head->next;for (p; p; p = p->next) {if (p->idx == 1 && p->subject.English == arr[i]) {printf("姓名:%s ", p->name);printf("学号:%s ", p->number);printf("英语成绩:%d \n", p->subject.English);
​				p->idx = 0;
​				i++;}}
​		j--;}break;
}
case 4:{
	int k = 0;
	int arr[1000] = { 0 };
	while (p) {
		arr[k] = p->subject.PE;
		p->idx = 1;
		p = p->next;
		k++;
	}
	int q = k;
	while (q) {
		for (int i = 0; i < q - 1; i++) {
			if (arr[i] < arr[i + 1]) {
				int c = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = c;
			}
		}
		q--;
	}
	int j = k, i = 0;
	while (j) {
		p = head->next;
		for (p; p; p = p->next) {
			if (p->idx == 1 && p->subject.PE == arr[i]) {
				printf("姓名:%s ", p->name);
				printf("学号:%s ", p->number);
				printf("体育成绩:%d \n", p->subject.PE);
				p->idx = 0;
				i++;
			}
		}
		j--;
	}
	break;

}
}
	break;
}
case 11: {
	printf("请输入指令:\n");
	char str[10];
	getchar();
	gets(str);
	if (strcmp(str, "SWPU") == 0) {
		ShellExecuteA(0, "open", "https://www.swpu.edu.cn/", 0, 0, 1);
	}
	else
	{
		printf("您的指令不正确哦!!!\n");
	}
break;
}
case 0:
{
	fclose(fp);
	printf("正在为您退出系统.\n");
	return 0;
}
default:
	printf("您的输入无效,请重新输入:\n");
	break;
}
}
return 0;
}

你可能感兴趣的:(c语言,开发语言)