1 项目概述1.1 项目目标开发一个基于命令行的学生信息管理系统实现对学生信息的增、删、改、查、统计等基本功能并将数据持久化保存到文件中。1.2 技术栈开发语言C语言数据结构链表动态存储持久化二进制文件读写开发环境任意C编译器GCC/Clang/MSVC1.3 功能需求功能编号功能名称描述F01添加学生添加新的学生记录F02删除学生按学号删除学生记录F03修改学生按学号修改学生信息F04查询学生按学号/姓名查询学生F05显示所有显示所有学生信息F06统计信息统计学生总数、平均分、最高/最低分F07按成绩排序按成绩从高到低显示F08保存数据将数据保存到文件F09加载数据从文件加载数据F10退出系统退出程序2 系统设计2.1 模块划分text学生信息管理系统 ├── 数据结构模块 (student.h) │ ├── 学生结构体定义 │ └── 链表节点结构体定义 ├── 链表操作模块 (list.c) │ ├── 创建节点 │ ├── 插入节点 │ ├── 删除节点 │ ├── 查找节点 │ └── 释放链表 ├── 学生管理模块 (student.c) │ ├── 添加学生 │ ├── 删除学生 │ ├── 修改学生 │ ├── 查询学生 │ └── 统计信息 ├── 文件操作模块 (file.c) │ ├── 保存数据 │ └── 加载数据 ├── 用户界面模块 (ui.c) │ ├── 显示菜单 │ ├── 显示学生信息 │ └── 获取用户输入 └── 主程序模块 (main.c) ├── 主循环 └── 程序入口2.2 数据结构设计c/* 学生信息结构体 */ typedef struct { int id; /* 学号唯一标识 */ char name[20]; /* 姓名 */ int age; /* 年龄 */ float score; /* 成绩 */ } Student; /* 链表节点结构体 */ typedef struct Node { Student data; /* 学生数据 */ struct Node *next; /* 指向下一个节点 */ } Node;2.3 文件存储格式采用二进制文件存储每次保存时写入所有学生数据加载时全部读入内存。text文件结构 ------------------ | 学生1的记录 | (sizeof(Student) 字节) ------------------ | 学生2的记录 | ------------------ | ... | ------------------3 完整代码实现3.1 student.h - 数据结构定义c#ifndef STUDENT_H #define STUDENT_H #include stdio.h #include stdlib.h #include string.h /* 学生信息结构体 */ typedef struct { int id; /* 学号 */ char name[20]; /* 姓名 */ int age; /* 年龄 */ float score; /* 成绩 */ } Student; /* 链表节点结构体 */ typedef struct Node { Student data; struct Node *next; } Node; /* 函数声明 */ Node* create_node(Student stu); Node* insert_node(Node *head, Student stu); Node* delete_node(Node *head, int id); Node* update_node(Node *head, int id, Student new_stu); Node* find_by_id(Node *head, int id, Student *result); void find_by_name(Node *head, const char *name); void print_student(const Student *stu); void print_all(Node *head); int get_count(Node *head); void get_statistics(Node *head, float *avg, float *max, float *min); void sort_by_score(Node *head); void free_list(Node *head); /* 文件操作 */ int save_to_file(Node *head, const char *filename); Node* load_from_file(const char *filename); #endif3.2 list.c - 链表操作实现c#include student.h /* 创建新节点 */ Node* create_node(Student stu) { Node *new_node (Node*)malloc(sizeof(Node)); if (new_node NULL) { printf(内存分配失败\n); return NULL; } new_node-data stu; new_node-next NULL; return new_node; } /* 插入节点按学号升序插入 */ Node* insert_node(Node *head, Student stu) { Node *new_node create_node(stu); if (new_node NULL) return head; /* 空链表或新节点学号最小插入头部 */ if (head NULL || stu.id head-data.id) { new_node-next head; return new_node; } /* 找到插入位置 */ Node *prev head; Node *curr head-next; while (curr ! NULL curr-data.id stu.id) { prev curr; curr curr-next; } /* 检查学号是否已存在 */ if (curr ! NULL curr-data.id stu.id) { printf(学号 %d 已存在插入失败\n, stu.id); free(new_node); return head; } prev-next new_node; new_node-next curr; return head; } /* 删除节点按学号 */ Node* delete_node(Node *head, int id) { if (head NULL) { printf(链表为空\n); return NULL; } /* 删除头节点 */ if (head-data.id id) { Node *temp head; head head-next; free(temp); printf(删除成功\n); return head; } /* 查找要删除的节点 */ Node *prev head; Node *curr head-next; while (curr ! NULL curr-data.id ! id) { prev curr; curr curr-next; } if (curr NULL) { printf(未找到学号 %d\n, id); return head; } prev-next curr-next; free(curr); printf(删除成功\n); return head; } /* 更新节点信息 */ Node* update_node(Node *head, int id, Student new_stu) { Node *curr head; while (curr ! NULL curr-data.id ! id) { curr curr-next; } if (curr NULL) { printf(未找到学号 %d\n, id); return head; } /* 保持学号不变 */ new_stu.id id; curr-data new_stu; printf(更新成功\n); return head; } /* 按学号查找 */ Node* find_by_id(Node *head, int id, Student *result) { Node *curr head; while (curr ! NULL curr-data.id ! id) { curr curr-next; } if (curr ! NULL) { *result curr-data; return curr; } return NULL; } /* 按姓名查找打印所有匹配的 */ void find_by_name(Node *head, const char *name) { Node *curr head; int found 0; printf(\n查找结果\n); printf(学号\t姓名\t年龄\t成绩\n); printf(----------------------------\n); while (curr ! NULL) { if (strcmp(curr-data.name, name) 0) { printf(%d\t%s\t%d\t%.1f\n, curr-data.id, curr-data.name, curr-data.age, curr-data.score); found 1; } curr curr-next; } if (!found) { printf(未找到姓名为 %s 的学生\n, name); } } /* 获取学生总数 */ int get_count(Node *head) { int count 0; Node *curr head; while (curr ! NULL) { count; curr curr-next; } return count; } /* 统计信息 */ void get_statistics(Node *head, float *avg, float *max, float *min) { if (head NULL) { *avg *max *min 0; return; } float sum 0; int count 0; *max head-data.score; *min head-data.score; Node *curr head; while (curr ! NULL) { sum curr-data.score; count; if (curr-data.score *max) *max curr-data.score; if (curr-data.score *min) *min curr-data.score; curr curr-next; } *avg sum / count; } /* 按成绩排序冒泡排序只交换数据不改变指针 */ void sort_by_score(Node *head) {{ if (head NULL) return; int swapped; Node *p; Node *q NULL; do { swapped 0; p head; while (p-next ! q) { if (p-data.score p-next-data.score) { /* 交换数据 */ Student temp p-data; p-data p-next-data; p-next-data temp; swapped 1; } p p-next; } q p; } while (swapped); printf(排序完成按成绩从高到低\n); } /* 释放链表 */ void free_list(Node *head) { Node *curr head; Node *next; while (curr ! NULL) { next curr-next; free(curr); curr next; } }3.3 student.c - 学生管理操作c#include student.h /* 打印单个学生信息 */ void print_student(const Student *stu) { printf(%d\t%s\t%d\t%.1f\n, stu-id, stu-name, stu-age, stu-score); } /* 打印所有学生 */ void print_all(Node *head) { if (head NULL) { printf(暂无学生数据\n); return; } printf(\n学生列表\n); printf(学号\t姓名\t年龄\t成绩\n); printf(----------------------------\n); Node *curr head; while (curr ! NULL) { print_student(curr-data); curr curr-next; } printf(共 %d 条记录\n, get_count(head)); } /* 添加学生交互式 */ Node* add_student_interactive(Node *head) { Student stu; printf(\n--- 添加学生 ---\n); printf(学号); scanf(%d, stu.id); /* 检查学号是否已存在 */ Student existing; if (find_by_id(head, stu.id, existing) ! NULL) { printf(学号 %d 已存在\n, stu.id); return head; } printf(姓名); scanf(%s, stu.name); printf(年龄); scanf(%d, stu.age); printf(成绩); scanf(%f, stu.score); return insert_node(head, stu); } /* 删除学生交互式 */ Node* delete_student_interactive(Node *head) { int id; printf(\n--- 删除学生 ---\n); printf(请输入要删除的学号); scanf(%d, id); return delete_node(head, id); } /* 修改学生交互式 */ Node* update_student_interactive(Node *head) { int id; Student stu; printf(\n--- 修改学生 ---\n); printf(请输入要修改的学号); scanf(%d, id); /* 检查是否存在 */ Student existing; if (find_by_id(head, id, existing) NULL) { printf(未找到学号 %d\n, id); return head; } printf(请输入新的姓名); scanf(%s, stu.name); printf(请输入新的年龄); scanf(%d, stu.age); printf(请输入新的成绩); scanf(%f, stu.score); return update_node(head, id, stu); } /* 查询学生交互式 */ void query_student_interactive(Node *head) { int choice; int id; char name[20]; Student stu; if (head NULL) { printf(暂无学生数据\n); return; } printf(\n--- 查询学生 ---\n); printf(1. 按学号查询\n); printf(2. 按姓名查询\n); printf(请选择); scanf(%d, choice); if (choice 1) { printf(请输入学号); scanf(%d, id); if (find_by_id(head, id, stu) ! NULL) { printf(\n查询结果\n); printf(学号\t姓名\t年龄\t成绩\n); printf(----------------------------\n); print_student(stu); } else { printf(未找到学号 %d\n, id); } } else if (choice 2) { printf(请输入姓名); scanf(%s, name); find_by_name(head, name); } else { printf(无效选择\n); } } /* 显示统计信息 */ void show_statistics(Node *head) { float avg, max, min; if (head NULL) { printf(暂无学生数据\n); return; } get_statistics(head, avg, max, min); printf(\n--- 统计信息 ---\n); printf(学生总数%d\n, get_count(head)); printf(平均成绩%.2f\n, avg); printf(最高成绩%.2f\n, max); printf(最低成绩%.2f\n, min); }3.4 file.c - 文件操作c#include student.h /* 保存数据到文件 */ int save_to_file(Node *head, const char *filename) { FILE *fp fopen(filename, wb); if (fp NULL) { printf(无法打开文件 %s 进行写入\n, filename); return -1; } Node *curr head; int count 0; while (curr ! NULL) { fwrite(curr-data, sizeof(Student), 1, fp); curr curr-next; count; } fclose(fp); printf(成功保存 %d 条记录到 %s\n, count, filename); return 0; } /* 从文件加载数据 */ Node* load_from_file(const char *filename) { FILE *fp fopen(filename, rb); if (fp NULL) { /* 文件不存在返回空链表 */ return NULL; } Node *head NULL; Student stu; int count 0; while (fread(stu, sizeof(Student), 1, fp) 1) { head insert_node(head, stu); count; } fclose(fp); if (count 0) { printf(成功从 %s 加载 %d 条记录\n, filename, count); } return head; }3.5 ui.c - 用户界面c#include student.h /* 显示主菜单 */ void show_menu(void) { printf(\n\n); printf( 学生信息管理系统 v1.0\n); printf(\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(\n); printf(请选择); } /* 显示操作结果 */ void show_result(int success, const char *msg) { if (success) { printf(✓ %s\n, msg); } else { printf(✗ %s\n, msg); } } /* 等待用户按回车继续 */ void wait_for_enter(void) { printf(\n按回车键继续...); while (getchar() ! \n); getchar(); }3.6 main.c - 主程序c#include student.h #define DATA_FILE students.dat int main(void) { Node *head NULL; int choice; printf(\n\n); printf( 学生信息管理系统\n); printf( 欢迎使用\n); printf(\n); /* 尝试加载已有数据 */ head load_from_file(DATA_FILE); if (head NULL) { printf(未找到数据文件将创建新系统\n); } do { show_menu(); scanf(%d, choice); switch (choice) { case 1: /* 添加学生 */ head add_student_interactive(head); break; case 2: /* 删除学生 */ head delete_student_interactive(head); break; case 3: /* 修改学生 */ head update_student_interactive(head); break; case 4: /* 查询学生 */ query_student_interactive(head); break; case 5: /* 显示所有 */ print_all(head); break; case 6: /* 统计信息 */ show_statistics(head); break; case 7: /* 按成绩排序 */ sort_by_score(head); print_all(head); break; case 8: /* 保存数据 */ save_to_file(head, DATA_FILE); break; case 9: /* 加载数据 */ /* 先释放当前数据 */ free_list(head); head load_from_file(DATA_FILE); break; case 0: /* 退出 */ printf(\n正在退出系统...\n); /* 询问是否保存 */ if (get_count(head) 0) { char confirm; printf(是否保存数据(y/n)); scanf( %c, confirm); if (confirm y || confirm Y) { save_to_file(head, DATA_FILE); } } break; default: printf(无效选择请重新输入\n); } if (choice ! 0) { /* 等待用户按回车继续 */ printf(\n); } } while (choice ! 0); /* 释放链表 */ free_list(head); printf(感谢使用再见\n); return 0; }4 项目总结4.1 功能测试示例text 学生信息管理系统 v1.0 1. 添加学生 2. 删除学生 3. 修改学生 4. 查询学生 5. 显示所有学生 6. 统计信息 7. 按成绩排序 8. 保存数据 9. 加载数据 0. 退出系统 请选择1 --- 添加学生 --- 学号1001 姓名张三 年龄20 成绩88.5 请选择1 --- 添加学生 --- 学号1002 姓名李四 年龄21 成绩92.0 请选择5 学生列表 学号 姓名 年龄 成绩 ---------------------------- 1001 张三 20 88.5 1002 李四 21 92.0 共 2 条记录4.2 本专栏学习路线回顾本专栏共40篇覆盖了C语言的核心知识点阶段篇章核心内容筑基篇1-4环境搭建、编译原理、程序结构、编码规范基础篇5-11数据类型、运算符、控制结构、输入输出进阶篇12-16选择结构、循环结构、循环控制数组与指针17-22一维/二维数组、字符数组、结构体、共用体、枚举函数与指针23-26函数定义、调用机制、参数传递、作用域高级指针27-33指针与数组、指针与字符串、函数指针、动态内存、二级指针文件与结构34-38文件操作、二进制读写、链表预处理与实战39-40宏定义、条件编译、综合项目4.3 项目扩展建议增加更多字段添加性别、班级、电话、地址等字段增加数据校验学号唯一性、年龄范围、成绩范围等支持模糊查询姓名模糊匹配、按分数段查询增加成绩分析优秀率、及格率、分数段统计导出报表导出为CSV/HTML格式增加登录功能简单的用户认证多表关联班级表、课程表、成绩表
【C语言程序设计】第40篇:综合项目实践:基于C语言的学生信息管理系统
1 项目概述1.1 项目目标开发一个基于命令行的学生信息管理系统实现对学生信息的增、删、改、查、统计等基本功能并将数据持久化保存到文件中。1.2 技术栈开发语言C语言数据结构链表动态存储持久化二进制文件读写开发环境任意C编译器GCC/Clang/MSVC1.3 功能需求功能编号功能名称描述F01添加学生添加新的学生记录F02删除学生按学号删除学生记录F03修改学生按学号修改学生信息F04查询学生按学号/姓名查询学生F05显示所有显示所有学生信息F06统计信息统计学生总数、平均分、最高/最低分F07按成绩排序按成绩从高到低显示F08保存数据将数据保存到文件F09加载数据从文件加载数据F10退出系统退出程序2 系统设计2.1 模块划分text学生信息管理系统 ├── 数据结构模块 (student.h) │ ├── 学生结构体定义 │ └── 链表节点结构体定义 ├── 链表操作模块 (list.c) │ ├── 创建节点 │ ├── 插入节点 │ ├── 删除节点 │ ├── 查找节点 │ └── 释放链表 ├── 学生管理模块 (student.c) │ ├── 添加学生 │ ├── 删除学生 │ ├── 修改学生 │ ├── 查询学生 │ └── 统计信息 ├── 文件操作模块 (file.c) │ ├── 保存数据 │ └── 加载数据 ├── 用户界面模块 (ui.c) │ ├── 显示菜单 │ ├── 显示学生信息 │ └── 获取用户输入 └── 主程序模块 (main.c) ├── 主循环 └── 程序入口2.2 数据结构设计c/* 学生信息结构体 */ typedef struct { int id; /* 学号唯一标识 */ char name[20]; /* 姓名 */ int age; /* 年龄 */ float score; /* 成绩 */ } Student; /* 链表节点结构体 */ typedef struct Node { Student data; /* 学生数据 */ struct Node *next; /* 指向下一个节点 */ } Node;2.3 文件存储格式采用二进制文件存储每次保存时写入所有学生数据加载时全部读入内存。text文件结构 ------------------ | 学生1的记录 | (sizeof(Student) 字节) ------------------ | 学生2的记录 | ------------------ | ... | ------------------3 完整代码实现3.1 student.h - 数据结构定义c#ifndef STUDENT_H #define STUDENT_H #include stdio.h #include stdlib.h #include string.h /* 学生信息结构体 */ typedef struct { int id; /* 学号 */ char name[20]; /* 姓名 */ int age; /* 年龄 */ float score; /* 成绩 */ } Student; /* 链表节点结构体 */ typedef struct Node { Student data; struct Node *next; } Node; /* 函数声明 */ Node* create_node(Student stu); Node* insert_node(Node *head, Student stu); Node* delete_node(Node *head, int id); Node* update_node(Node *head, int id, Student new_stu); Node* find_by_id(Node *head, int id, Student *result); void find_by_name(Node *head, const char *name); void print_student(const Student *stu); void print_all(Node *head); int get_count(Node *head); void get_statistics(Node *head, float *avg, float *max, float *min); void sort_by_score(Node *head); void free_list(Node *head); /* 文件操作 */ int save_to_file(Node *head, const char *filename); Node* load_from_file(const char *filename); #endif3.2 list.c - 链表操作实现c#include student.h /* 创建新节点 */ Node* create_node(Student stu) { Node *new_node (Node*)malloc(sizeof(Node)); if (new_node NULL) { printf(内存分配失败\n); return NULL; } new_node-data stu; new_node-next NULL; return new_node; } /* 插入节点按学号升序插入 */ Node* insert_node(Node *head, Student stu) { Node *new_node create_node(stu); if (new_node NULL) return head; /* 空链表或新节点学号最小插入头部 */ if (head NULL || stu.id head-data.id) { new_node-next head; return new_node; } /* 找到插入位置 */ Node *prev head; Node *curr head-next; while (curr ! NULL curr-data.id stu.id) { prev curr; curr curr-next; } /* 检查学号是否已存在 */ if (curr ! NULL curr-data.id stu.id) { printf(学号 %d 已存在插入失败\n, stu.id); free(new_node); return head; } prev-next new_node; new_node-next curr; return head; } /* 删除节点按学号 */ Node* delete_node(Node *head, int id) { if (head NULL) { printf(链表为空\n); return NULL; } /* 删除头节点 */ if (head-data.id id) { Node *temp head; head head-next; free(temp); printf(删除成功\n); return head; } /* 查找要删除的节点 */ Node *prev head; Node *curr head-next; while (curr ! NULL curr-data.id ! id) { prev curr; curr curr-next; } if (curr NULL) { printf(未找到学号 %d\n, id); return head; } prev-next curr-next; free(curr); printf(删除成功\n); return head; } /* 更新节点信息 */ Node* update_node(Node *head, int id, Student new_stu) { Node *curr head; while (curr ! NULL curr-data.id ! id) { curr curr-next; } if (curr NULL) { printf(未找到学号 %d\n, id); return head; } /* 保持学号不变 */ new_stu.id id; curr-data new_stu; printf(更新成功\n); return head; } /* 按学号查找 */ Node* find_by_id(Node *head, int id, Student *result) { Node *curr head; while (curr ! NULL curr-data.id ! id) { curr curr-next; } if (curr ! NULL) { *result curr-data; return curr; } return NULL; } /* 按姓名查找打印所有匹配的 */ void find_by_name(Node *head, const char *name) { Node *curr head; int found 0; printf(\n查找结果\n); printf(学号\t姓名\t年龄\t成绩\n); printf(----------------------------\n); while (curr ! NULL) { if (strcmp(curr-data.name, name) 0) { printf(%d\t%s\t%d\t%.1f\n, curr-data.id, curr-data.name, curr-data.age, curr-data.score); found 1; } curr curr-next; } if (!found) { printf(未找到姓名为 %s 的学生\n, name); } } /* 获取学生总数 */ int get_count(Node *head) { int count 0; Node *curr head; while (curr ! NULL) { count; curr curr-next; } return count; } /* 统计信息 */ void get_statistics(Node *head, float *avg, float *max, float *min) { if (head NULL) { *avg *max *min 0; return; } float sum 0; int count 0; *max head-data.score; *min head-data.score; Node *curr head; while (curr ! NULL) { sum curr-data.score; count; if (curr-data.score *max) *max curr-data.score; if (curr-data.score *min) *min curr-data.score; curr curr-next; } *avg sum / count; } /* 按成绩排序冒泡排序只交换数据不改变指针 */ void sort_by_score(Node *head) {{ if (head NULL) return; int swapped; Node *p; Node *q NULL; do { swapped 0; p head; while (p-next ! q) { if (p-data.score p-next-data.score) { /* 交换数据 */ Student temp p-data; p-data p-next-data; p-next-data temp; swapped 1; } p p-next; } q p; } while (swapped); printf(排序完成按成绩从高到低\n); } /* 释放链表 */ void free_list(Node *head) { Node *curr head; Node *next; while (curr ! NULL) { next curr-next; free(curr); curr next; } }3.3 student.c - 学生管理操作c#include student.h /* 打印单个学生信息 */ void print_student(const Student *stu) { printf(%d\t%s\t%d\t%.1f\n, stu-id, stu-name, stu-age, stu-score); } /* 打印所有学生 */ void print_all(Node *head) { if (head NULL) { printf(暂无学生数据\n); return; } printf(\n学生列表\n); printf(学号\t姓名\t年龄\t成绩\n); printf(----------------------------\n); Node *curr head; while (curr ! NULL) { print_student(curr-data); curr curr-next; } printf(共 %d 条记录\n, get_count(head)); } /* 添加学生交互式 */ Node* add_student_interactive(Node *head) { Student stu; printf(\n--- 添加学生 ---\n); printf(学号); scanf(%d, stu.id); /* 检查学号是否已存在 */ Student existing; if (find_by_id(head, stu.id, existing) ! NULL) { printf(学号 %d 已存在\n, stu.id); return head; } printf(姓名); scanf(%s, stu.name); printf(年龄); scanf(%d, stu.age); printf(成绩); scanf(%f, stu.score); return insert_node(head, stu); } /* 删除学生交互式 */ Node* delete_student_interactive(Node *head) { int id; printf(\n--- 删除学生 ---\n); printf(请输入要删除的学号); scanf(%d, id); return delete_node(head, id); } /* 修改学生交互式 */ Node* update_student_interactive(Node *head) { int id; Student stu; printf(\n--- 修改学生 ---\n); printf(请输入要修改的学号); scanf(%d, id); /* 检查是否存在 */ Student existing; if (find_by_id(head, id, existing) NULL) { printf(未找到学号 %d\n, id); return head; } printf(请输入新的姓名); scanf(%s, stu.name); printf(请输入新的年龄); scanf(%d, stu.age); printf(请输入新的成绩); scanf(%f, stu.score); return update_node(head, id, stu); } /* 查询学生交互式 */ void query_student_interactive(Node *head) { int choice; int id; char name[20]; Student stu; if (head NULL) { printf(暂无学生数据\n); return; } printf(\n--- 查询学生 ---\n); printf(1. 按学号查询\n); printf(2. 按姓名查询\n); printf(请选择); scanf(%d, choice); if (choice 1) { printf(请输入学号); scanf(%d, id); if (find_by_id(head, id, stu) ! NULL) { printf(\n查询结果\n); printf(学号\t姓名\t年龄\t成绩\n); printf(----------------------------\n); print_student(stu); } else { printf(未找到学号 %d\n, id); } } else if (choice 2) { printf(请输入姓名); scanf(%s, name); find_by_name(head, name); } else { printf(无效选择\n); } } /* 显示统计信息 */ void show_statistics(Node *head) { float avg, max, min; if (head NULL) { printf(暂无学生数据\n); return; } get_statistics(head, avg, max, min); printf(\n--- 统计信息 ---\n); printf(学生总数%d\n, get_count(head)); printf(平均成绩%.2f\n, avg); printf(最高成绩%.2f\n, max); printf(最低成绩%.2f\n, min); }3.4 file.c - 文件操作c#include student.h /* 保存数据到文件 */ int save_to_file(Node *head, const char *filename) { FILE *fp fopen(filename, wb); if (fp NULL) { printf(无法打开文件 %s 进行写入\n, filename); return -1; } Node *curr head; int count 0; while (curr ! NULL) { fwrite(curr-data, sizeof(Student), 1, fp); curr curr-next; count; } fclose(fp); printf(成功保存 %d 条记录到 %s\n, count, filename); return 0; } /* 从文件加载数据 */ Node* load_from_file(const char *filename) { FILE *fp fopen(filename, rb); if (fp NULL) { /* 文件不存在返回空链表 */ return NULL; } Node *head NULL; Student stu; int count 0; while (fread(stu, sizeof(Student), 1, fp) 1) { head insert_node(head, stu); count; } fclose(fp); if (count 0) { printf(成功从 %s 加载 %d 条记录\n, filename, count); } return head; }3.5 ui.c - 用户界面c#include student.h /* 显示主菜单 */ void show_menu(void) { printf(\n\n); printf( 学生信息管理系统 v1.0\n); printf(\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(\n); printf(请选择); } /* 显示操作结果 */ void show_result(int success, const char *msg) { if (success) { printf(✓ %s\n, msg); } else { printf(✗ %s\n, msg); } } /* 等待用户按回车继续 */ void wait_for_enter(void) { printf(\n按回车键继续...); while (getchar() ! \n); getchar(); }3.6 main.c - 主程序c#include student.h #define DATA_FILE students.dat int main(void) { Node *head NULL; int choice; printf(\n\n); printf( 学生信息管理系统\n); printf( 欢迎使用\n); printf(\n); /* 尝试加载已有数据 */ head load_from_file(DATA_FILE); if (head NULL) { printf(未找到数据文件将创建新系统\n); } do { show_menu(); scanf(%d, choice); switch (choice) { case 1: /* 添加学生 */ head add_student_interactive(head); break; case 2: /* 删除学生 */ head delete_student_interactive(head); break; case 3: /* 修改学生 */ head update_student_interactive(head); break; case 4: /* 查询学生 */ query_student_interactive(head); break; case 5: /* 显示所有 */ print_all(head); break; case 6: /* 统计信息 */ show_statistics(head); break; case 7: /* 按成绩排序 */ sort_by_score(head); print_all(head); break; case 8: /* 保存数据 */ save_to_file(head, DATA_FILE); break; case 9: /* 加载数据 */ /* 先释放当前数据 */ free_list(head); head load_from_file(DATA_FILE); break; case 0: /* 退出 */ printf(\n正在退出系统...\n); /* 询问是否保存 */ if (get_count(head) 0) { char confirm; printf(是否保存数据(y/n)); scanf( %c, confirm); if (confirm y || confirm Y) { save_to_file(head, DATA_FILE); } } break; default: printf(无效选择请重新输入\n); } if (choice ! 0) { /* 等待用户按回车继续 */ printf(\n); } } while (choice ! 0); /* 释放链表 */ free_list(head); printf(感谢使用再见\n); return 0; }4 项目总结4.1 功能测试示例text 学生信息管理系统 v1.0 1. 添加学生 2. 删除学生 3. 修改学生 4. 查询学生 5. 显示所有学生 6. 统计信息 7. 按成绩排序 8. 保存数据 9. 加载数据 0. 退出系统 请选择1 --- 添加学生 --- 学号1001 姓名张三 年龄20 成绩88.5 请选择1 --- 添加学生 --- 学号1002 姓名李四 年龄21 成绩92.0 请选择5 学生列表 学号 姓名 年龄 成绩 ---------------------------- 1001 张三 20 88.5 1002 李四 21 92.0 共 2 条记录4.2 本专栏学习路线回顾本专栏共40篇覆盖了C语言的核心知识点阶段篇章核心内容筑基篇1-4环境搭建、编译原理、程序结构、编码规范基础篇5-11数据类型、运算符、控制结构、输入输出进阶篇12-16选择结构、循环结构、循环控制数组与指针17-22一维/二维数组、字符数组、结构体、共用体、枚举函数与指针23-26函数定义、调用机制、参数传递、作用域高级指针27-33指针与数组、指针与字符串、函数指针、动态内存、二级指针文件与结构34-38文件操作、二进制读写、链表预处理与实战39-40宏定义、条件编译、综合项目4.3 项目扩展建议增加更多字段添加性别、班级、电话、地址等字段增加数据校验学号唯一性、年龄范围、成绩范围等支持模糊查询姓名模糊匹配、按分数段查询增加成绩分析优秀率、及格率、分数段统计导出报表导出为CSV/HTML格式增加登录功能简单的用户认证多表关联班级表、课程表、成绩表