C语言学生成绩管理系统如何实现核心功能?

99ANYc3cd6
预计阅读时长 51 分钟
位置: 首页 C语言 正文

这个系统将使用结构体来存储学生信息,使用文件来实现数据的持久化存储(即程序关闭后数据不会丢失),整个程序采用模块化设计,将不同功能封装成独立的函数,使代码结构清晰,易于维护和扩展。

c语言程序设计学生成绩管理系统
(图片来源网络,侵删)

功能需求分析

一个功能完善的学生成绩管理系统应具备以下功能:

  1. 录入学生信息:可以添加新的学生记录,包括学号、姓名、各科成绩。
  2. 显示所有学生信息:以表格形式清晰地展示所有学生的数据。
  3. 查询学生信息
    • 按学号查询
    • 按姓名查询
  4. 修改学生信息:根据学号找到学生并修改其信息。
  5. 删除学生信息:根据学号删除指定的学生记录。
  6. 统计功能
    • 计算每个学生的总分和平均分。
    • 计算每门课程的平均分。
    • 找出总分最高和最低的学生。
  7. 排序功能:可以按总分或单科成绩对学生进行排序(升序/降序)。
  8. 数据保存与加载
    • 将所有学生信息保存到文件中(如 students.dat)。
    • 程序启动时自动从文件中加载已有数据。
  9. 退出系统:保存数据并安全退出。

数据结构设计

为了存储学生信息,我们定义一个结构体 Student

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> // 用于 getch(),在Windows下按任意键继续
// 定义学生结构体
#define MAX_NAME_LEN 50
#define MAX_ID_LEN 20
#define COURSE_NUM 3 // 假设有3门课程
typedef struct {
    char id[MAX_ID_LEN];      // 学号
    char name[MAX_NAME_LEN];  // 姓名
    float scores[COURSE_NUM]; // 各科成绩
    float total;              // 总分
    float average;            // 平均分
} Student;

核心代码实现

下面是完整的C语言源代码,我将它分模块进行解释。

1 头文件和全局变量

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> // 用于 getch(),在Windows下按任意键继续
// --- 数据结构定义 ---
#define MAX_NAME_LEN 50
#define MAX_ID_LEN 20
#define COURSE_NUM 3 // 假设有3门课程:数学、英语、C语言
#define FILENAME "students.dat"
typedef struct {
    char id[MAX_ID_LEN];
    char name[MAX_NAME_LEN];
    float scores[COURSE_NUM];
    float total;
    float average;
} Student;
// 全局变量:学生数组和学生数量
Student students[1000]; // 假设最多存储1000名学生
int student_count = 0;

2 功能函数声明

// 函数声明
void show_menu();
void load_data();
void save_data();
void add_student();
void display_all();
void search_student();
void modify_student();
void delete_student();
void calculate_statistics();
void sort_students();
void calculate_student_totals();

3 主函数

int main() {
    load_data(); // 程序启动时加载数据
    int choice;
    while (1) {
        show_menu();
        printf("请输入您的选择: ");
        scanf("%d", &choice);
        switch (choice) {
            case 1: add_student(); break;
            case 2: display_all(); break;
            case 3: search_student(); break;
            case 4: modify_student(); break;
            case 5: delete_student(); break;
            case 6: calculate_statistics(); break;
            case 7: sort_students(); break;
            case 0:
                save_data();
                printf("感谢使用,数据已保存,再见!\n");
                exit(0);
            default:
                printf("无效的输入,请重新选择!\n");
                system("pause"); // 按任意键继续
        }
        system("cls"); // 清屏,Windows系统有效
    }
    return 0;
}

4 菜单显示

void show_menu() {
    printf("\n\n\n");
    printf("========================================\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("=  0. 退出系统                        =\n");
    printf("========================================\n");
}

5 文件操作 (数据持久化)

// 从文件加载数据
void load_data() {
    FILE *fp = fopen(FILENAME, "rb");
    if (fp == NULL) {
        // 文件不存在是正常情况(第一次运行)
        return;
    }
    // 读取学生数量
    fread(&student_count, sizeof(int), 1, fp);
    // 读取所有学生数据
    fread(students, sizeof(Student), student_count, fp);
    fclose(fp);
    printf("成功从文件加载 %d 条学生记录,\n", student_count);
    system("pause");
}
// 保存数据到文件
void save_data() {
    FILE *fp = fopen(FILENAME, "wb");
    if (fp == NULL) {
        printf("错误:无法打开文件进行保存!\n");
        return;
    }
    // 先写入学生数量
    fwrite(&student_count, sizeof(int), 1, fp);
    // 再写入所有学生数据
    fwrite(students, sizeof(Student), student_count, fp);
    fclose(fp);
}

6 核心功能实现

// 计算单个学生的总分和平均分
void calculate_student_totals(Student *s) {
    s->total = 0;
    for (int i = 0; i < COURSE_NUM; i++) {
        s->total += s->scores[i];
    }
    s->average = s->total / COURSE_NUM;
}
// 1. 录入学生信息
void add_student() {
    if (student_count >= 1000) {
        printf("学生数量已达上限,无法添加!\n");
        system("pause");
        return;
    }
    Student s;
    printf("请输入学号: ");
    scanf("%s", s.id);
    printf("请输入姓名: ");
    scanf("%s", s.name);
    printf("请输入数学成绩: ");
    scanf("%f", &s.scores[0]);
    printf("请输入英语成绩: ");
    scanf("%f", &s.scores[1]);
    printf("请输入C语言成绩: ");
    scanf("%f", &s.scores[2]);
    calculate_student_totals(&s);
    students[student_count++] = s;
    printf("学生信息添加成功!\n");
    system("pause");
}
// 2. 显示所有学生信息
void display_all() {
    if (student_count == 0) {
        printf("系统中没有学生信息!\n");
        system("pause");
        return;
    }
    printf("\n%-15s %-20s %-10s %-10s %-10s %-10s %-10s\n", 
           "学号", "姓名", "数学", "英语", "C语言", "总分", "平均分");
    printf("-----------------------------------------------------------------\n");
    for (int i = 0; i < student_count; i++) {
        printf("%-15s %-20s ", students[i].id, students[i].name);
        for (int j = 0; j < COURSE_NUM; j++) {
            printf("%-10.1f ", students[i].scores[j]);
        }
        printf("%-10.1f %-10.1f\n", students[i].total, students[i].average);
    }
    system("pause");
}
// 3. 查询学生信息 (按学号/姓名)
void search_student() {
    if (student_count == 0) {
        printf("系统中没有学生信息!\n");
        system("pause");
        return;
    }
    int choice;
    printf("1. 按学号查询\n2. 按姓名查询\n请选择查询方式: ");
    scanf("%d", &choice);
    char keyword[MAX_ID_LEN];
    int found = 0;
    if (choice == 1) {
        printf("请输入要查询的学号: ");
        scanf("%s", keyword);
        for (int i = 0; i < student_count; i++) {
            if (strcmp(students[i].id, keyword) == 0) {
                printf("\n%-15s %-20s %-10s %-10s %-10s %-10s %-10s\n", 
                       "学号", "姓名", "数学", "英语", "C语言", "总分", "平均分");
                printf("-----------------------------------------------------------------\n");
                printf("%-15s %-20s ", students[i].id, students[i].name);
                for (int j = 0; j < COURSE_NUM; j++) {
                    printf("%-10.1f ", students[i].scores[j]);
                }
                printf("%-10.1f %-10.1f\n", students[i].total, students[i].average);
                found = 1;
                break;
            }
        }
    } else if (choice == 2) {
        printf("请输入要查询的姓名: ");
        scanf("%s", keyword);
        for (int i = 0; i < student_count; i++) {
            if (strcmp(students[i].name, keyword) == 0) {
                printf("\n%-15s %-20s %-10s %-10s %-10s %-10s %-10s\n", 
                       "学号", "姓名", "数学", "英语", "C语言", "总分", "平均分");
                printf("-----------------------------------------------------------------\n");
                printf("%-15s %-20s ", students[i].id, students[i].name);
                for (int j = 0; j < COURSE_NUM; j++) {
                    printf("%-10.1f ", students[i].scores[j]);
                }
                printf("%-10.1f %-10.1f\n", students[i].total, students[i].average);
                found = 1;
            }
        }
    } else {
        printf("无效的选择!\n");
    }
    if (!found) {
        printf("未找到匹配的学生信息!\n");
    }
    system("pause");
}
// 4. 修改学生信息
void modify_student() {
    if (student_count == 0) {
        printf("系统中没有学生信息!\n");
        system("pause");
        return;
    }
    char id[MAX_ID_LEN];
    printf("请输入要修改的学生学号: ");
    scanf("%s", id);
    for (int i = 0; i < student_count; i++) {
        if (strcmp(students[i].id, id) == 0) {
            printf("找到学生 %s,请输入新的信息:\n", students[i].name);
            printf("请输入新的数学成绩 (原: %.1f): ", students[i].scores[0]);
            scanf("%f", &students[i].scores[0]);
            printf("请输入新的英语成绩 (原: %.1f): ", students[i].scores[1]);
            scanf("%f", &students[i].scores[1]);
            printf("请输入新的C语言成绩 (原: %.1f): ", students[i].scores[2]);
            scanf("%f", &students[i].scores[2]);
            calculate_student_totals(&students[i]);
            printf("学生信息修改成功!\n");
            system("pause");
            return;
        }
    }
    printf("未找到学号为 %s 的学生!\n", id);
    system("pause");
}
// 5. 删除学生信息
void delete_student() {
    if (student_count == 0) {
        printf("系统中没有学生信息!\n");
        system("pause");
        return;
    }
    char id[MAX_ID_LEN];
    printf("请输入要删除的学生学号: ");
    scanf("%s", id);
    int found_index = -1;
    for (int i = 0; i < student_count; i++) {
        if (strcmp(students[i].id, id) == 0) {
            found_index = i;
            break;
        }
    }
    if (found_index != -1) {
        // 将后面的所有学生前移一位,覆盖掉要删除的学生
        for (int i = found_index; i < student_count - 1; i++) {
            students[i] = students[i + 1];
        }
        student_count--;
        printf("学号为 %s 的学生信息已删除!\n", id);
    } else {
        printf("未找到学号为 %s 的学生!\n", id);
    }
    system("pause");
}
// 6. 统计与分析
void calculate_statistics() {
    if (student_count == 0) {
        printf("系统中没有学生信息!\n");
        system("pause");
        return;
    }
    float course_sums[COURSE_NUM] = {0};
    float max_total = students[0].total;
    float min_total = students[0].total;
    int max_index = 0, min_index = 0;
    for (int i = 0; i < student_count; i++) {
        for (int j = 0; j < COURSE_NUM; j++) {
            course_sums[j] += students[i].scores[j];
        }
        if (students[i].total > max_total) {
            max_total = students[i].total;
            max_index = i;
        }
        if (students[i].total < min_total) {
            min_total = students[i].total;
            min_index = i;
        }
    }
    printf("\n--- 统计分析结果 ---\n");
    printf("1. 各科平均分:\n");
    printf("   数学: %.2f\n", course_sums[0] / student_count);
    printf("   英语: %.2f\n", course_sums[1] / student_count);
    printf("   C语言: %.2f\n", course_sums[2] / student_count);
    printf("\n2. 总分最高分学生:\n");
    printf("   姓名: %s, 学号: %s, 总分: %.1f\n", students[max_index].name, students[max_index].id, max_total);
    printf("\n3. 总分最低分学生:\n");
    printf("   姓名: %s, 学号: %s, 总分: %.1f\n", students[min_index].name, students[min_index].id, min_total);
    system("pause");
}
// 7. 成绩排序
void sort_students() {
    if (student_count == 0) {
        printf("系统中没有学生信息!\n");
        system("pause");
        return;
    }
    int choice, order;
    printf("1. 按总分排序\n2. 按数学成绩排序\n请选择排序依据: ");
    scanf("%d", &choice);
    printf("1. 升序\n2. 降序\n请选择排序方式: ");
    scanf("%d", &order);
    // 使用简单的冒泡排序
    for (int i = 0; i < student_count - 1; i++) {
        for (int j = 0; j < student_count - 1 - i; j++) {
            float key1, key2;
            if (choice == 1) { // 按总分
                key1 = students[j].total;
                key2 = students[j + 1].total;
            } else { // 按数学成绩
                key1 = students[j].scores[0];
                key2 = students[j + 1].scores[0];
            }
            if ((order == 1 && key1 > key2) || (order == 2 && key1 < key2)) {
                // 交换
                Student temp = students[j];
                students[j] = students[j + 1];
                students[j + 1] = temp;
            }
        }
    }
    printf("排序完成!\n");
    display_all(); // 排序后直接显示
}

如何编译和运行

  1. 保存代码:将以上所有代码块合并到一个文件中,student_management.c
  2. 编译:如果你使用的是GCC编译器(在Linux或MinGW/Cygwin中),可以在命令行中运行:
    gcc student_management.c -o student_management.exe

    (在Linux上,输出文件名可以是 student_management,不需要 .exe)

    c语言程序设计学生成绩管理系统
    (图片来源网络,侵删)
  3. 运行
    ./student_management.exe
  4. 首次运行:程序会提示“成功从文件加载 0 条学生记录”,因为数据文件 students.dat 还不存在,这是正常的。
  5. 后续运行:当你添加数据并退出后,再次运行程序,它会自动加载上次保存的数据。

可能的改进和扩展

这个版本已经是一个功能完整的系统,但如果你想进一步挑战,可以考虑以下扩展:

  1. 更健壮的输入验证:检查学号是否重复、成绩是否在0-100之间等。
  2. 动态内存分配:使用 mallocrealloc 来动态分配学生数组内存,而不是使用固定大小的全局数组,这样可以处理任意数量的学生。
  3. 更复杂的排序:使用 qsort 函数(C标准库中的快速排序)来代替冒泡排序,效率更高。
  4. 图形用户界面:使用像 EasyX (Windows) 或 GTK / Qt (跨平台) 这样的库来创建图形界面,使操作更直观。
  5. 多文件组织:将代码拆分为多个文件(如 main.c, functions.c, functions.h),这是大型项目的标准做法。
  6. 密码登录:增加一个简单的登录功能,保护系统数据。
  7. 支持更多课程:通过从文件读取课程信息或让用户动态添加课程名,来增加灵活性。

希望这个详细的实现能帮助你完成你的C语言课程设计!祝你学习顺利!

c语言程序设计学生成绩管理系统
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
谭浩强C语言第四版答案是否完整准确?
« 上一篇 01-12
织梦5.7超链接失效怎么办?
下一篇 » 01-12

相关文章

取消
微信二维码
支付宝二维码

目录[+]