FEATURED · 精选文章

VS2022下C语言学生信息管理系统完整实现与避坑指南

发布时间 / 2026/8/30 3:13:58
来源 / 创域科博编辑部
栏目 / 资讯中心
VS2022下C语言学生信息管理系统完整实现与避坑指南 简介C语言是计算机编程的基石而链表与文件读写则是其中最具工程价值的核心技能。动态内存分配让数据管理摆脱了静态数组的容量限制通过指针操作实现高效的增删改查。同时数据的持久化存储离不开文件IOfprintf与fscanf的配合能轻松完成结构化数据的保存与恢复。在课程设计与实战开发中学生信息管理系统正是综合运用这些技术的经典项目。本文基于VS2022环境从零构建一个完整的学生信息管理系统覆盖链表插入删除、排序统计、模糊查询以及文件加载保存并详细解析编译报错与调试技巧为初学者提供一条从理论到落地的清晰路径。 说实话每年到这个时间点总能看到一堆人在群里问C语言大作业怎么写。学生信息管理系统这个题目几乎快被写烂了但仔细一问十个里有八个还在用vs2010或者devc少数用codeblocks能正儿八经打开vs2022写的人都不多。有人觉得vs2022太重太复杂有人一上来就被各种配置劝退还有人压根不知道这个经典题目在vs2022里能玩出什么花样。我用vs2022亲自把这个项目完整过了一遍从建项目到写完增删改查、排序统计、文件读写每一步都踩过坑也填了坑这篇就把它当个完整复盘把从零到一的过程、核心代码、调试经验和答辩要点全部拆开讲清楚。这篇内容适合几类人看正在做C语言课程设计的大一学生、准备把学生信息管理系统作为第一个完整项目练手的自学者、想系统了解链表增删改查和文件操作实际配合的初学者还有那些想在答辩时把系统说清楚、讲明白、拿到高分的同学。我把整个思路从需求分析到代码实现再到vs2022的细节配置全部揉碎你跟着走一遍不光能交作业还能真正搞懂这堆代码背后的逻辑。1. 项目需求梳理与整体设计1.1 一个经典题目背后的真实需求学生信息管理系统属于C语言里最典型的综合性题目。它不像贪吃蛇那种偏图形和逻辑也不像图书管理系统那样要处理复杂的条码规则。它的核心就是四个字增删改查。但就是这个基本盘涵盖了C语言几乎所有的重要知识点结构体、数组和链表、函数封装、指针传递、文件IO、排序算法、字符串处理。一个系统写完整个学期学的C语言基本都被串联起来了。先看题目通常的要求。一般来说系统要管理的信息包括学号、姓名、性别、年龄、班级、各科成绩等字段。功能上包括添加学生信息支持连续录入删除指定学生按学号或姓名修改指定学生的信息查找学生按学号或姓名精确查询有时要求模糊查询显示全部学生信息按某门课成绩或总分排序输出统计班级平均分、最高分、及格率等数据保存到文件程序启动时从文件加载这个需求集任何一个单拿出来都不难但组合在一起就需要你有清晰的模块化思路。如果代码全堆在main函数里写到两百行的时候你自己都看不下去。所以从设计阶段就要想好每一个功能应该拆成什么函数、放在什么层次。1.2 技术选型用链表还是数组很多网上的代码还在用静态结构体数组比如struct student stu[100]。这种写法最大的好处是理解门槛低下标访问直接排序和交换也直观。但它的短板太致命了容量固定超过上限就直接溢出删除元素要整体移动后面所有元素性能差还容易漏如果你在答辩时跟老师说这叫学生信息管理系统老师大概率会追问一句如果学生人数超过了100怎么办答不好就是送命题。我的建议是直接用链表。链表的动态内存分配特性让系统的容量几乎没有上限删除和插入只需要改指针不需要移动大量数据。对于学完指针和结构体的课程设计阶段链表正好是检验你这两块掌握程度的最佳载体。而且链表和文件配合也顺理成章遍历链表写入文件再从文件逐条读出重建链表逻辑清晰。也有人会问能不能用动态数组realloc来实现。能干但你会发现删除操作和内存管理都要自己小心翼翼维护比链表更容易出bug。链表写起来虽然多几行代码但每一步都有章可循更适合这个阶段。1.3 模块划分与代码结构我拿到这个题目后没有直接开写而是先画了系统的模块图虽然交作业不用交但脑子里必须有。整体分成三层第一层是数据层定义结构体和链表的节点类型这是所有操作的基石。第二层是业务逻辑层所有功能函数都在这层实现。包括链表的创建、插入、删除、查找、修改、排序、统计、展示以及文件的保存和加载。第三层是交互层也就是main函数和菜单函数。负责显示菜单、读取用户输入、调用对应的业务函数。这样分的直接好处是你写完了插入函数后面删除函数里需要遍历链表直接复用查找逻辑就行。修改函数里需要找到学号对应的节点也直接调用查找函数。代码量从堆一起的一坨变成各干各的积木块出bug的时候定位也快。2. 数据结构与核心实现思路2.1 学生信息结构体的设计细节学生信息结构体的字段看起来就是照着题目抄但实际上有讲究。学号我建议用字符数组而不是整型或长整型。为什么第一学号可能会包含字母比如2023C001整型根本存不下。第二即使纯数字如果定义成整型输入012345和12345就会被识别成同一个值这不符合学号的实际语义。很多同学在这里栽过跟头老师输入一个带前导0的学号程序自动把0吃了后面按学号查找的时候怎么都对不上。字段类型设计参考#define NAME_LEN 20 #define ID_LEN 15 typedef struct student { char id[ID_LEN]; // 学号用字符串存储 char name[NAME_LEN]; // 姓名 char gender[4]; // 性别男 或 女 int age; // 年龄 char class_id[10]; // 班级 float score_c; // C语言成绩 float score_math; // 数学成绩 float score_eng; // 英语成绩 } Student;然后定义链表节点typedef struct node { Student data; // 数据域直接嵌套结构体 struct node *next; // 指针域 } Node;把数据域直接放在节点里比用指针指向Student更省事。因为后面排序时如果只交换节点里的data而保持指针关系不变操作会非常简单。这个技巧在看到排序实现时会感受到巨大优势。2.2 链表操作的核心函数封装链表操作的本质就是维护好头指针和每个节点的next指针。我把这一层的函数全部封装好每个函数只做一件事方便后续模块调用。首先是创建链表头节点以及根据用户输入创建新节点Node *createList() { return NULL; // 空链表头指针置为NULL } Node *createNode(Student stu) { Node *newNode (Node *)malloc(sizeof(Node)); if (newNode NULL) { printf(内存分配失败\n); exit(1); } newNode-data stu; newNode-next NULL; return newNode; }内存分配失败一定要判断这是很多初学者容易忽略的地方。平时写小项目几乎不会遇到分配失败但养成判断的习惯后面写任何带动态内存的程序都不容易出大事故。然后是插入。按学号从小到大有序插入这样每次显示数据的时候天然就是有序的不用每次都排序Node *insertNode(Node *head, Node *newNode) { if (head NULL) { return newNode; } // 插到表头新节点学号比头节点小 if (strcmp(newNode-data.id, head-data.id) 0) { newNode-next head; return newNode; } // 遍历找到插入位置 Node *p head; while (p-next ! NULL strcmp(p-next-data.id, newNode-data.id) 0) { p p-next; } newNode-next p-next; p-next newNode; return head; }有序插入的好处非常明显。第一显示的时候不需要额外排序。第二插入逻辑本身也做了去重判断同一个学号不会出现两条记录。你可以在这个函数里加一个判断如果学号相等就提示已存在不插入。删除函数则需要先查找再删除。删除节点要注意区分删除的是头节点还是非头节点这里定义一个辅助指针prev用于记录前驱Node *deleteNode(Node *head, char *id) { Node *p head, *prev NULL; while (p ! NULL strcmp(p-data.id, id) ! 0) { prev p; p p-next; } if (p NULL) { printf(未找到学号为 %s 的学生\n, id); return head; } if (prev NULL) { head p-next; // 删除的是头节点 } else { prev-next p-next; } free(p); printf(删除成功\n); return head; }这段代码有一个容易被忽略但极为关键的细节在删除函数里游离了节点后函数需要通过返回值把头指针更新传出去。因为头指针本身也是局部变量如果删除的是头节点不返回新的头指针外部的head还是指向被释放的空间形成悬空指针。这个坑很多初学链表的人都会踩答辨时也常被重点追问。2.3 数据持久化文件读写方案学生信息管理系统如果不支持文件保存每次关了程序数据就没了那系统基本没有实际意义。所以文件读写是重点中的重点。我采用的是文本文件的存储方案文件名就叫students.txt每条记录占一行字段之间用逗号分隔。为什么选文本而不是二进制因为文本文件可以拿记事本直接打开方便检查数据正确性答辩时给老师演示也直观。二进制文件好处是读写快、占空间小但不可读调试不方便。保存函数的核心逻辑是遍历链表逐条输出到文件void saveToFile(Node *head, const char *filename) { FILE *fp fopen(filename, wb); if (fp NULL) { printf(无法打开文件 %s 保存数据\n, filename); return; } Node *p head; while (p ! NULL) { fprintf(fp, %s,%s,%s,%d,%s,%.2f,%.2f,%.2f\n, p-data.id, p-data.name, p-data.gender, p-data.age, p-data.class_id, p-data.score_c, p-data.score_math, p-data.score_eng); p p-next; } fclose(fp); printf(数据已保存到 %s\n, filename); }加载函数则是打开文件逐行读取并用sscanf把字符串解析成结构体字段Node *loadFromFile(Node *head, const char *filename) { FILE *fp fopen(filename, rb); if (fp NULL) { printf(未找到数据文件启动时初始化为空链表。\n); return head; } Student stu; while (fscanf(fp, %14[^,],%19[^,],%3[^,],%d,%9[^,],%f,%f,%f\n, stu.id, stu.name, stu.gender, stu.age, stu.class_id, stu.score_c, stu.score_math, stu.score_eng) 8) { Node *newNode createNode(stu); head insertNode(head, newNode); } fclose(fp); printf(数据加载完成共 %d 条记录。\n, countNodes(head)); return head; }这里有个很关键的格式细节%14[^,]表示最多读取14个非逗号字符防止缓冲区溢出。如果你直接写%s遇到中文姓名或边界情况容易出问题。fscanf的返回值等于8说明成功读取了8个字段用来判断是否读到文件末尾比feof更可靠。这些细节都是我在调试时踩出来的写的时候不觉得一跑数据不对就明白了。3. 关键功能模块的代码实现3.1 主菜单与用户交互循环菜单交互是整个系统的门面。我采用do-while循环加switch分支的结构选择0退出循环。一个常见的问题是用户输入了非数字字符scanf(%d, choice)会陷入死循环因为非数字字符没有被消费掉。我的做法是读取输入后用getchar()把缓冲区清空再用while(getchar() ! \n)处理掉换行int menu() { int choice; printf(\n 学生信息管理系统 \n); printf(1. 添加学生信息\n); printf(2. 删除学生信息\n); printf(3. 修改学生信息\n); printf(4. 查找学生信息\n); printf(5. 显示全部学生\n); printf(6. 按成绩排序\n); printf(7. 统计信息\n); printf(8. 保存数据到文件\n); printf(9. 从文件加载数据\n); printf(0. 退出系统\n); printf(请输入你的选择); scanf(%d, choice); while (getchar() ! \n); // 吸收多余字符 return choice; }很多代码把菜单函数和main函数的选择逻辑分开写这是对的。菜单函数只负责显示和读入选择main函数根据返回值调用对应模块各干各的后面想加功能也方便。3.2 添加与删除功能的完整逻辑添加学生的函数核心是交互录入和有序插入Node *addStudent(Node *head) { Student stu; printf(请输入学号); scanf(%s, stu.id); // 先检查学号是否已存在 if (findById(head, stu.id) ! NULL) { printf(该学号已存在无法重复添加\n); return head; } printf(请输入姓名); scanf(%s, stu.name); printf(请输入性别男/女); scanf(%s, stu.gender); printf(请输入年龄); scanf(%d, stu.age); printf(请输入班级); scanf(%s, stu.class_id); printf(请输入C语言成绩); scanf(%f, stu.score_c); printf(请输入数学成绩); scanf(%f, stu.score_math); printf(请输入英语成绩); scanf(%f, stu.score_eng); Node *newNode createNode(stu); head insertNode(head, newNode); printf(添加成功\n); return head; }这里的关键点是先查重再插入否则链表里可能出现重复学号后面的查找和删除都会出错。修改学生信息的逻辑也一样先按学号找到节点然后对p-data直接赋值更新返回不为NULL说明修改成功返回NULL说明没找到。3.3 排序功能好用的冒泡排序写法和思路很多人排序时习惯对节点指针进行交换但实际上有一个更稳的方只要交换链表节点里的Student数据域链表指针关系完全不用动用类似数组冒泡排序的思路就能完成。因为链表的有序插入保证了初始状态基本有序直接用冒泡排序性能完全够。按总分排序的核心代码void sortByTotal(Node *head) { if (head NULL) return; int swapped; Node *p; do { swapped 0; p head; while (p-next ! NULL) { float total1 p-data.score_c p-data.score_math p-data.score_eng; float total2 p-next-data.score_c p-next-data.score_math p-next-data.score_eng; if (total1 total2) { Student temp p-data; p-data p-next-data; p-next-data temp; swapped 1; } p p-next; } } while (swapped); printf(按总分从高到低排序完成\n); }注意这里用了do-while加swapped标志的优化版冒泡一趟没有交换就说明已经有序提前退出。链表节点本身的next指向完全不动只交换数据域逻辑简单且不易出错。如果你真要交换节点指针那要考虑前驱节点、头节点等各种情况非常容易写出野指针。3.4 统计模块与模糊查询技巧统计模块按班级统计平均分、最高分、最低分、及格率。这里可以加一个班级过滤参数也可以用循环遍历所有学生分类统计。最简单的实现是遍历链表把所有班级信息打出来然后对每个班级分别统计。查询模块按学号精确查找是我之前写好的findById直接线性遍历。但很多题目的进阶要求是按姓名模糊查找比如输入张能找到所有姓张的人。模糊匹配最简单的方法是逐个字符前缀匹配但更通用的做法是调用C标准库的strstr函数void searchByName(Node *head, const char *name) { Node *p head; int found 0; while (p ! NULL) { if (strstr(p-data.name, name) ! NULL) { printStudent(p-data); found 1; } p p-next; } if (!found) { printf(未找到姓名包含 %s 的学生\n, name); } }strstr的语义是在前面字符串中查找后一个字符串首次出现的位置如果返回非NULL就说明包含。这个函数用来做模糊搜索非常顺手。printf和scanf处理中文字符串时边界、空格等问题要注意如果需要支持带空格的名字就要用gets或者scanf(%[^\n])而不是scanf(%s)但大作业阶段要求不高用%s够用。4. vs2022环境配置与编译细节4.1 创建项目与语言标准设置在vs2022里新建C语言项目有个小坑vs2022默认的C语言标准是较老的C89如果你用了变长数组、for(int i0;...这类C99特性编译器会报错。解决办法是配置项目属性。步骤是这样打开vs2022创建新项目选择空项目语言选C因为vs的项目类型里C和C是同一个容器然后在项目上右键选属性 → C/C → 命令行在其他选项里加上/std:c11。这个选项是让编译器按C11标准编译vs2022支持C11和部分C17。具体流程文件 → 新建 → 项目筛选器选C选择空项目。项目名称填StudentSystem位置选好创建。在源文件上右键 → 添加 → 新建项选择C文件(.cpp)但文件后缀名改成.c。这一步很关键vs2022根据后缀判断编译方式后缀是.c就按C语言编译。把代码粘进去编译。如果遇到C语言标准问题就在项目属性里改。下面有详细说明。4.2 常见编译报错与解决方案我在vs2022里实际编译运行这个学生信息管理系统时遇到过几类报错这里整理成一张排查表错误信息出现原因解决方案error C4996: scanf was declared deprecatedvs默认禁止使用旧版C函数在代码第一行加#define _CRT_SECURE_NO_WARNINGS或在项目属性-预处理器定义里加_CRT_SECURE_NO_WARNINGSerror C2065: for 循环初始化声明编译器按C89标准编译属性 → C/C → 命令行 → 添加/std:c11或者把所有循环变量声明提到函数开头error C2447: missing function header函数定义写错了或前面少了分号往前检查头文件结束、上一行加分号warning C4013: strstr undefined忘了包含string.h在文件头部加#include string.hlink error LNK2019: unresolved external symbol函数只有声明没有定义或拼写不一致检查函数名拼写尤其是大小写和下划线C4996是最常见的因为vs一直鼓励用scanf_s替代scanf。但大作业的代码很多都是网上同步的改成scanf_s改动量大还容易出错我的建议是直接在代码最上面加#define _CRT_SECURE_NO_WARNINGS整个世界清爽。4.3 调试工具的使用心得vs2022的调试器是这个项目排查Bug的最大帮手。说实话写链表程序尤其是涉及到多级指针和头指针更新的时候纸上谈兵是看不出问题的必须靠断点。我的调试习惯是这样先在菜单入口和插入函数各打一个断点然后按F11逐步往下。重点观察头指针head的值以及每个节点的next是否指向正确地址。在监视窗口里展开head-data.id直接看内存值。比如你插入第一个节点后head应该指向一个新地址插入第二个节点后如果地址没有变化或者next显示异常值基本可以定位是哪一步指针没改对。另外vs2022还有个很好用的内存窗口菜单调试-窗口-内存输入变量地址可以直接看内存里的原始字节。这个对排查结构体内存对齐问题和数组越界很有帮助。有一次我排查排序乱序问题就是因为结构体里字符串数组的大小定义不对sscanf把超长输入写到了相邻变量里改掉缓冲区大小立刻正常。5. 完整运行流程与边界情况测试5.1 从编码到运行的完整流程把代码按照模块顺序写完后我直接在vs2022里按CtrlF5编译运行。第一次跑的时候菜单一直重复但只要输入6排序、输入5显示程序行为就正常我当时还以为是排序函数写错了。后来发现是自己逻辑写错了主循环里while(choice ! 0)但每次循环开始前菜单函数都会重新输出一遍这在视觉上就容易误会。其实不是跳过是因为没有清屏。加上system(cls)后整体界面才清晰。完整的测试流程如下首次运行提示未找到数据文件初始化为空链表此时显示0条记录。连续添加5个学生故意让学号顺序乱序输入比如3号、1号、5号、2号、4号添加后使用显示功能看是否已经按学号自动排好序。删除其中1号学生再次显示确认记录数量和顺序正确。修改3号学生的成绩显示确认更新。按总分排序确认顺序从高到低。统计功能确认平均分和及格率计算正确。保存数据到文件退出程序。重新运行程序加载文件显示数据确认数据完整恢复。整个流程走完系统的基本功能就都经过了验证。真正重要的其实是第三步和第八步分别对应链表删除和文件持久化也是最容易出问题的两个环节。5.2 边界情况怎么做才不翻车真正的测试不在于正常流程而在于边界情况。我总结了下面这些场景每个都要实际跑一遍空链表时执行删除、查找、排序和统计程序应当提示链表为空而不是崩溃。删除链表中唯一一个节点头指针要正确更新为NULL。删除不存在的学号程序应当友好提示未找到。添加已有学号的学生要提示学号重复不能真的插入。学号输入超过14个字符会不会缓冲区溢出导致程序崩溃。成绩输入负数或大于100要不要做合法性校验。文件不存在或格式被手动改坏时加载函数能不能稳定退出而不是死循环。这里我强烈建议在添加学生时加上成绩范围的校验虽然很多课程设计要求不写但加了你就能在答辩时多讲一条我做了输入合法性的检查这是加分项if (stu.score_c 0 || stu.score_c 100 || stu.score_math 0 || stu.score_math 100 || stu.score_eng 0 || stu.score_eng 100) { printf(成绩必须在0~100之间请重新输入\n); return head; }别小看这几行答辩时老师随手输入一个600分的成绩如果你的程序能拦截印象分直接拉满。5.3 文件加载里的一个关键边界问题文件加载函数我最开始是用feof(fp)判断文件是否读完结果总是多读一条数据最后链表的末尾会多出一个全是空值的节点。原因是feof只有在尝试读取越过文件末尾之后才会返回真也就是说最后一次成功读取后feof仍然是假进入循环再次调用fscanf此时fscanf失败但feof才变成真。这个时序问题绕了不少人。用fscanf的返回值来判断就完全没这个问题。成功解析8个字段返回8没读到或格式不对返回EOF或者小于8循环自然终止。这算是我在这个项目里学到最实用的一个文件读取技巧。同理网上很多代码用while(!feof(fp))读文件然后多出一行空数据基本都是这个原因。6. 常见问题与避坑经验6.1 最容易踩的五个坑结合我自己的调试经历和帮别人看代码的经验这个项目最容易出问题的地方集中在以下五个第一个坑是scanf缓冲区残留。scanf读取完数字后换行符还留在缓冲区里如果后面跟着gets或者另一个scanf(%c)就会读到残留的换行。这个问题我建议直接统一解决在每次scanf之后用while(getchar() ! \n);消费掉换行符。第二个坑是free了之后还在使用。删除节点后p还指向原来那块内存如果后面不小心再访问p-next就会读取到已经被系统回收的内存轻则数据错乱重则直接报错。解决办法在free之后立即习惯性把指针置为NULL。第三个坑是头指针悬空。删除头节点时如果不用返回值把它更新出去外面的head还在指那个已经free掉的内存。我在前面的deleteNode函数里特别返回了新的head就是为了一次性解决这个问题。很多同学的代码在这里卡很久建议对照检查。第四个坑是文件读取时用错了格式串导致学号和姓名错位。比如数据文件里学号是12位你格式串里写%s读取中文姓名带空格时就会出问题。解决思路是用%[^,]限定读取非逗号字符同时保证数组长度足够。第五个坑是忘记判断malloc返回值。虽然项目里很少真的分配失败但一旦分配失败又不检查程序直接解引用NULL指针崩溃调试半天找不出原因。你要在写代码的时候就养成习惯。6.2 答辩时的常见追问和应对很多同学代码写完了但答辨时老师问几个问题就慌了。这里把老师最常问的几个问题和应对思路整理出来老师会问链表和数组的区别是什么。回答思路数组是连续内存、随机访问快、但容量固定、插入删除要移动数据链表是离散内存、插入删除只需改指针、但随机访问必须遍历且每个节点有额外的指针开销。老师会问为什么文件打开失败要有提示但程序不能崩溃。回答思路文件可能不存在或没有权限如果直接读写会导致未定义行为提示后可以让用户重新操作。老师会问你的排序是怎么实现的时间复杂度是多少。回答思路说明交换的是节点里的数据域没有改节点指针冒泡排序的时间复杂度是O(n^2)数据量小几百人时性能足够如果数据量大可以用归并或快排但为了课程设计让代码容易理解冒泡是最合适的。老师会问如果文件里有一行脏数据怎么办。如果你在加载函数里用了fscanf返回值判断就可以回答程序会跳过损坏的记录能正常加载剩余有效数据这是一个很有加分的回答。这些问题的核心其实就是在考察你到底是不是真懂自己的代码。所以答辩前把你的每个函数重新读一遍确保每行代码都能说出为什么这么写比你背任何答案都管用。6.3 提高代码质量的小建议代码完成后我习惯性地做一轮清理。把printf里零散的提示语统一格式比如所有成功提示都以成功结尾所有失败提示都以失败或未找到开头。删除多余的注释只保留函数头部说明和关键逻辑的注释。变量命名尽量用完整单词不用a、b、c这种无意义命名。这些习惯看着小但在答辩时老师打开你的代码第一眼就能感受到差异。另外我建议你把所有函数声明集中放到头文件里student.h中声明所有接口.c文件中实现这样代码结构会显得更专业。虽然课程设计不要求多文件但你主动这么做了老师第一印象就会不同。还有一个实际经验代码写完后至少在一个全新的vs2022项目里重新编译运行一遍确保不依赖你机器上的特殊设置。你可以把整个项目文件夹压缩发给同学让他在另一台电脑上打开运行。如果在别人的电脑上能直接跑通才说明工程配置完全正确。7. 一些实操心得做这个项目最大的收获不是我写出了一个系统而是真正理解了C语言的内存管理是怎么回事。你在数组里写代码永远感受不到野指针和悬空指针的可怕。但只要用链表free一个节点后你就会自然而然地想现在还有什么地方指向这块内存吗这种意识才是写C语言最值钱的东西。文件名我一开始用的全英文students.txt结果在加载时发现含有中文路径的情况可能会导致打不开改成相对路径后就好了。这里建议项目的路径不要太复杂尽量不要放在带空格的目录里。如果你用vs2022的默认路径用户目录名字是中文或者包含空格某些老旧的代码用fopen打开文件就可能出问题。这个概率不大但碰到了就很烦。最后分享一个我自己觉得特别有用的小技巧在调试菜单函数的时候可以临时加一个自动添加测试数据的函数initTestData()在里面写死几个学生信息一键填充。这样每次调试排序、统计、文件保存时不用手动一条一条录入效率高很多。答辩前再把这个函数从菜单里注释或移除就行。这个技巧对你自己日常改代码的便利性提升非常大我后来写别的链表项目也一直在用。本文还有配套的精品资源点击获取
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻