C语言课程设计成绩管理系统如何实现?

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

C语言课程设计:学生成绩管理系统

项目概述

本项目旨在使用C语言开发一个基于命令行的学生成绩管理系统,该系统将实现对学生信息的增、删、改、查等基本操作,并能进行简单的成绩统计与分析,通过本课程设计,可以巩固和深化对C语言核心知识(如结构体、数组、指针、文件I/O等)的理解,并掌握模块化程序设计的基本思想。

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

功能需求分析

系统应具备以下核心功能:

  1. 录入学生信息:能够从键盘输入一个或多个学生的学号、姓名、多门课程的成绩(如C语言、高等数学、英语)。
  2. 显示所有学生信息:以表格形式清晰展示所有已录入学生的完整信息。
  3. 查询学生信息:可以通过学号或姓名查询特定学生的信息,并显示。
  4. 修改学生信息:根据学号找到学生,并可以修改其姓名或任意一门课程的成绩。
  5. 删除学生信息:根据学号找到学生,并将其信息从系统中移除。
  6. 统计与分析
    • 计算每个学生的总分和平均分。
    • 计算每门课程的平均分、最高分和最低分。
    • (可选)按总分或平均分对学生进行排序。
  7. 数据持久化:将所有学生信息保存到文件中,程序启动时能从文件中加载数据,退出时自动保存数据,确保信息不丢失。

系统设计

数据结构设计

为了存储学生信息,我们使用struct(结构体)来定义一个学生模型。

#define MAX_NAME_LEN 20
#define MAX_ID_LEN   15
#define COURSE_NUM   3 // 假设有3门课程
// 课程名称数组,方便显示
const char COURSE_NAMES[COURSE_NUM][20] = {"C语言", "高等数学", "英语"};
typedef struct {
    char id[MAX_ID_LEN];      // 学号
    char name[MAX_NAME_LEN];  // 姓名
    float scores[COURSE_NUM]; // 各科成绩
    float total;              // 总分
    float average;            // 平均分
} Student;

模块化设计

为了提高代码的可读性、可维护性和复用性,我们将不同功能的代码封装到不同的函数中,形成独立的模块。

模块名称 功能描述 主要函数
主菜单模块 显示系统主菜单,接收用户选择,调用相应功能函数 showMenu()
数据管理模块 负责文件的读写,实现数据的持久化 saveToFile(), loadFromFile()
学生信息录入模块 处理学生信息的输入 addStudent(), inputStudentInfo()
学生信息显示模块 格式化输出学生信息列表 displayAllStudents()
学生信息查询模块 按学号或姓名查询学生 queryStudent()
学生信息修改模块 根据学号定位并修改学生信息 modifyStudent()
学生信息删除模块 根据学号定位并删除学生信息 deleteStudent()
成绩统计模块 计算并显示各类统计数据 calculateStatistics(), sortStudents()

文件设计

使用二进制文件(.dat)来存储学生数据,相比文本文件,读写速度更快,且格式不易出错。

c语言课程设计成绩管理系统
(图片来源网络,侵删)
  • 文件名students.dat
  • :一个Student结构体数组。

核心代码实现

下面是完整的项目代码,包含了详细的注释。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> // 用于 getch(),Windows平台下按任意键继续
// --- 常量定义 ---
#define MAX_STUDENTS 100 // 最大学生数量
#define MAX_NAME_LEN 20
#define MAX_ID_LEN   15
#define COURSE_NUM   3
#define FILENAME "students.dat"
// 课程名称
const char COURSE_NAMES[COURSE_NUM][20] = {"C语言", "高等数学", "英语"};
// --- 学生结构体 ---
typedef struct {
    char id[MAX_ID_LEN];
    char name[MAX_NAME_LEN];
    float scores[COURSE_NUM];
    float total;
    float average;
} Student;
// --- 全局变量 ---
Student students[MAX_STUDENTS]; // 学生数组
int student_count = 0;          // 当前学生数量
// --- 函数声明 ---
void showMenu();
void loadFromFile();
void saveToFile();
void addStudent();
void displayAllStudents();
void queryStudent();
void modifyStudent();
void deleteStudent();
void calculateStatistics();
void sortStudents();
void inputStudentInfo(Student *s);
void clearInputBuffer();
// --- 主函数 ---
int main() {
    loadFromFile(); // 程序启动时加载数据
    int choice;
    do {
        showMenu();
        printf("请输入您的选择: ");
        scanf("%d", &choice);
        clearInputBuffer(); // 清除输入缓冲区中的换行符
        switch (choice) {
            case 1: addStudent(); break;
            case 2: displayAllStudents(); break;
            case 3: queryStudent(); break;
            case 4: modifyStudent(); break;
            case 5: deleteStudent(); break;
            case 6: calculateStatistics(); break;
            case 7: sortStudents(); break;
            case 0: 
                saveToFile();
                printf("感谢使用,数据已保存,再见!\n");
                break;
            default:
                printf("无效的选择,请重新输入!\n");
                break;
        }
        if (choice != 0) {
            printf("\n按任意键返回主菜单...");
            getch(); // 等待用户按键
        }
    } while (choice != 0);
    return 0;
}
// --- 显示主菜单 ---
void showMenu() {
    system("cls"); // Windows下清屏,Linux/macOS用 system("clear");
    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");
}
// --- 从文件加载数据 ---
void loadFromFile() {
    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("成功从 %s 加载了 %d 条学生记录,\n", FILENAME, student_count);
}
// --- 保存数据到文件 ---
void saveToFile() {
    FILE *fp = fopen(FILENAME, "wb");
    if (fp == NULL) {
        printf("错误:无法打开文件 %s 进行写入!\n", FILENAME);
        return;
    }
    // 写入学生数量
    fwrite(&student_count, sizeof(int), 1, fp);
    // 写入学生数组
    fwrite(students, sizeof(Student), student_count, fp);
    fclose(fp);
}
// --- 录入学生信息 ---
void addStudent() {
    if (student_count >= MAX_STUDENTS) {
        printf("学生数量已达上限,无法继续添加!\n");
        return;
    }
    printf("\n--- 录入学生信息 ---\n");
    inputStudentInfo(&students[student_count]);
    student_count++;
    printf("学生信息添加成功!\n");
}
// --- 输入单个学生信息 ---
void inputStudentInfo(Student *s) {
    printf("请输入学号: ");
    scanf("%s", s->id);
    clearInputBuffer();
    printf("请输入姓名: ");
    scanf("%s", s->name);
    clearInputBuffer();
    s->total = 0;
    for (int i = 0; i < COURSE_NUM; i++) {
        printf("请输入%s成绩: ", COURSE_NAMES[i]);
        scanf("%f", &s->scores[i]);
        s->total += s->scores[i];
    }
    s->average = s->total / COURSE_NUM;
}
// --- 显示所有学生信息 ---
void displayAllStudents() {
    if (student_count == 0) {
        printf("\n当前没有任何学生信息!\n");
        return;
    }
    printf("\n--- 所有学生信息 ---\n");
    printf("---------------------------------------------------------------------------------\n");
    printf("学号\t\t姓名\t\t");
    for (int i = 0; i < COURSE_NUM; i++) {
        printf("%s\t\t", COURSE_NAMES[i]);
    }
    printf("总分\t\t平均分\n");
    printf("---------------------------------------------------------------------------------\n");
    for (int i = 0; i < student_count; i++) {
        printf("%s\t\t%s\t\t", students[i].id, students[i].name);
        for (int j = 0; j < COURSE_NUM; j++) {
            printf("%.2f\t\t", students[i].scores[j]);
        }
        printf("%.2f\t\t%.2f\n", students[i].total, students[i].average);
    }
    printf("---------------------------------------------------------------------------------\n");
    printf("共 %d 名学生\n", student_count);
}
// --- 查询学生信息 ---
void queryStudent() {
    if (student_count == 0) {
        printf("\n当前没有任何学生信息!\n");
        return;
    }
    int choice;
    char keyword[MAX_ID_LEN];
    printf("\n--- 查询学生信息 ---\n");
    printf("1. 按学号查询\n");
    printf("2. 按姓名查询\n");
    printf("请选择查询方式: ");
    scanf("%d", &choice);
    clearInputBuffer();
    printf("请输入查询关键词: ");
    scanf("%s", keyword);
    clearInputBuffer();
    int found = 0;
    for (int i = 0; i < student_count; i++) {
        if ((choice == 1 && strcmp(students[i].id, keyword) == 0) ||
            (choice == 2 && strcmp(students[i].name, keyword) == 0)) {
            printf("\n查询结果:\n");
            printf("学号: %s, 姓名: %s\n", students[i].id, students[i].name);
            printf("成绩: ");
            for (int j = 0; j < COURSE_NUM; j++) {
                printf("%s: %.2f  ", COURSE_NAMES[j], students[i].scores[j]);
            }
            printf("\n总分: %.2f, 平均分: %.2f\n", students[i].total, students[i].average);
            found = 1;
            break; // 如果学号唯一,找到后即可退出
        }
    }
    if (!found) {
        printf("未找到学号或姓名为 '%s' 的学生,\n", keyword);
    }
}
// --- 修改学生信息 ---
void modifyStudent() {
    if (student_count == 0) {
        printf("\n当前没有任何学生信息!\n");
        return;
    }
    char id[MAX_ID_LEN];
    printf("\n--- 修改学生信息 ---\n");
    printf("请输入要修改的学生学号: ");
    scanf("%s", id);
    clearInputBuffer();
    for (int i = 0; i < student_count; i++) {
        if (strcmp(students[i].id, id) == 0) {
            printf("已找到学生: %s (%s)\n", students[i].name, students[i].id);
            printf("请输入新的信息 (直接回车则保持原样):\n");
            char temp_input[50];
            printf("姓名 (%s): ", students[i].name);
            gets(temp_input);
            if (strlen(temp_input) > 0) strcpy(students[i].name, temp_input);
            students[i].total = 0;
            for (int j = 0; j < COURSE_NUM; j++) {
                printf("%s成绩 (%.2f): ", COURSE_NAMES[j], students[i].scores[j]);
                gets(temp_input);
                if (strlen(temp_input) > 0) {
                    students[i].scores[j] = atof(temp_input);
                }
                students[i].total += students[i].scores[j];
            }
            students[i].average = students[i].total / COURSE_NUM;
            printf("学生信息修改成功!\n");
            return;
        }
    }
    printf("未找到学号为 '%s' 的学生,\n", id);
}
// --- 删除学生信息 ---
void deleteStudent() {
    if (student_count == 0) {
        printf("\n当前没有任何学生信息!\n");
        return;
    }
    char id[MAX_ID_LEN];
    printf("\n--- 删除学生信息 ---\n");
    printf("请输入要删除的学生学号: ");
    scanf("%s", id);
    clearInputBuffer();
    for (int i = 0; i < student_count; i++) {
        if (strcmp(students[i].id, id) == 0) {
            // 将后面的所有学生前移一位,覆盖当前学生
            for (int j = i; j < student_count - 1; j++) {
                students[j] = students[j + 1];
            }
            student_count--;
            printf("学号为 '%s' 的学生信息已删除,\n", id);
            return;
        }
    }
    printf("未找到学号为 '%s' 的学生,\n", id);
}
// --- 成绩统计与分析 ---
void calculateStatistics() {
    if (student_count == 0) {
        printf("\n当前没有任何学生信息!\n");
        return;
    }
    printf("\n--- 成绩统计与分析 ---\n");
    float course_totals[COURSE_NUM] = {0};
    float course_max[COURSE_NUM];
    float course_min[COURSE_NUM];
    // 初始化最高分和最低分
    for (int i = 0; i < COURSE_NUM; i++) {
        course_max[i] = students[0].scores[i];
        course_min[i] = students[0].scores[i];
    }
    for (int i = 0; i < student_count; i++) {
        for (int j = 0; j < COURSE_NUM; j++) {
            course_totals[j] += students[i].scores[j];
            if (students[i].scores[j] > course_max[j]) {
                course_max[j] = students[i].scores[j];
            }
            if (students[i].scores[j] < course_min[j]) {
                course_min[j] = students[i].scores[j];
            }
        }
    }
    printf("\n各科成绩统计:\n");
    printf("-------------------------------------------------\n");
    printf("课程\t\t平均分\t\t最高分\t\t最低分\n");
    printf("-------------------------------------------------\n");
    for (int i = 0; i < COURSE_NUM; i++) {
        float avg = course_totals[i] / student_count;
        printf("%s\t\t%.2f\t\t%.2f\t\t%.2f\n", COURSE_NAMES[i], avg, course_max[i], course_min[i]);
    }
    printf("-------------------------------------------------\n");
}
// --- 学生信息排序 ---
void sortStudents() {
    if (student_count == 0) {
        printf("\n当前没有任何学生信息!\n");
        return;
    }
    int choice;
    printf("\n--- 学生信息排序 ---\n");
    printf("1. 按总分降序排序\n");
    printf("2. 按平均分降序排序\n");
    printf("请选择排序方式: ");
    scanf("%d", &choice);
    clearInputBuffer();
    // 使用简单的冒泡排序
    for (int i = 0; i < student_count - 1; i++) {
        for (int j = 0; j < student_count - 1 - i; j++) {
            float compare_value1 = (choice == 1) ? students[j].total : students[j].average;
            float compare_value2 = (choice == 1) ? students[j+1].total : students[j+1].average;
            if (compare_value1 < compare_value2) {
                Student temp = students[j];
                students[j] = students[j + 1];
                students[j + 1] = temp;
            }
        }
    }
    printf("排序完成!\n");
    displayAllStudents(); // 排序后立即显示
}
// --- 清除输入缓冲区 ---
void clearInputBuffer() {
    while (getchar() != '\n');
}

编译与运行指南

  1. 环境:支持C语言的编译器,如GCC (Linux/macOS) 或 MinGW/Visual Studio (Windows)。
  2. 保存代码:将以上代码保存为 grade_management.c 文件。
  3. 编译
    • GCC (Linux/macOS/Windows with MinGW):
      gcc grade_management.c -o grade_management
    • Visual Studio:
      1. 创建一个新的 "C++ 空项目"(虽然代码是C,但VS兼容性很好)。
      2. grade_management.c 添加到项目中。
      3. 选择 "生成" -> "生成解决方案"。
  4. 运行
    • 命令行:
      ./grade_management  # Linux/macOS
      grade_management.exe # Windows
    • Visual Studio: 按 F5 或点击 "本地Windows调试器" 运行。

功能扩展建议

如果觉得基本功能已经掌握,可以尝试以下扩展来提升项目难度和完整性:

  1. 密码登录系统:增加一个简单的用户名和密码验证功能。
  2. 更复杂的查询:支持按分数段查询(如查询C语言成绩在80-90分之间的所有学生)。
  3. 动态内存分配:使用 mallocrealloc 动态分配内存,替代固定大小的 students 数组,实现学生数量无上限。
  4. 图形用户界面:使用图形库(如EasyX, GTK, Qt)将命令行界面改为图形界面,提升用户体验。
  5. 多文件结构:将代码拆分到 .h (头文件) 和 .c (源文件) 中,student.h, main.c, file_io.c 等,这是大型项目的标准做法。
  6. 数据备份与恢复:增加数据备份功能和从备份文件恢复数据的功能。

这个项目涵盖了C语言的大部分核心知识点,是一个非常好的课程设计选择,祝你项目顺利!

c语言课程设计成绩管理系统
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
织梦手机网页搜索设置怎么弄?
« 上一篇 03-03
C语言学生管理系统如何实现核心功能?
下一篇 » 03-03
取消
微信二维码
支付宝二维码

目录[+]