第一周软件开发与创新课程作业

一.来源:来自同年级同学的学生信息管理系统期末大作业项目。

二.运行环境+运行结果的截图:
1.源代码:

点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#define MAX_NUM 50
#define FILE_NAME "info.dat"

float line;
int num = 0;
int k = 0;
int n = 0;

struct Student
{
	int id;
	char name[MAX_NUM];
	int sex;
	int age;
	float score;
	char addr[100];
	struct Student* next;
};

Student* head = NULL;

float score[1000005];
int id[1000005];

////函数声明////

void print(char str, int n);

void main_menu_display();
void info_menu_display();
void score_menu_display();
void file_menu_display();
void info_manage();
void add_student();
void delete_student();
void modify_student();
void find_student();
void view_student();

void score_menu_display();

void score_manage();
void file_manage();
void Check_in();
void score_ranking();
void List_viewing();
void scholarship_score_line();

void read_file();
void write_file();

////main////
int main()
{
	int choice;
	do
	{
		system("cls"); // 清屏
		main_menu_display();
		printf("请选择:\n");
		scanf("%d", &choice);
		getchar();

		switch (choice)
		{
		case 1:
			info_manage();
			break;
		case 2:
			score_manage();
			break;
		case 3:
			file_manage();
			break;
		case 4:
			printf("正在退出程序...\n");
			break;
		default:
			printf("请输入正确的选项\n");
		}
		Sleep(1000);
	} while (choice != 4);

	return 0;
}

void print(char str, int n)
{
	for (int i = 1; i <= n; i++)
		printf("%c", str);
}

void main_menu_display()
{
	print('*', 100);
	printf("\n");
	print(' ', 41 + 4);
	printf("学生管理系统");
	printf("\n");
	print(' ', 41);
	printf("1 学生基本信息管理");
	printf("\n");
	print(' ', 41);
	printf("2 学生成绩信息管理");
	printf("\n");
	print(' ', 41);
	printf("3 文件操作");
	printf("\n");
	print(' ', 41);
	printf("4 退出");
	printf("\n");
	print('*', 100);
	printf("\n");
	return;
}

void info_menu_display()
{
	print('*', 100);
	printf("\n");
	print(' ', 42);
	printf("学生基本信息管理");
	printf("\n");
	print(' ', 41);
	printf("1 添加新学生信息");
	printf("\n");
	print(' ', 41);
	printf("2 删除学生信息");
	printf("\n");
	print(' ', 41);
	printf("3 修改学生信息");
	printf("\n");
	print(' ', 41);
	printf("4 查看所有学生信息");
	printf("\n");
	print(' ', 41);
	printf("5 查找学生信息");
	printf("\n");
	print(' ', 41);
	printf("6 返回上一级");
	printf("\n");
	print('*', 100);
	printf("\n");
	return;
}

void info_manage()
{
	int choice;
	do
	{
		system("cls"); // 清屏
		info_menu_display();
		printf("请选择:\n");
		scanf("%d", &choice);
		getchar();
		switch (choice)
		{
		case 1:
			add_student();
			break;
		case 2:
			delete_student();
			break;
		case 3:
			modify_student();
			break;
		case 4:
			view_student();
			break;
		case 5:
			find_student();
			break;
		case 6:
			printf("正在返回上一级...");
			break;
		default:
			printf("请输入正确的选项\n");
		}
		Sleep(1000);
	} while (choice != 6);
}

void add_student()
{
	Student* newStudent = (Student*)malloc(sizeof(Student)); // 为新学生分配内存
	if (!newStudent)
	{
		printf("内存分配失败,请重试\n");
		return;
	}
	printf("请输入学号: ");
	scanf("%d", &newStudent->id);
	getchar();
	printf("请输入姓名: ");
	scanf("%s", &newStudent->name);
	printf("请输入年龄: ");
	scanf("%d", &newStudent->age);
	printf("请输入性别:(1为男,0为女) ");
	scanf("%d", &newStudent->sex);
	printf("请输入家庭地址: ");
	scanf("%s", &newStudent->addr);

	newStudent->score = 0.00;
	newStudent->next = head;
	head = newStudent;

	printf("成功添加新学生信息\n");
	n++;
}

void delete_student()
{
	int id;
	printf("请输入待删除学生的学号:\n");
	scanf("%d", &id);
	Student* current = head;
	Student* prev = NULL;
	while (current != NULL)
	{
		if (current->id == id)
		{
			if (prev == NULL)
			{ // 删掉头部node
				head = current->next;
			}
			else
			{								// 删掉中部node
				prev->next = current->next; // 相当于跳过了current节点
			}
			free(current);
			printf("已成功删除\n");
			return;
		}
		prev = current;
		current = current->next;
	}
	printf("未找到对应学号的学生\n");
	return;
}

void modify_student()
{
	int id;
	printf("请输入待修改学生的学号:\n");
	scanf("%d", &id);
	Student* current = head;
	// Student *prev=NULL;
	while (current != NULL)
	{
		if (current->id == id)
		{
			printf("请输入新姓名: ");
			scanf("%s", &current->name);
			printf("请输入新年龄: ");
			scanf("%d", &current->age);
			printf("请输入新性别:(1为男,0为女) ");
			scanf("%d", &current->sex);
			printf("请输入新家庭地址: ");
			scanf("%s", &current->addr);
			printf("已成功修改\n");
			return;
		}
		// prev=current;
		current = current->next;
	}
	printf("未找到对应学号的学生\n");
	return;
}

void find_student()
{
	int id;
	printf("请输入待查找学生的学号:\n");
	scanf("%d", &id);
	Student* current = head;
	// Student *prev=NULL;
	while (current != NULL)
	{
		if (current->id == id)
		{
			printf("\n学号\t姓名\t年龄\t性别\t家庭住址\n");
			print('*', 100);
			printf("\n");
			printf("%d\t%s\t%d\t%s\t%s\n", current->id, current->name, current->age, current->sex ? "男" : "女", current->addr);
			printf("任意键以继续\n");
			getchar();
			getchar();
			return;
		}
		// prev=current;
		current = current->next;
	}
	printf("未找到对应学号的学生\n");
	return;
}

void view_student()
{
	if (head == NULL)
	{
		printf("尚未添加任何学生信息\n");
		return;
	}
	Student* current = head;
	printf("\n学号\t姓名\t年龄\t性别\t家庭住址\t绩点\n");
	print('*', 100);
	printf("\n");
	while (current != NULL)
	{
		printf("%d\t%s\t%d\t%s\t%s\t%.2f\n", current->id, current->name, current->age, current->sex ? "男" : "女", current->addr, current->score);
		current = current->next;
	}
	printf("任意键以继续\n");
	getchar();
}

void score_menu_display()
{
	print('*', 100);
	printf("\n");
	print(' ', 42);
	printf("学生成绩信息管理");
	printf("\n");
	print(' ', 41);
	printf("1 学生成绩登记");
	printf("\n");
	print(' ', 41);
	printf("2 查看某同学绩点排名");
	printf("\n");
	print(' ', 41);
	printf("3 设置奖学金绩点分数线");
	printf("\n");
	print(' ', 41);
	printf("4 查看奖学金名单");
	printf("\n");
	print(' ', 41);
	printf("5 返回上一级");
	printf("\n");
	print('*', 100);
	printf("\n");
	return;
}

void score_manage()
{
	int choice;
	do
	{
		system("cls");
		score_menu_display();
		printf("请选择:\n");
		scanf("%d", &choice);
		getchar();
		switch (choice)
		{
		case 1:
			Check_in();
			break;
		case 2:
			score_ranking();
			break;
		case 3:
			scholarship_score_line();
			break;
		case 4:
			List_viewing();
			break;
		case 5:
			printf("正在返回上一级...");
			break;
		default:
			printf("请输入正确的选项");
		}
		Sleep(1000);
	} while (choice != 5);

	return;
}

void Check_in()
{
	int id;
	printf("请输入要登记的学生的学号:\n");
	scanf("%d", &id);
	Student* current = head;
	// Student *prev=NULL;
	while (current != NULL)
	{
		if (current->id == id)
		{
			printf("请输入该登记学生的成绩:\n");
			scanf("%f", &current->score);
			printf("已成功登记\n");
			return;
		}
		// prev=current;
		current = current->next;
	}
	printf("未找到对应学号的学生\n");
	return;
}

void score_ranking()
{
	if (head == NULL)
	{
		printf("尚未添加任何学生信息\n");
		return;
	}
	Student* current = head;
	k = 0;
	memset(score, 0, sizeof(score));
	memset(id, 0, sizeof(id));
	while (current != NULL)
	{
		score[k] = current->score;
		id[k] = current->id;
		k++;
		current = current->next; // 使current指向下一个节点//
	}

	int flag = 1;
	while (flag == 1)
	{
		flag = 0;
		for (int j = 0; j < k - 1; j++)
		{
			if (score[j] < score[j + 1])
			{
				flag = 1;
				int t1 = score[j];
				score[j] = score[j + 1];
				score[j + 1] = t1;
				int t2 = id[j];
				id[j] = id[j + 1];
				id[j + 1] = t2;
			}
		}
	}
	printf("学生成绩排名:\n");
	printf("\n学号\t姓名\t绩点\n");
	print('*', 100);
	printf("\n");
	for (int i = 0; i < k; i++)
	{
		Student* current = head;
		while (current != NULL)
		{
			if (current->id == id[i])
				printf("%d\t%s\t%.2f\n", current->id, current->name, score[i]);
			current = current->next;
		}
	}
	printf("任意键以继续\n");
	getchar();
}

// 设置奖学金绩点分数线//
void scholarship_score_line()
{

	printf("请输入奖学金绩点分数线: ");
	scanf("%f", &line);
	printf("奖学金绩点分数线已设置为:%.2f\n", line);
}

void List_viewing()
{
	printf("当前分数线为%.2f\n", line);
	printf("\n学号\t姓名\t绩点\n");
	print('*', 100);
	printf("\n");
	for (int i = 0; i < k; i++)
	{
		if (score[i] >= line)
		{
			Student* current = head;
			while (current != NULL)
			{
				if (current->id == id[i])
					printf("%d\t%s\t%.2f\n", current->id, current->name, score[i]);
				current = current->next;
			}
		}
	}
	printf("按任意键以继续\n");
	getchar();
	return;
}

void file_manage()
{
	int choice;
	do
	{
		system("cls"); // 清屏
		file_menu_display();
		printf("请选择:\n");
		scanf("%d", &choice);
		getchar();
		switch (choice)
		{
		case 1:
			read_file();
			break;
		case 2:
			write_file();
			break;
		case 3:
			printf("正在返回上一级...");
			break;
		default:
			printf("请输入正确的选项\n");
		}
		Sleep(1000);
	} while (choice != 3);
}

void file_menu_display()
{
	print('*', 100);
	printf("\n");
	print(' ', 41 + 4);
	printf("文件操作");
	printf("\n");
	print(' ', 41);
	printf("1 从文件读入学生信息");
	printf("\n");
	print(' ', 41);
	printf("2 导出学生信息为文件");
	printf("\n");
	print(' ', 41);
	printf("3 返回上一级");
	printf("\n");
	print('*', 100);
	printf("\n");
	return;
}

void read_file()
{
	FILE* file = fopen(FILE_NAME, "rb");
	if (!file)
	{
		printf("文件夹内没有找到对应文件\n");
		return;
	}

	Student* newStudent;
	while ((newStudent = (Student*)malloc(sizeof(Student))) != NULL && fread(newStudent, sizeof(Student), 1, file) == 1)
	{
		newStudent->next = head;
		head = newStudent;
	}

	fclose(file);
	printf("成功导入文件信息\n");
}

void write_file()
{
	FILE* file = fopen(FILE_NAME, "wb");
	if (!file)
	{
		printf("未能成功打开文件\n");
		return;
	}

	Student* current = head;
	while (current != NULL)
	{
		fwrite(current, sizeof(Student), 1, file);
		current = current->next;
	}

	fclose(file);
	printf("成功导出文件信息\n");
}

2.运行环境:

image

3.运行结果:
添加:
f01112810b55a33fb1768c198aaab6d

修改:
ca1ca67a12fb70591da968264d68b4b
902b6e91070cbc3adcbdfbd84bac877

查找:
image

删除:
455cb8e0c5c14b9375bc03d17c6c414
887bd24f1ea74f9f13fa27c17eeaec8

成绩添加
6206166a16ff05dbd5f7e2d2aaef6ee
a9881f0b0c22429052bd427c6ba2d37

成绩查看
image

奖学金设置
image
image

文件操作:
先导出
ad1812e1b1d97c8cd6e4c8227047d34
在删除所有学生
656c16454c8e8c42c889eecb2d3b9b5

接着从文件读入学生信息
47b1b7b0f0f15765101029a7555f576
d3a1014fffd92f442c4167d9a748fbc

边界情况
2d7869c0ed83a61a8222ccd51924a32
a5e30dc39a3f89606609cba3e0f9d21

三.主要问题列表,针对问题的改善或者重构思路
1.主要问题:scanf语法错误 (scanf("%s", &newStudent->name);),以及无长度限制的%s输入危险,可能导致缓冲区溢出。(scanf("%s", newStudent->addr);)

改善:(1)添加缓冲区清理函数

void clear_input_buffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}

把它添加到add_student()、view_student()、modify_student()、find_student()中;

(2)修改输入,加上长度限制,修改语法错误,删去&

 printf("请输入姓名: ");
 scanf("%49s", newStudent->name);
 clear_input_buffer();

 printf("请输入家庭地址: ");
 scanf("%99s", newStudent->addr);
 clear_input_buffer();

2.主要问题:内存泄漏问题,每次从文件读取都会丢失原有链表的内存,程序退出时没有释放链表

改善:

点击查看代码
// 修复 read_file() 函数
void read_file()
{
    // 先释放原有链表
    Student* current = head;
    while (current != NULL) {
        Student* temp = current;
        current = current->next;
        free(temp);
    }
    head = NULL;
    n = 0;  // 重置计数器
    
    FILE* file = fopen(FILE_NAME, "rb");
    if (!file)
    {
        printf("文件夹内没有找到对应文件\n");
        return;
    }

    Student* newStudent;
    while ((newStudent = (Student*)malloc(sizeof(Student))) != NULL)
    {
        if (fread(newStudent, sizeof(Student), 1, file) != 1)
        {
            free(newStudent);
            break;
        }
        newStudent->next = head;
        head = newStudent;
        n++;  // 更新计数器
    }

    fclose(file);
    printf("成功导入文件信息\n", n);
}


// 增加程序退出时的内存释放
void free_all_memory() {
    Student* current = head;
    while (current != NULL) {
        Student* temp = current;
        current = current->next;
        free(temp);
    }
    head = NULL;
    n = 0;
    k = 0;
}

// 修改main函数
 case 4:
            printf("正在退出程序...\n");
            free_all_memory();  // 释放内存
            break;

3.主要问题:缺少数据验证,如年龄可输入负数、300岁,成绩可输入负数、超过4.0,学号可重复

改善:添加验证函数

点击查看代码
//数据验证函数
int is_id_exists(int id) {
    Student* current = head;
    while (current != NULL) {
        if (current->id == id) {
            return 1;  // 学号已存在
        }
        current = current->next;
    }
    return 0;  // 学号不存在
}

int validate_age(int age) {
    return age > 0 && age < 101;  // 年龄在1-100之间
}

int validate_sex(int sex) {
    return sex == 0 || sex == 1;  // 性别只能是0或1
}

int validate_score(float score) {
    return score >= 0.0 && score <= 4.0;  // 绩点在0-4之间
}

// 修改 add_student(),添加数据验证
void add_student()
{
    Student* newStudent = (Student*)malloc(sizeof(Student));
    if (!newStudent)
    {
        printf("内存分配失败,请重试\n");
        return;
    }
    
    //学号唯一性验证
    printf("请输入学号: ");
    scanf("%d", &newStudent->id);
    clear_input_buffer();
    
    if (is_id_exists(newStudent->id)) {
        printf("学号已存在,添加失败\n");
        free(newStudent);
        return;
    }
    
    printf("请输入姓名: ");
    scanf("%49s", newStudent->name);
    clear_input_buffer();
    
    //年龄范围验证
    do {
        printf("请输入年龄: ");
        scanf("%d", &newStudent->age);
        clear_input_buffer();
        if (!validate_age(newStudent->age)) {
            printf("年龄必须在1-119之间,请重新输入\n");
        }
    } while (!validate_age(newStudent->age));
    
    printf("请输入性别:(1为男,0为女) ");
    scanf("%d", &newStudent->sex);
    clear_input_buffer();
    
    printf("请输入家庭地址: ");
    scanf("%99s", newStudent->addr);
    clear_input_buffer();

    newStudent->score = 0.00;
    newStudent->next = head;
    head = newStudent;

    printf("成功添加新学生信息\n");
    n++;
}

// 修改 modify_student(),同上
void modify_student()
{
    int id;
    printf("请输入待修改学生的学号:\n");
    scanf("%d", &id);
    clear_input_buffer();
    
    Student* current = head;
    while (current != NULL)
    {
        if (current->id == id)
        {
            printf("请输入新姓名: ");
            scanf("%49s", current->name);
            clear_input_buffer();
            
            // 年龄范围验证
            do {
                printf("请输入新年龄: ");
                scanf("%d", &current->age);
                clear_input_buffer();
                if (!validate_age(current->age)) {
                    printf("年龄必须在1-119之间,请重新输入\n");
                }
            } while (!validate_age(current->age));
            
            printf("请输入新性别:(1为男,0为女) ");
            scanf("%d", &current->sex);
            clear_input_buffer();
            
            printf("请输入新家庭地址: ");
            scanf("%99s", current->addr);
            clear_input_buffer();
            
            printf("已成功修改\n");
            return;
        }
        current = current->next;
    }
    printf("未找到对应学号的学生\n");
}

// 修改 Check_in(),同上
void Check_in()
{
    int id;
    printf("请输入要登记的学生的学号:\n");
    scanf("%d", &id);
    clear_input_buffer();
    
    Student* current = head;
    while (current != NULL)
    {
        if (current->id == id)
        {
            //成绩范围验证
            do {
                printf("请输入该登记学生的成绩(0-4之间):\n");
                scanf("%f", &current->score);
                clear_input_buffer();
                if (!validate_score(current->score)) {
                    printf("成绩必须在0-4之间,请重新输入\n");
                }
            } while (!validate_score(current->score));
            
            printf("已成功登记\n");
            return;
        }
        current = current->next;
    }
    printf("未找到对应学号的学生\n");
}

// 修改 delete_student(),同上
void delete_student()
{
    int id;
    printf("请输入待删除学生的学号:\n");
    scanf("%d", &id);
    clear_input_buffer();
    
    //检查学号是否存在
    if (!is_id_exists(id)) {
        printf("学号 %d 不存在,删除失败\n", id);
        return;
    }
    
    Student* current = head;
    Student* prev = NULL;
    while (current != NULL)
    {
        if (current->id == id)
        {
            if (prev == NULL)
            {
                head = current->next;
            }
            else
            {
                prev->next = current->next;
            }
            free(current);
            n--;
            printf("已成功删除\n");
            return;
        }
        prev = current;
        current = current->next;
    }
}

// 修改 find_student(),同上
void find_student()
{
    int id;
    printf("请输入待查找学生的学号:\n");
    scanf("%d", &id);
    clear_input_buffer();
    
    //检查学号是否存在
    if (!is_id_exists(id)) {
        printf("学号 %d 不存在\n", id);
        return;
    }
    
    Student* current = head;
    while (current != NULL)
    {
        if (current->id == id)
        {
            printf("\n学号\t姓名\t年龄\t性别\t家庭住址\n");
            print('*', 100);
            printf("\n");
            printf("%d\t%s\t%d\t%s\t%s\n", current->id, current->name, current->age, current->sex ? "男" : "女", current->addr);
            printf("按回车键以继续\n");
            clear_input_buffer();
            getchar();
            return;
        }
        current = current->next;
    }
}

// 修改 scholarship_score_line(),添加分数线范围验证
void scholarship_score_line()
{
    //分数线范围验证
    do {
        printf("请输入奖学金绩点分数线(0-4之间): ");
        scanf("%f", &line);
        clear_input_buffer();
        if (line < 0 || line > 4) {
            printf("分数线必须在0-4之间,请重新输入\n");
        }
    } while (line < 0 || line > 4);
    
    printf("奖学金绩点分数线已设置为:%.2f\n", line);
}

4.主要问题:float score[1000005]和int id[1000005]内存浪费严重,数组是全局的,程序运行期间一直占用内存,并且链表已经存储了所有学生信息,又用两个大数组重复存储学号和成绩造成数据冗余

改善:

点击查看代码
float line;
int num = 0;
int k = 0;
int n = 0;
//删除
//float score[1000005];
//int id[1000005];


//修改score_ranking函数
void score_ranking()
{
    if (head == NULL)
    {
        printf("尚未添加任何学生信息\n");
        return;
    }
    
    // 统计学生数量
    int count = 0;
    Student* current = head;
    while (current != NULL)
    {
        count++;
        current = current->next;
    }
    
    // 动态分配临时数组
    float* score = (float*)malloc(count * sizeof(float));
    int* id = (int*)malloc(count * sizeof(int));
    
    if (score == NULL || id == NULL)
    {
        printf("内存不足,无法显示排名\n");
        free(score);
        free(id);
        return;
    }
    current = head;
    int k = 0;
    while (current != NULL)
    {
        score[k] = current->score;
        id[k] = current->id;
        k++;
        current = current->next;
    }
    
    // 冒泡排序
    int flag = 1;
    while (flag == 1)
    {
        flag = 0;
        for (int j = 0; j < k - 1; j++)
        {
            if (score[j] < score[j + 1])
            {
                flag = 1;
                float t1 = score[j];
                score[j] = score[j + 1];
                score[j + 1] = t1;
                int t2 = id[j];
                id[j] = id[j + 1];
                id[j + 1] = t2;
            }
        }
    }
    
    printf("学生成绩排名:\n");
    printf("\n学号\t姓名\t绩点\n");
    print('*', 100);
    printf("\n");
    for (int i = 0; i < k; i++)
    {
        Student* current = head;
        while (current != NULL)
        {
            if (current->id == id[i])
                printf("%d\t%s\t%.2f\n", current->id, current->name, score[i]);
            current = current->next;
        }
    }
    
    free(score);
    free(id);
    
    printf("任意键以继续\n");
    getchar();

//修改 List_viewing函数
void List_viewing()
{
    if (head == NULL)
    {
        printf("暂无学生信息\n");
        return;
    }
    
    printf("当前分数线为%.2f\n", line);
    printf("\n学号\t姓名\t绩点\n");
    print('*', 100);
    printf("\n");
    
    Student* current = head;
    while (current != NULL)
    {
        if (current->score >= line)
        {
            printf("%d\t%s\t%.2f\n", current->id, current->name, current->score);
        }
        current = current->next;
    }
    
    printf("按任意键以继续\n");
    getchar();
}
}

四.重构的软件的测试截图

1.验证系统是否能阻止学号重复
image

2.年龄验证
image

3.成绩验证
image

4.验证超长输入是否导致缓冲区溢出
018c6eb18d30b0a36c6c0246156bf0c
53592c1a5d395f85b03db7dd180e7f0

5.排名功能是否动态分配内存 并且排名从高到低
image
image

五.总结:
这次修改学生管理系统,我主要处理了四个问题:数据验证、scanf输入错误、内存泄漏,还有那个超大数组。说实话,每个问题改起来的感觉都不一样,让我对写代码这件事有了很多新的认识。
数据验证这个改起来最直观。年龄不能超过120、成绩只能在0到4之间、学号不能重复,这些都是明摆着的规则,逻辑特别清晰。但真动手改的时候才发现直接返回显得太生硬,让用户重新输入吧又要加循环,还得小心别写成死循环。就这一个选择,我纠结了好一会儿。
scanf语法错误和缓冲区溢出这个问题,现在回头看有点哭笑不得。那个多余的&,我自己写的时候有时也是会忘。还有不加长度限制的%s,平时测试输几个正常名字没问题,但万一谁手抖敲了一长串,程序直接就崩了。改的时候要挨个检查每个数组多大——name是50就用%49s,addr是100就用%99s,留一个位置给结束符。这种细节特别磨人,但漏一个就是隐患。
内存泄漏是我改得最痛苦的地方。原代码从文件读数据时,新数据直接覆盖上去,旧链表就没人管了,内存一直在那儿占着不释放。程序跑一会儿可能没问题,但要是反复读写文件,内存占用就蹭蹭往上涨。改这个的时候我头发都快薅掉了——不只是简单加个free就行,要考虑malloc失败了怎么办?文件读到一半出错了怎么办?用户突然退出怎么办?而且计数器n还得在增删改查各种操作里保持一致。我第一次意识到,资源管理不是配个对就完事,而是要管好整个生命周期。
超大数组这个问题最有意思。原代码开头定义了两个全局数组float score[1000005]和int id[1000005],改这个的时候我纠结了一下,是直接把数组改小点凑合用,还是彻底重构成动态分配。最后选了后者,长痛不如短痛。但这一改就牵扯大了,两个函数都要动,score_ranking()要改成动态分配内存,List_viewing()干脆重写,不再依赖排序后的数组,直接遍历链表判断。改完发现还挺爽的,不仅内存省了,两个功能还解耦了——以前必须先排名才能看奖学金名单,现在随时看都行,数据都是最新的。
回过头看这四个问题,我感觉自己像打怪升级一样。语法错误是最初级的,细心就能避免;安全漏洞需要有点意识,养成好习惯就行;内存泄漏就要动点脑筋了,得理解程序怎么运行的;超大数组这个层面,已经开始触及架构设计的问题了。作为学生,平时交作业只要功能跑通就行,但这次改代码让我明白,真正的工程不是这样的。代码不仅要能跑,还要跑得稳、跑得久、资源用得省。每个看似不起眼的问题,背后都可能藏着一堆连锁反应。改完这版代码,虽然累,但下次自己写的时候,应该能少踩不少坑。

posted @ 2026-03-09 18:07  芒果g9  阅读(1)  评论(0)    收藏  举报