C语言实现学生管理系统

131 阅读7分钟
#include <stdlib.h>
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
               "*****   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);
	
	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\n", new_stu->name);
			fprintf(fp, "学号:%s\n", new_stu->number);
			fprintf(fp, "年龄:%d\n", new_stu->age);
			fprintf(fp, "性别:%c\n", new_stu->sex);
			fprintf(fp, "数学成绩:%d\n", new_stu->subject.math);
			fprintf(fp, "计算机成绩:%d\n", new_stu->subject.computer);
			fprintf(fp, "英语成绩:%d\n", new_stu->subject.English);
			fprintf(fp, "体育成绩:%d\n", new_stu->subject.PE);
			fprintf(fp, "总分:%d\n", new_stu->all_scores);
			fprintf(fp, "平均分:%d\n\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\n学号:%s\n年龄:%d\n性别:%c\n数学成绩:%d\n计算机成绩:%d\n英语成绩:%d\n体育成绩:%d\n总分:%d\n平均分:%d\n\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\n学号:%s\n年龄:%d\n性别:%c\n数学成绩:%d\n计算机成绩:%d\n英语成绩:%d\n体育成绩:%d\n总分:%d\n平均分:%d\n\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\n", student.name);
				printf("学号:%s\n", student.number);
				printf("年龄:%d\n", student.age);
				printf("性别:%c\n", student.sex);
				printf("数学成绩:%d\n", student.subject.math);
				printf("计算机成绩:%d\n", student.subject.computer);
				printf("英语成绩:%d\n", student.subject.English);
				printf("体育成绩:%d\n", student.subject.PE);
				printf("总分:%d\n", 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\n学号:%s\n年龄:%d\n性别:%c\n数学成绩:%d\n计算机成绩:%d\n英语成绩:%d\n体育成绩:%d\n总分:%d\n平均分:%d\n\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\n学号:%s\n年龄:%d\n性别:%c\n数学成绩:%d\n计算机成绩:%d\n英语成绩:%d\n体育成绩:%d\n总分:%d\n平均分:%d\n\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: {
			FILE* ffp = fopen("D:\\Shelly\\OneDrive\\桌面\\无标题.txt", "r");
			fseek(fp, 0, SEEK_SET);
			struct stu student;
			while (fscanf(fp, "姓名:%s\n学号:%s\n年龄:%d\n性别:%c\n数学成绩:%d\n计算机成绩:%d\n英语成绩:%d\n体育成绩:%d\n总分:%d\n平均分:%d\n\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");
			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 0:
			{
			fclose(fp);
			printf("正在为您退出系统.\n");
				return 0;
			}
		default:
			printf("您的输入无效,请重新输入:\n");
			break;
		}
	}
	return 0;
}

尚未解决的问题: 第一,我在学科和学生信息中设置的元素过多,没有考虑到,如果是竖着排版的话,会影响阅读,解决方案的话控制换行符和格式化输出一下就可以解决,目前已解决,不过个人觉得还是不够美。

第二个问题,我对部分非法输入进行了判别,还有部分非法输入,例如,在写入成绩的时候,如果不小心输了字母,会导致文件读写出错,解决的方案是将int类型转换为char类型,并且判断输入的是否符合格式,不符直接打回。

第三个问题,按要求应该是用函数,而不是全部写在main函数中,不过我个人觉得这种case分支,阅读和修改起来也不是很麻烦,解决方案的话,就是改为函数形式就行了。

第四个问题,起初我没有考虑到,如果是重名怎么办?当然,我修改了这个问题,所以后续的操作基本上都是学号进行,但是我保留了查询学生中的姓名查询,毕竟能让功能看起来更多样化一点,解决方案就是删除这一部分,或者说让他一直读下去,读到EOF为止。

第五个问题,本系统支持文件读写,事实上,即使在文件中,存在学生的信息,如果不提前按5,进行读入那么链表是空的,这就是如果写的是函数接口的好处,这样可以直接在开头处进行一次调用,我的解决方案就是引导用户来按下这个5。