我们将构建一个基于控制台的学生信息管理系统,系统将使用结构体来存储每个学生的信息,并使用文件来持久化数据,确保程序关闭后数据不会丢失。

(图片来源网络,侵删)
主要功能
- 添加学生信息:从键盘输入学生的学号、姓名、年龄、成绩等信息,并添加到系统中。
- 显示所有学生信息:以表格形式清晰展示当前系统中的所有学生。
- 根据学号查询学生:输入学号,查找并显示该学生的详细信息。
- 根据学号修改学生信息:输入学号,找到学生后修改其除学号外的其他信息。
- 根据学号删除学生:输入学号,从系统中删除该学生的记录。
- 按成绩排序:将所有学生按成绩从高到低进行排序并显示。
- 保存数据到文件:将当前所有学生信息保存到
students.dat文件中。 - 从文件加载数据:从
students.dat文件中读取学生信息,加载到系统中。 - 退出系统:保存数据并安全退出程序。
代码实现
我们将代码分为三个主要部分:
student.h:头文件,包含结构体定义和函数声明。student.c:源文件,包含所有功能函数的具体实现。main.c:主程序文件,包含主菜单和程序流程控制。
头文件 student.h
// student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义学生结构体
typedef struct {
int id; // 学号
char name[50]; // 姓名
int age; // 年龄
float score; // 成绩
} Student;
// 函数声明
void addStudent(Student students[], int *count);
void displayAllStudents(const Student students[], int count);
void searchStudentById(const Student students[], int count);
void modifyStudent(Student students[], int count);
void deleteStudent(Student students[], int *count);
void sortStudentsByScore(Student students[], int count);
void saveToFile(const Student students[], int count);
void loadFromFile(Student students[], int *count);
void showMenu();
#endif // STUDENT_H
功能实现 student.c
// student.c
#include "student.h"
// 添加学生
void addStudent(Student students[], int *count) {
if (*count >= 100) { // 假设最多存储100个学生
printf("学生数量已达上限,无法添加!\n");
return;
}
Student s;
printf("请输入学号: ");
scanf("%d", &s.id);
// 检查学号是否已存在
for (int i = 0; i < *count; i++) {
if (students[i].id == s.id) {
printf("错误:学号 %d 已存在!\n", s.id);
return;
}
}
printf("请输入姓名: ");
scanf("%s", s.name);
printf("请输入年龄: ");
scanf("%d", &s.age);
printf("请输入成绩: ");
scanf("%f", &s.score);
students[(*count)++] = s;
printf("学生信息添加成功!\n");
}
// 显示所有学生
void displayAllStudents(const Student students[], int count) {
if (count == 0) {
printf("系统中没有学生信息,\n");
return;
}
printf("\n%-10s %-20s %-10s %-10s\n", "学号", "姓名", "年龄", "成绩");
printf("------------------------------------------------\n");
for (int i = 0; i < count; i++) {
printf("%-10d %-20s %-10d %-10.2f\n", students[i].id, students[i].name, students[i].age, students[i].score);
}
}
// 按学号查询
void searchStudentById(const Student students[], int count) {
if (count == 0) {
printf("系统中没有学生信息,\n");
return;
}
int id;
printf("请输入要查询的学号: ");
scanf("%d", &id);
for (int i = 0; i < count; i++) {
if (students[i].id == id) {
printf("\n查询到学生信息:\n");
printf("学号: %d\n", students[i].id);
printf("姓名: %s\n", students[i].name);
printf("年龄: %d\n", students[i].age);
printf("成绩: %.2f\n", students[i].score);
return; // 找到后立即返回
}
}
printf("未找到学号为 %d 的学生,\n", id);
}
// 修改学生信息
void modifyStudent(Student students[], int count) {
if (count == 0) {
printf("系统中没有学生信息,\n");
return;
}
int id;
printf("请输入要修改的学生学号: ");
scanf("%d", &id);
for (int i = 0; i < count; i++) {
if (students[i].id == id) {
printf("找到学生 %s,请输入新的信息:\n", students[i].name);
printf("请输入新姓名: ");
scanf("%s", students[i].name);
printf("请输入新年龄: ");
scanf("%d", &students[i].age);
printf("请输入新成绩: ");
scanf("%f", &students[i].score);
printf("学生信息修改成功!\n");
return;
}
}
printf("未找到学号为 %d 的学生,\n", id);
}
// 删除学生
void deleteStudent(Student students[], int *count) {
if (*count == 0) {
printf("系统中没有学生信息,\n");
return;
}
int id;
printf("请输入要删除的学生学号: ");
scanf("%d", &id);
for (int i = 0; i < *count; i++) {
if (students[i].id == id) {
// 将后面的所有学生前移一位,覆盖掉当前学生
for (int j = i; j < *count - 1; j++) {
students[j] = students[j + 1];
}
(*count)--; // 学生总数减一
printf("学号为 %d 的学生信息已删除,\n", id);
return;
}
}
printf("未找到学号为 %d 的学生,\n", id);
}
// 按成绩排序 (使用简单的冒泡排序)
void sortStudentsByScore(Student students[], int count) {
if (count == 0) {
printf("系统中没有学生信息,\n");
return;
}
for (int i = 0; i < count - 1; i++) {
for (int j = 0; j < count - 1 - i; j++) {
if (students[j].score < students[j + 1].score) {
// 交换结构体
Student temp = students[j];
students[j] = students[j + 1];
students[j + 1] = temp;
}
}
}
printf("学生信息已按成绩从高到低排序,\n");
displayAllStudents(students, count);
}
// 保存到文件
void saveToFile(const Student students[], int count) {
FILE *fp = fopen("students.dat", "wb"); // "wb" 表示二进制写入
if (fp == NULL) {
printf("无法打开文件进行保存!\n");
return;
}
// 先写入学生数量
fwrite(&count, sizeof(int), 1, fp);
// 再写入所有学生数据
fwrite(students, sizeof(Student), count, fp);
fclose(fp);
printf("数据已成功保存到 students.dat 文件,\n");
}
// 从文件加载
void loadFromFile(Student students[], int *count) {
FILE *fp = fopen("students.dat", "rb"); // "rb" 表示二进制读取
if (fp == NULL) {
printf("未找到数据文件,将创建一个新文件,\n");
return;
}
// 先读取学生数量
fread(count, sizeof(int), 1, fp);
// 再读取所有学生数据
fread(students, sizeof(Student), *count, fp);
fclose(fp);
printf("已成功从 students.dat 文件加载 %d 条学生数据,\n", *count);
}
主程序 main.c
// main.c
#include "student.h"
#define MAX_STUDENTS 100
int main() {
Student students[MAX_STUDENTS];
int studentCount = 0;
int choice;
// 程序启动时尝试从文件加载数据
loadFromFile(students, &studentCount);
while (1) {
showMenu();
printf("请输入您的选择 (0-8): ");
scanf("%d", &choice);
switch (choice) {
case 1:
addStudent(students, &studentCount);
break;
case 2:
displayAllStudents(students, studentCount);
break;
case 3:
searchStudentById(students, studentCount);
break;
case 4:
modifyStudent(students, studentCount);
break;
case 5:
deleteStudent(students, &studentCount);
break;
case 6:
sortStudentsByScore(students, studentCount);
break;
case 7:
saveToFile(students, studentCount);
break;
case 8:
// 退出前保存数据
saveToFile(students, studentCount);
printf("感谢使用,再见!\n");
exit(0); // 正常退出程序
default:
printf("无效的输入,请输入 1 到 8 之间的数字!\n");
break;
}
printf("\n按任意键继续...");
getchar(); // 清空输入缓冲区
getchar(); // 等待用户按回车
}
return 0;
}
// 显示菜单
void showMenu() {
system("cls || clear"); // 清屏 (Windows: cls, Linux/Mac: clear)
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("==============================================\n");
}
如何编译和运行
-
保存文件:将上面的三段代码分别保存为
student.h、student.c和main.c文件,并将它们放在同一个文件夹下。 -
编译:打开你的终端(Windows下的CMD或PowerShell,Linux/macOS的Terminal),进入文件所在的目录,然后使用GCC进行编译。
# main.c 是主程序,student.c 是其依赖的源文件 # -o student_system 指定输出的可执行文件名为 student_system gcc main.c student.c -o student_system
-
运行:
(图片来源网络,侵删)- 在Windows上:
student_system.exe
- 在Linux或macOS上:
./student_system
- 在Windows上:
程序启动后,会先尝试加载 students.dat 文件,然后显示一个文本菜单,你可以通过输入数字来选择相应的功能。
项目扩展建议
这个项目已经具备了基本功能,但如果你想进一步学习和改进,可以考虑以下几点:
- 动态内存分配:目前使用固定大小的数组
Student[MAX_STUDENTS],可以改用malloc、realloc和free来动态分配内存,这样系统可以处理任意数量的学生,直到内存耗尽。 - 更丰富的排序和查询:
- 增加按姓名、年龄排序的功能。
- 实现模糊查询(查询姓名中包含“张”的学生)。
- 更友好的用户界面:
- 使用更高级的库(如
ncurses)来创建更美观的基于终端的UI。 - 添加输入验证,防止用户输入非数字等错误数据。
- 使用更高级的库(如
- 数据加密:如果学生信息比较敏感,可以考虑在保存到文件前进行简单的加密,读取时再解密。
- 网络功能:将程序改造成一个客户端/服务器模型,多个用户可以同时访问和管理学生信息,这需要学习Socket编程。
- 图形用户界面:使用GTK+、Qt或EasyX等库为程序开发一个图形界面,使其更直观易用。
这个项目是学习C语言结构体、文件操作、函数和指针等核心概念的绝佳实践,希望这个详细的指南能帮助你顺利完成它!

(图片来源网络,侵删)
