c语言课程设计学生选课系统设计

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

C语言课程设计:学生选课系统

项目概述

项目名称 学生选课管理系统

c语言课程设计学生选课系统设计
(图片来源网络,侵删)

项目目标 设计并实现一个基于命令行的学生选课系统,该系统应能够模拟学生选课的全过程,包括学生信息管理、课程信息管理、选课、退课、查询等功能,通过本项目,旨在加深对C语言核心概念(如结构体、数组、指针、文件I/O)的理解和应用,并锻炼基本的程序设计、模块化和调试能力。

开发环境

  • 操作系统: Windows / Linux / macOS
  • 编程语言: C语言 (C99标准)
  • 编译器: GCC (MinGW on Windows), Clang, MSVC
  • 开发工具: Visual Studio Code, Dev-C++, Sublime Text, Vim 等

功能设计

系统应至少包含以下核心功能:

  1. 主菜单: 提供所有功能的入口,用户可以通过数字选择操作。
  2. 学生信息管理:
    • 添加学生: 手动输入学生信息(学号、姓名、密码),并保存。
    • 显示所有学生: 列出系统中所有学生的基本信息。
    • 根据学号查找学生: 快速定位并显示某个学生的详细信息。
  3. 课程信息管理:
    • 添加课程: 手动输入课程信息(课程ID、课程名、授课教师、容量、已选人数)。
    • 显示所有课程: 列出系统中所有课程的基本信息。
    • 根据课程ID查找课程: 快速定位并显示某个课程的详细信息。
  4. 选课功能:
    • 学生输入自己的学号和密码进行登录。
    • 登录成功后,显示该学生已选课程和所有可选课程。
    • 学生可以输入课程ID进行选课。
    • 选课逻辑校验:
      • 检查课程是否存在。
      • 检查学生是否已经选过该课程(防止重复选课)。
      • 检查课程是否已满(已选人数 >= 容量)。
      • 所有校验通过后,更新学生选课列表和课程的已选人数。
  5. 退课功能:
    • 学生登录后,可以查看自己已选的课程。
    • 输入要退的课程ID。
    • 退课逻辑校验:

      检查学生是否已选该课程。

      c语言课程设计学生选课系统设计
      (图片来源网络,侵删)
    • 校验通过后,从学生选课列表中移除该课程,并减少课程的已选人数。
  6. 查询功能:
    • 学生查询: 学生登录后,可以查看自己的个人信息和已选课程列表。
    • 课程查询: (非登录状态)根据课程ID查询课程详情,包括选课学生名单。
  7. 数据持久化:
    • 系统启动时,从文件(如 students.dat, courses.dat)中加载学生和课程数据。
    • 每当学生或课程信息发生变更(增、删、改)时,立即将最新数据写回文件,确保数据不丢失。

数据结构设计

为了高效地管理数据,我们需要定义几个核心的结构体。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// --- 1. 学生结构体 ---
#define MAX_COURSES_PER_STUDENT 10 // 每个学生最多选多少门课
#define MAX_NAME_LEN 50
#define MAX_ID_LEN 20
typedef struct {
    char id[MAX_ID_LEN];       // 学号
    char name[MAX_NAME_LEN];   // 姓名
    char password[MAX_ID_LEN]; // 密码
    int selected_courses[MAX_COURSES_PER_STUDENT]; // 存储已选课程的ID数组
    int course_count;          // 已选课程数量
} Student;
// --- 2. 课程结构体 ---
#define MAX_STUDENTS_PER_COURSE 100 // 每门课最多多少人选
#define MAX_TEACHER_LEN 50
typedef struct {
    char id[MAX_ID_LEN];         // 课程ID
    char name[MAX_NAME_LEN];     // 课程名
    char teacher[MAX_TEACHER_LEN]; // 授课教师
    int capacity;                // 课程容量
    int enrolled_count;          // 已选人数
    int enrolled_students[MAX_STUDENTS_PER_COURSE]; // 存储已选学生的学号数组
} Course;
// --- 3. 全局数据管理 ---
// 使用数组来存储学生和课程,简单直观,适合课程设计规模
Student students[1000]; // 假设最多1000名学生
Course courses[100];    // 假设最多100门课程
int student_count = 0;
int course_count = 0;

模块划分与函数设计

将系统功能分解为独立的函数,便于管理和维护。

模块 函数名 功能描述
主菜单 main_menu() 显示主菜单,根据用户输入调用相应功能函数
文件操作 load_data() 启动时从文件加载数据到内存
save_data() 退出或数据变更时,将内存数据保存到文件
学生管理 add_student() 添加新学生
display_all_students() 显示所有学生信息
find_student() 按学号查找学生
课程管理 add_course() 添加新课程
display_all_courses() 显示所有课程信息
find_course() 按课程ID查找课程
选课/退课 student_login() 学生登录验证
select_course() 学生选课核心逻辑
drop_course() 学生退课核心逻辑
查询功能 query_student_info() 学生查询个人信息和已选课
query_course_detail() 查询课程详细信息(含学生名单)

核心代码示例

这里展示几个关键函数的实现思路。

main() 函数 - 程序入口

c语言课程设计学生选课系统设计
(图片来源网络,侵删)
int main() {
    load_data(); // 启动时加载数据
    int choice;
    while (1) {
        main_menu();
        printf("请输入您的选择: ");
        scanf("%d", &choice);
        switch (choice) {
            case 1: // 学生管理
                // ... 调用学生管理相关函数 ...
                break;
            case 2: // 课程管理
                // ... 调用课程管理相关函数 ...
                break;
            case 3: // 学生登录选课
                student_login();
                break;
            case 4: // 退出系统
                save_data(); // 退出前保存数据
                printf("感谢使用,再见!\n");
                exit(0);
            default:
                printf("无效的输入,请重新选择!\n");
        }
    }
    return 0;
}

load_data()save_data() 函数 - 文件I/O

void save_data() {
    // 保存学生数据
    FILE *student_file = fopen("students.dat", "wb");
    if (student_file) {
        fwrite(&student_count, sizeof(int), 1, student_file);
        fwrite(students, sizeof(Student), student_count, student_file);
        fclose(student_file);
    }
    // 保存课程数据
    FILE *course_file = fopen("courses.dat", "wb");
    if (course_file) {
        fwrite(&course_count, sizeof(int), 1, course_file);
        fwrite(courses, sizeof(Course), course_count, course_file);
        fclose(course_file);
    }
}
void load_data() {
    // 加载学生数据
    FILE *student_file = fopen("students.dat", "rb");
    if (student_file) {
        fread(&student_count, sizeof(int), 1, student_file);
        fread(students, sizeof(Student), student_count, student_file);
        fclose(student_file);
    }
    // 加载课程数据
    FILE *course_file = fopen("courses.dat", "rb");
    if (course_file) {
        fread(&course_count, sizeof(int), 1, course_file);
        fread(courses, sizeof(Course), course_count, course_file);
        fclose(course_file);
    }
}

select_course() 函数 - 核心业务逻辑

void select_course() {
    char student_id[MAX_ID_LEN], password[MAX_ID_LEN];
    printf("请输入学号: ");
    scanf("%s", student_id);
    printf("请输入密码: ");
    scanf("%s", password);
    // 1. 查找并验证学生
    int student_idx = -1;
    for (int i = 0; i < student_count; i++) {
        if (strcmp(students[i].id, student_id) == 0 && strcmp(students[i].password, password) == 0) {
            student_idx = i;
            break;
        }
    }
    if (student_idx == -1) {
        printf("学号或密码错误!\n");
        return;
    }
    Student *s = &students[student_idx];
    // 2. 显示可选课程
    printf("\n--- 可选课程列表 ---\n");
    display_all_courses();
    // 3. 输入要选的课程ID
    char course_id[MAX_ID_LEN];
    printf("\n请输入要选的课程ID: ");
    scanf("%s", course_id);
    // 4. 查找课程
    int course_idx = -1;
    for (int i = 0; i < course_count; i++) {
        if (strcmp(courses[i].id, course_id) == 0) {
            course_idx = i;
            break;
        }
    }
    if (course_idx == -1) {
        printf("课程不存在!\n");
        return;
    }
    Course *c = &courses[course_idx];
    // 5. 校验选课条件
    if (c->enrolled_count >= c->capacity) {
        printf("选课失败:课程 %s 已满!\n", c->name);
        return;
    }
    for (int i = 0; i < s->course_count; i++) {
        if (s->selected_courses[i] == course_idx) { // 注意:这里存的是课程在数组中的索引
            printf("选课失败:您已经选过这门课了!\n");
            return;
        }
    }
    // 6. 执行选课操作
    s->selected_courses[s->course_count] = course_idx;
    s->course_count++;
    c->enrolled_students[c->enrolled_count] = student_idx; // 存储学生在数组中的索引
    c->enrolled_count++;
    printf("选课成功!您已成功选入课程 %s,\n", c->name);
}

系统扩展建议(进阶)

如果觉得基础功能已经完成,可以尝试以下扩展来提升项目质量:

  1. 使用链表代替数组:

    • 优点: 动态分配内存,可以处理任意数量的学生和课程,避免数组大小限制。
    • 实现: 定义 StudentNodeCourseNode 结构体,包含指向下一个节点的指针。
  2. 优化数据结构:

    • 使用哈希表: 对于按ID查找频繁的操作(如登录、查课程),使用哈希表可以将查找时间复杂度从 O(n) 降到接近 O(1),极大提升性能。
  3. 增加用户角色:

    • 管理员角色: 拥有所有权限,包括删除学生/课程、修改信息等。
    • 教师角色: 可以查看自己教授的课程和选课学生名单。
    • 在登录时增加角色选择。
  4. 图形用户界面:

    • 使用 EasyX (Windows) 或 GTK / Qt (跨平台) 等库,将命令行界面改为图形界面,提升用户体验。
  5. 更完善的错误处理:

    • 对文件打开失败、内存分配失败等情况进行更健壮的处理,而不是简单地 exit
  6. 增加排序和统计功能:

    • 按选课人数对课程进行排序。
    • 统计每门课的选课率、热门课程等。

这个学生选课系统设计方案涵盖了从需求分析到代码实现的全过程,通过模块化的设计,将复杂问题分解为小而美的函数,使得代码结构清晰、易于维护,文件I/O的设计保证了数据的持久化,核心的选课/退课逻辑则锻炼了对业务流程和边界条件的处理能力。

你可以按照这个框架,逐步实现每个函数,最终完成一个功能完整、结构良好的C语言课程设计项目,祝你项目顺利!

-- 展开阅读全文 --
头像
织梦产品列表页二级菜单
« 上一篇 01-07
织梦数据库密码忘了怎么办?
下一篇 » 01-07

相关文章

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

目录[+]