C语言学生管理系统二次开发

  1. 代码来源
    管理系统来自于舍友写的一份关于C语言学生管理系统期末作业
  2. 环境
    系统:win11
    工具:dv-c++
    原代码:
点击查看代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//需要用到strcmp函数 

#define LEN 15//姓名和学号的最大字符数 
#define N 50//最大学生人数

int n = 0, t = 1;//n代表当前学生人数,t用来控制整个程序的执行,以及程序的退出; 

//函数声明
void menu();//主菜单函数 
void help();//使用帮助 
void increase();//增加学生信息  
void seek();//查找学生信息
void de();//删除学生信息 
void save();//保存文件
void present();//显示当前信息
void modify();//修改学生信息   
void flush();//刷新学生成绩 
void tuichu();//退出函数 

struct student
{
	char StuID[LEN];//学生学号 
	char Stuname[LEN];
	int Stuage;
	char Stusex;
	float score[3]; //各科成绩 
}stu[N];

int main()
{
	int num;//num是菜单选项 
	while (t)//t是全局变量,用tuichu函数来控制循环是否继续 
	{
		menu();//输出主菜单界面 
		printf("您好,请输入菜单编号:");
		scanf("%d", &num);
		switch (num)
		{
		case 1: help(); break;
		case 2: increase(); break;
		case 3: seek(); break;
		case 4: de(); break;
		case 5: save(); break;
		case 6: present(); break;
		case 7: modify(); break;
		case 8: flush(); break;
		case 9: tuichu(); break;
		default:printf("输入有误,请重新输入!");
		}


	}

	system("pause");
	return 0;
}
void menu()
{
	printf("\n\n");
	printf("*****************************************************\n");
	printf("*----------------------duoduo------------------------\n");
	printf("*                 学生信息管理系统                  *\n");
	printf("*****************************************************\n");
	printf("********************系统功能菜单*********************\n");
	printf("----------------------     --------------------------\n");
	printf("*****************************************************\n");
	printf("**    1、使用帮助       *     2、增加学生信息      **\n");
	printf("*****************************************************\n");
	printf("**    3、查询学生信息   *     4、删除学生信息      **\n");
	printf("*****************************************************\n");
	printf("**    5、保存当前信息   *     6、显示当前信息      **\n");
	printf("*****************************************************\n");
	printf("**    7、修改学生信息   *     8、刷新学生信息      **\n");
	printf("*****************************************************\n");
	printf("**    9、退出系统       *                          **\n");
	printf("*************************                            \n");
	printf("----------------------     --------------------------\n");

}
void help()
{
	printf("\n这是一个学生信息管理系统,为了帮助您更快的了解使用它,请先仔细阅读以下注意事项:\n");
	printf("\n                  注意事项:                    \n ");
	printf("\n       1、请根据提示进行操作!\n");
	printf("\n       2、初次使用请先选择增加学生信息!\n");
	printf("\n       3、修改或者增加学生信息后切记保存!\n");
	printf("\n       4、如果数据有错误,请先修改再保存!\n");
	printf("\n       5、若您之前使用过,下次进入系统请先刷新学生信息!\n");
	printf("\n       6、在添加学生时,用两个字符代表不同的性别,比如男用‘M’代替,女用‘W’代替!\n");
	printf("\n       7、保存或者刷新时,输入的文件名后缀请使用.txt,比如: stu.txt,系统会在源程序\n");
	printf("\n          “学生管理系统.exe”的相同目录建立一个.txt文件来保存学生信息,您可以查看\n");
	printf("\n          该文件,但非专业人员不要轻易改动,否则会造成刷新数据异常或刷新失败!\n");
	printf("\n       8、学生信息包括:姓名、学号、性别、年龄、C语言成绩、高数成绩、英语成绩等!\n");
	printf("\n       9、使用遇到任何问题请与我们联系,邮箱:ouyang_na_na@163.com\n");
	printf("\n       10、最后感谢您的使用!\n");
	system("pause");
}

void increase()
{
	int i = n, j, flag, m = 0;//i代表增加学生信息过程中任意时刻的学生人数 
	printf("\n请输入待增加的学生人数:\n");
	scanf("%d", &m);
	if (m > 0) {
		do {
			flag = 1;
			while (flag)
			{
				flag = 0;
				printf("请输入第%d位学生的学号:\n", i + 1);//第几位学生从1开始计数,而stu[]从零开始,需要加1 
				scanf("%s", stu[i].StuID);
				//判断学号是否重复
				for (j = 0; j < i; j++) {
					if (strcmp(stu[i].StuID, stu[j].StuID) == 0) {
						printf("该学号已经存在,请重新输入!\n");
						flag = 1;
						break;
					}
				}
			}
			printf("请输入第%d位学生姓名:\n", i + 1);
			scanf("%s", stu[i].Stuname);
			printf("请输入第%d位学生年龄:\n", i + 1);
			scanf("%d", &stu[i].Stuage);
			getchar();//处理上面输入的换行符,不然系统会把换行符当做一个字符赋值给性别 
			printf("请输入第%d位学生性别:\n", i + 1);
			scanf("%c", &stu[i].Stusex);
			printf("请输入第%d位学生的C语言成绩:\n", i + 1);
			scanf("%f", &stu[i].score[0]);
			printf("请输入第%d位学生的高数成绩:\n", i + 1);
			scanf("%f", &stu[i].score[1]);
			printf("请输入第%d位学生的大学英语成绩:\n", i + 1);
			scanf("%f", &stu[i].score[2]);
			i++;
		} while (i < n + m);//只要当前学生人数还没到达添加后的总人数,就得继续添加		
	}
	n += m;// 添加完成,系统人数n的值也要增加 
	printf("添加完成!!!\n");
	system("pause");
}
void seek()
{
	int i, num, flag;
	char s1[LEN + 1];
	printf("*****************************\n");
	printf("**-------1.按学号查询------**\n");
	printf("**-------2.按姓名查询------**\n");
	printf("**-------3.退出本菜单------**\n");
	printf("*****************************\n");
	while (1)
	{
		flag = 0;
		printf("请输入子菜单:");
		scanf("%d", &num);
		switch (num)
		{
		case 1:
			printf("请输入需要查找学生的学号:\n");
			scanf("%s", s1);
			for (i = 0; i < n; i++)
			{
				if (strcmp(stu[i].StuID, s1) == 0)
				{
					flag = 1;
					printf("学号\t\t姓名\t\t性别\t\t年龄\t\tC语言\t\t高数\t\t英语\n");
					printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n", stu[i].StuID, stu[i].Stuname, stu[i].Stusex, stu[i].Stuage, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
				}
			}break;
		case 2:
			printf("请输入需要查找学生的姓名:\n");
			scanf("%s", s1);
			for (i = 0; i < n; i++)
			{
				if (strcmp(stu[i].Stuname, s1) == 0)
				{
					flag = 1;
					printf("学号\t\t姓名\t\t性别\t\t年龄\t\tC语言\t\t高数\t\t英语\n");
					printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n", stu[i].StuID, stu[i].Stuname, stu[i].Stusex, stu[i].Stuage, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
				}
			}break;
		case 3: return;
		default: printf("请在1--3之间输入\n");
		}
		if (flag == 0)
			printf("找不到该学生!\n请重新输入!");
	}
}
void de()
{
	int i, j, flag;
	char s1[LEN];
	printf("请输入需要删除的学生学号:\n");
	scanf("%s", s1);
	flag = 0;
	for (i = 0; i < n; i++)
	{
		if (strcmp(s1, stu[i].StuID) == 0)
		{
			flag = 1;
			for (j = i; j < n - 1; j++)
			{
				stu[j] = stu[j + 1];//直接把后面的学生都往前移动一位 
			}
		}
		if (flag == 1) break;//说明已经找到了需要删除的学生,结束循环 
	}
	if (0 == flag)
	{
		printf("该学号不存在!!!\n");
	}

	if (1 == flag)
	{
		printf("删除成功\n");
		n--;
	}
	system("pause");
}

void save()//把学生信息保存到文件 
{
	int i;
	FILE* fp;
	char filename[LEN + 1];
	printf("请输入要保存的文件名:\n");
	scanf("%s", filename);
	if ((fp = fopen(filename, "w")) == NULL)
	{
		printf("打开文件失败!\n");
		exit(0);
	}
	for (i = 0; i < n; i++)
		if (fwrite(&stu[i], sizeof(struct student), 1, fp) != 1)
			printf("保存失败!!\n");
	printf("保存成功!!!\n");
	fclose(fp);
	system("pause");
}

void present()
{
	int i;

	if (n == 0)
	{
		printf("您好,现在没有学生信息,请先增加学生信息或者刷新再来试试!\n");
	}
	else
	{
		printf("现在共有%d名学生:\n", n);
		printf("学号\t\t姓名\t\t性别\t\t年龄\t\tC语言\t\t高数\t\t英语\n");
		for (i = 0; i < n; i++)
		{
			printf("%s\t\t%s\t\t%c\t\t%d\t\t%.2f\t\t%.2f\t\t%.2f\n", stu[i].StuID, stu[i].Stuname, stu[i].Stusex, stu[i].Stuage, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
		}
	}

	system("pause");
}

void modify()
{
	int i, flag;
	char ID[LEN], name[LEN], sex;
	int age;
	float score;
	printf("请输入需要修改的学生姓名:\n");
	getchar();
	gets(name);

	while (1)
	{
		flag = 0;
		for (i = 0; i < n; i++)
		{
			if (strcmp(name, stu[i].Stuname) == 0)
			{
				flag = 1;
				int num;//用于switch函数的子菜单 
				printf("***************************************************\n");
				printf("*----1.修改学号--------  -  -----2.修改性别-------*\n");
				printf("*----3.修改年龄--------  -  -----4.修改C语言成绩--*\n");
				printf("*----5.修改高数成绩----  -  -----6.修改英语成绩---*\n");
				printf("*-------------------7.退出本菜单------------------*\n");
				printf("***************************************************\n\n");
				printf("请输入子菜单:");
				scanf("%d", &num);
				switch (num)
				{
				case 1:
					printf("请输入新的学号:\n");
					getchar();
					gets(ID);
					strcpy(stu[i].StuID, ID); break;
				case 2:
					getchar();
					printf("请输入新的性别:\n");
					scanf("%c", &sex);
					stu[i].Stusex = sex; break;
				case 3:
					printf("请输入新的年龄:\n");
					scanf("%d", &age);
					stu[i].Stuage = age; break;
				case 4:
					printf("请输入新的C语言成绩:\n");
					scanf("%f", &score);
					stu[i].score[0] = score; break;
				case 5:
					printf("请输入新的高数成绩:\n");
					scanf("%f", &score);
					stu[i].score[1] = score; break;
				case 6:
					printf("请输入新的英语成绩:\n");
					scanf("%f", &score);
					stu[i].score[2] = score; break;
				case 7:
					return; break;
				default:
					printf("请在1--7之间选择!\n");
				}
				if (num > 0 && num < 7)
					printf("修改成功,记得保存哟!!!\n");
				break;//找到学生,结束循环;	
			}
		}
		if (flag == 0)
		{
			printf("没有找到该学生,请重新输入需要修改信息的学生姓名:\n");
			gets(name);
		}
	}
	system("pause");
}

void flush()
{
	int i, k = 0;//k代表刷新过程中学生人数 
	FILE* fp;
	char filename[LEN + 1];
	printf("请输入需要刷新的文件名:\n");
	getchar();
	gets(filename);
	if ((fp = fopen(filename, "r")) == NULL)//打开文件 
	{
		printf("打开文件失败!\n");
		exit(0);
	}
	for (i = 0; i < N; i++)//N是最大的学生人数,可在程序开头进行更改 
	{
		if (fread(&stu[i], sizeof(struct student), 1, fp) == 1)
			k++;//记录学生人数 
	}
	n = k;// 把k的值给n 
	if (k == 0)
		printf("刷新失败!!!\n");
	else
		printf("刷新成功!!!\n");
	fclose(fp);
	system("pause");

}
void tuichu()
{
	int h;//控制是否确认退出 
	printf("即将退出,确认请按1,取消请按0\n");
	scanf("%d", &h);
	if (h == 1)
	{
		t = 0;//t是main函数中while函数是否继续执行的控制条件,是一个全局变量,程序开头已经定义并且赋值位 1
		printf("成功退出,感谢使用!\n");
	}
	if (h == 0)
	{
		printf("退出已取消!\n");
		system("pause");
	}

}	
	



	


运行结果如下:
image
3. 源代码的问题以及重构思路

  • 安全性优化
    移除废弃函数gets(),改用scanf() + 输入缓冲区清理,避免缓冲区溢出;
    增加输入校验(如年龄必须为正整数、成绩范围 0-100、性别仅支持 M/W)。
  • 功能增强
    新增成绩统计:结构体增加total_score(总分)和avg_score(平均分)字段,新增calculate_scores()函数自动计算,查询 / 显示时同步展示;
    优化修改功能:原代码只能按姓名修改(易重复),改为按学号修改(唯一标识),修改成绩后自动重算总分 / 平均分;
    优化删除功能:增加删除前确认步骤,避免误删;
    优化加载功能:加载文件前清空原有数据,避免数据残留;
    交互体验提升:菜单排版优化、清屏操作、输入错误时的友好提示。
  • 代码规范优化
    变量 / 函数命名规范化:如current_student_count替换原n,load_info_from_file()替换原flush(),可读性大幅提升;
    增加typedef定义结构体别名Student,简化代码书写;
    提取通用校验逻辑为独立函数(is_id_exist()、validate_gender()、validate_score()),减少代码冗余。
  • 兼容性优化
    保存 / 加载文件时,先保存学生人数再保存数据,确保加载时数据完整;
    性别输入支持大小写(自动转为大写),提升用户友好性。
  1. 二次开发后的代码
点击查看代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define LEN 15          // 姓名/学号最大字符数
#define N 50            // 最大学生人数
#define SCORE_MIN 0.0   // 成绩最小值
#define SCORE_MAX 100.0 // 成绩最大值

int current_student_count = 0; // 当前学生人数(替换原n,命名更直观)
int program_running = 1;       // 控制程序运行(替换原t)

// 学生结构体(增加总分/平均分字段)
typedef struct
{
	char id[LEN];          // 学号
	char name[LEN];        // 姓名
	int age;               // 年龄
	char gender;           // 性别(M/W)
	float scores[3];       // C语言、高数、英语成绩
	float total_score;     // 总分
	float avg_score;       // 平均分
} Student;

Student students[N]; // 学生数组

// 函数声明(命名规范化,增加功能函数)
void show_main_menu();        // 显示主菜单
void show_help_info();        // 显示帮助信息
void add_student_info();      // 增加学生信息
void query_student_info();    // 查询学生信息
void delete_student_info();   // 删除学生信息
void save_info_to_file();     // 保存信息到文件
void show_all_students();     // 显示所有学生信息
void modify_student_info();   // 修改学生信息
void load_info_from_file();   // 从文件加载信息(替换原flush)
void exit_program();          // 退出程序
void calculate_scores(int idx);// 计算总分和平均分
int is_id_exist(const char* id); // 检查学号是否存在
int validate_gender(char gender); // 验证性别合法性
int validate_score(float score);  // 验证成绩合法性

int main()
{
	int menu_choice;
	while (program_running)
	{
		show_main_menu();
		printf("请输入功能编号(1-10):");
		// 处理输入异常(如输入非数字)
		while (scanf("%d", &menu_choice) != 1)
		{
			while (getchar() != '\n'); // 清空输入缓冲区
			printf("输入无效!请输入数字(1-10):");
		}
		printf("----------------------------------------\n");

		switch (menu_choice)
		{
			case 1:
				show_help_info();
				break;
			case 2:
				add_student_info();
				break;
			case 3:
				query_student_info();
				break;
			case 4:
				delete_student_info();
				break;
			case 5:
				save_info_to_file();
				break;
			case 6:
				show_all_students();
				break;
			case 7:
				modify_student_info();
				break;
			case 8:
				load_info_from_file();
				break;
			case 9:
				exit_program();
				break;
			default:
				printf("输入错误!请选择1-10之间的功能编号。\n");
		}
		printf("----------------------------------------\n");
		system("pause");
		system("cls"); // 清屏,提升交互体验
	}
	return 0;
}

// 显示主菜单(优化排版,增加成绩统计提示)
void show_main_menu()
{
	printf("\n========================================\n");
	printf("           学生信息管理系统             \n");
	printf("========================================\n");
	printf("  1、使用帮助        2、增加学生信息    \n");
	printf("  3、查询学生信息    4、删除学生信息    \n");
	printf("  5、保存当前信息    6、显示所有信息    \n");
	printf("  7、修改学生信息    8、加载文件信息    \n");
	printf("  9、退出系统                          \n");
	printf("========================================\n");
}

// 显示帮助信息(补充新增功能说明)
void show_help_info()
{
	printf("\n========== 使用帮助 ==========\n");
	printf("1、初次使用请先【增加学生信息】\n");
	printf("2、修改/增加信息后请【保存当前信息】\n");
	printf("3、重启系统后请【加载文件信息】恢复数据\n");
	printf("4、性别仅支持输入:M(男)/ W(女)\n");
	printf("5、成绩范围:0.0 - 100.0,超出将提示重新输入\n");
	printf("6、系统自动计算学生总分和平均分\n");
	printf("==============================\n");
}

// 验证性别合法性
int validate_gender(char gender)
{
	return (gender == 'M' || gender == 'W' || gender == 'm' || gender == 'w') ? 1 : 0;
}

// 验证成绩合法性
int validate_score(float score)
{
	return (score >= SCORE_MIN && score <= SCORE_MAX) ? 1 : 0;
}

// 检查学号是否存在
int is_id_exist(const char* id)
{
	int i = 0;
	for (i = 0; i < current_student_count; i++)
	{
		if (strcmp(students[i].id, id) == 0)
		{
			return 1; // 存在
		}
	}
	return 0; // 不存在
}

// 计算总分和平均分
void calculate_scores(int idx)
{
	students[idx].total_score = students[idx].scores[0] + students[idx].scores[1] + students[idx].scores[2];
	students[idx].avg_score = students[idx].total_score / 3.0;
}

// 增加学生信息(优化输入校验,自动计算成绩)
void add_student_info()
{
	int add_count;
	printf("请输入要增加的学生人数:");
	while (scanf("%d", &add_count) != 1 || add_count <= 0 || add_count + current_student_count > N)
	{
		while (getchar() != '\n');
		printf("输入无效!请输入正整数,且总人数不超过%d:", N);
	}

	int current = current_student_count;
	int i = 0;
	for (i = current; i < current + add_count; i++)
	{
		// 学号校验(唯一)
		char temp_id[LEN];
		do
		{
			printf("\n--- 第%d位学生信息 --- \n", i + 1);
			printf("学号:");
			scanf("%s", temp_id);
			if (is_id_exist(temp_id))
			{
				printf("学号%s已存在!请重新输入。\n", temp_id);
			}
		}
		while (is_id_exist(temp_id));
		strcpy(students[i].id, temp_id);

		// 姓名
		printf("姓名:");
		scanf("%s", students[i].name);

		// 年龄(正整数)
		printf("年龄:");
		while (scanf("%d", &students[i].age) != 1 || students[i].age <= 0)
		{
			while (getchar() != '\n');
			printf("年龄无效!请输入正整数:");
		}

		// 性别(校验)
		char temp_gender;
		do
		{
			printf("性别(M/W):");
			getchar(); // 清空换行符
			scanf("%c", &temp_gender);
			if (!validate_gender(temp_gender))
			{
				printf("性别无效!仅支持M(男)/ W(女):");
			}
		}
		while (!validate_gender(temp_gender));
		students[i].gender = toupper(temp_gender); // 统一转为大写

		// 成绩(范围校验)
		printf("C语言成绩:");
		while (scanf("%f", &students[i].scores[0]) != 1 || !validate_score(students[i].scores[0]))
		{
			while (getchar() != '\n');
			printf("成绩无效!请输入0.0-100.0之间的数值:");
		}

		printf("高数成绩:");
		while (scanf("%f", &students[i].scores[1]) != 1 || !validate_score(students[i].scores[1]))
		{
			while (getchar() != '\n');
			printf("成绩无效!请输入0.0-100.0之间的数值:");
		}

		printf("英语成绩:");
		while (scanf("%f", &students[i].scores[2]) != 1 || !validate_score(students[i].scores[2]))
		{
			while (getchar() != '\n');
			printf("成绩无效!请输入0.0-100.0之间的数值:");
		}

		// 自动计算总分和平均分
		calculate_scores(i);
	}

	current_student_count += add_count;
	printf("\n成功增加%d名学生信息!\n", add_count);
}

// 查询学生信息(支持按学号/姓名,显示总分/平均分)
void query_student_info()
{
	int choice;
	char keyword[LEN];
	int found = 0;

	printf("\n========== 查询菜单 ==========\n");
	printf("1、按学号查询\n");
	printf("2、按姓名查询\n");
	printf("3、退出查询\n");
	printf("请选择:");
	scanf("%d", &choice);

	if (choice == 3) return;

	printf("请输入查询关键词:");
	scanf("%s", keyword);

	// 表头
	printf("\n学号\t姓名\t性别\t年龄\tC语言\t高数\t英语\t总分\t平均分\n");
	printf("----------------------------------------------------------------------\n");
	int i = 0;
	for (i = 0; i < current_student_count; i++)
	{
		if ((choice == 1 && strcmp(students[i].id, keyword) == 0) ||
		        (choice == 2 && strcmp(students[i].name, keyword) == 0))
		{
			printf("%s\t%s\t%c\t%d\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",
			       students[i].id, students[i].name, students[i].gender,
			       students[i].age, students[i].scores[0], students[i].scores[1],
			       students[i].scores[2], students[i].total_score, students[i].avg_score);
			found = 1;
		}
	}

	if (!found)
	{
		printf("未找到匹配的学生信息!\n");
	}
}

// 删除学生信息(优化逻辑,支持确认删除)
void delete_student_info()
{
	char del_id[LEN];
	int del_idx = -1;
	int confirm;

	printf("请输入要删除的学生学号:");
	scanf("%s", del_id);

	// 查找学号
	int i = 0;
	for ( i = 0; i < current_student_count; i++)
	{
		if (strcmp(students[i].id, del_id) == 0)
		{
			del_idx = i;
			break;
		}
	}

	if (del_idx == -1)
	{
		printf("学号%s不存在!\n", del_id);
		return;
	}

	// 显示待删除信息,确认删除
	printf("\n待删除学生信息:\n");
	printf("学号\t姓名\t性别\t年龄\n");
	printf("%s\t%s\t%c\t%d\n", students[del_idx].id, students[del_idx].name,
	       students[del_idx].gender, students[del_idx].age);
	printf("确认删除?(1=确认,0=取消):");
	scanf("%d", &confirm);

	if (confirm != 1)
	{
		printf("删除已取消!\n");
		return;
	}

	// 数据前移,覆盖待删除项
	for (i = del_idx; i < current_student_count - 1; i++)
	{
		students[i] = students[i + 1];
	}
	current_student_count--;
	printf("学号%s的学生信息已成功删除!\n", del_id);
}

// 保存信息到文件(二进制保存,兼容加载)
void save_info_to_file()
{
	FILE* fp;
	char filename[LEN + 5]; // 预留后缀空间

	printf("请输入保存的文件名(建议后缀.txt):");
	scanf("%s", filename);

	fp = fopen(filename, "wb");
	if (fp == NULL)
	{
		printf("文件打开失败!\n");
		return;
	}

	// 保存学生人数 + 学生数据
	fwrite(&current_student_count, sizeof(int), 1, fp);
	fwrite(students, sizeof(Student), current_student_count, fp);

	fclose(fp);
	printf("学生信息已成功保存到%s!\n", filename);
}

// 显示所有学生信息(增加总分/平均分列)
void show_all_students()
{
	if (current_student_count == 0)
	{
		printf("当前无学生信息!请先增加或加载数据。\n");
		return;
	}

	printf("\n========== 所有学生信息 ==========\n");
	printf("学号\t姓名\t性别\t年龄\tC语言\t高数\t英语\t总分\t平均分\n");
	printf("----------------------------------------------------------------------\n");
	int i = 0;
	for (i = 0; i < current_student_count; i++)
	{
		printf("%s\t%s\t%c\t%d\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",
		       students[i].id, students[i].name, students[i].gender,
		       students[i].age, students[i].scores[0], students[i].scores[1],
		       students[i].scores[2], students[i].total_score, students[i].avg_score);
	}
	printf("========================================\n");
	printf("总计:%d名学生\n", current_student_count);
}

// 修改学生信息(支持按学号查找,修复姓名重复问题,增加成绩重计算)
void modify_student_info()
{
	char modify_id[LEN];
	int modify_idx = -1;

	printf("请输入要修改的学生学号:");
	scanf("%s", modify_id);

	// 按学号查找(唯一标识,避免姓名重复问题)
	int i = 0;
	for ( i = 0; i < current_student_count; i++)
	{
		if (strcmp(students[i].id, modify_id) == 0)
		{
			modify_idx = i;
			break;
		}
	}

	if (modify_idx == -1)
	{
		printf("学号%s不存在!\n", modify_id);
		return;
	}

	// 显示当前信息
	printf("\n当前学生信息:\n");
	printf("学号:%s\t姓名:%s\t性别:%c\t年龄:%d\n",
	       students[modify_idx].id, students[modify_idx].name,
	       students[modify_idx].gender, students[modify_idx].age);
	printf("C语言:%.2f\t高数:%.2f\t英语:%.2f\n",
	       students[modify_idx].scores[0], students[modify_idx].scores[1],
	       students[modify_idx].scores[2]);

	// 修改子菜单
	int choice;
	do
	{
		printf("\n========== 修改菜单 ==========\n");
		printf("1、修改姓名    2、修改性别    3、修改年龄\n");
		printf("4、修改C语言   5、修改高数    6、修改英语\n");
		printf("7、退出修改\n");
		printf("请选择:");
		scanf("%d", &choice);

		switch (choice)
		{
			case 1:
				printf("新姓名:");
				scanf("%s", students[modify_idx].name);
				break;
			case 2:
			{
				char new_gender;
				do
				{
					printf("新性别(M/W):");
					getchar();
					scanf("%c", &new_gender);
				}
				while (!validate_gender(new_gender));
				students[modify_idx].gender = toupper(new_gender);
				break;
			}
			case 3:
				printf("新年龄:");
				while (scanf("%d", &students[modify_idx].age) != 1 || students[modify_idx].age <= 0)
				{
					while (getchar() != '\n');
					printf("年龄无效!请输入正整数:");
				}
				break;
			case 4:
				printf("新C语言成绩:");
				while (scanf("%f", &students[modify_idx].scores[0]) != 1 || !validate_score(students[modify_idx].scores[0]))
				{
					while (getchar() != '\n');
					printf("成绩无效!请输入0.0-100.0:");
				}
				calculate_scores(modify_idx); // 重算总分/平均分
				break;
			case 5:
				printf("新高数成绩:");
				while (scanf("%f", &students[modify_idx].scores[1]) != 1 || !validate_score(students[modify_idx].scores[1]))
				{
					while (getchar() != '\n');
					printf("成绩无效!请输入0.0-100.0:");
				}
				calculate_scores(modify_idx);
				break;
			case 6:
				printf("新英语成绩:");
				while (scanf("%f", &students[modify_idx].scores[2]) != 1 || !validate_score(students[modify_idx].scores[2]))
				{
					while (getchar() != '\n');
					printf("成绩无效!请输入0.0-100.0:");
				}
				calculate_scores(modify_idx);
				break;
			case 7:
				printf("退出修改!\n");
				break;
			default:
				printf("输入错误!请选择1-7。\n");
		}
		if (choice >= 1 && choice <= 6)
		{
			printf("修改成功!\n");
		}
	}
	while (choice != 7);
}

// 从文件加载信息(替换原flush,清空原有数据)
void load_info_from_file()
{
	FILE* fp;
	char filename[LEN + 5];

	printf("请输入要加载的文件名:");
	scanf("%s", filename);

	fp = fopen(filename, "rb");
	if (fp == NULL)
	{
		printf("文件打开失败!请检查文件名是否正确。\n");
		return;
	}

	// 清空原有数据
	current_student_count = 0;

	// 读取学生人数
	fread(&current_student_count, sizeof(int), 1, fp);
	// 读取学生数据
	fread(students, sizeof(Student), current_student_count, fp);

	fclose(fp);
	printf("成功加载%d名学生信息!\n", current_student_count);
}

// 退出程序(优化提示)
void exit_program()
{
	int confirm;
	printf("\n========== 退出确认 ==========\n");
	printf("确认退出系统?(1=确认,0=取消):");
	scanf("%d", &confirm);

	if (confirm == 1)
	{
		program_running = 0;
		printf("感谢使用学生信息管理系统!\n");
	}
	else
	{
		printf("退出已取消!\n");
	}
}

5. 测试截图

image
6. 总结
本次二次开发主要完成了以下核心优化:

  • 修复安全漏洞:移除gets(),增加输入合法性校验,避免非法输入导致程序崩溃;
  • 增强核心功能:新增成绩统计(总分/平均分),优化查询/修改/删除逻辑,解决原代码的功能缺陷;
  • 提升用户体验:优化菜单排版、输入提示、清屏操作,让交互更直观;
  • 规范代码结构:统一命名规则,提取通用函数,降低代码维护成本。
posted @ 2026-03-10 19:02  yanxizao  阅读(8)  评论(0)    收藏  举报