1. 来源
    来自CSDN博客的https://blog.csdn.net/weixin_73870552/article/details/135298985?spm=1001.2014.3001.5501 我将对这个已经编译的程序进行测试,找出其中的问题,并进行改进。
  2. 运行环境
    系统:Windows 11 64 位
    VS2022 版本:社区版
    字符集:使用多字节字符集
    配置:Debug
  3. 运行结果

微信截图_20260310212447

微信截图_20260310212502

微信截图_20260310212511

微信截图_20260310212615

点击查看代码
#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include<fstream>
#include<vector>
#include<cstring>  // 替换string.h,C++标准头文件
#include<cstdlib>  // 替换stdlib.h,C++标准头文件
using namespace std;

int flag = 0;                   // 0=学生 1=管理员

class Course 
{
public:
    friend void Input_course(vector<Course>& cour);
    friend void Delete_course(vector<Course>& cour);
    friend void Modify_course(vector<Course>& cour);
    friend void Lookup_course(vector<Course>& cour);
    friend void Show_course(vector<Course>& cour);
    friend void Add_course(vector<Course>& cour);                                                                       
    friend int Read_course(vector<Course>& cour);
    friend void Write_course(vector<Course>& cour, int n);

    const char* c_id() { return id; }
    const char* c_name() { return name; }
    const bool c_nature() { return nature; }

    Course()
        : id("None"), name("None"), nature(false), hour(0), credit(0), count(0)  // 修正初始化
    {}

public:
    char id[20];
    char name[20];
private:
    bool nature;            // 0=选修 1=必修
    int hour;               // 课时                                                                             
    int credit;             // 学分(修正拼写错误:credir→credit)
public:
    int count;              // 选课人数 0-60
};

class Student
{
public:
    friend void Input_stu(vector<Student>& stu);
    friend void Delete_stu(vector<Student>& stu);
    friend void Modify_stu(vector<Student>& stu);
    friend void Lookup_stu(vector<Student>& stu);
    friend void Add_stu(vector<Student>& stu);
    friend void Show_stu(vector<Student>& stu);
    friend int Read_stu(vector<Student>& stu);
    friend void Write_stu(vector<Student>& stu, int n);

    friend void Select(vector<Course>& cour, vector<Student>& stu);
    friend void Deselect(vector<Course>& cour, vector<Student>& stu);
public:
    char _id[20];
    char _class[20];
    char _name[20];
    Course _cour_compulsory[2];  // 最多2门必修
    Course _cour_elective[1];    // 最多1门选修
    int _num_compulsory = 0;     // 已选必修数
    int _num_elective = 0;       // 已选选修数
};

vector<Course> cour;
vector<Student> stu;

// ========================================== 课程相关函数 ==================================================== //

void Write_course(vector<Course>& cour, int n)
{
    ofstream myfile("course.txt");  // 移除binary模式,文本写入无需二进制
    if (!myfile)
    {
        cout << "ERROR! course.txt 打开失败。" << endl;
        abort();
    }

    myfile << n << endl;  // 移除多余空行,避免读取异常
    for (int i = 0; i < n; i++)
    {
        myfile << cour[i].id << "\t" << cour[i].name << "\t"
            << cour[i].nature << "\t" << cour[i].hour << "\t"
            << cour[i].credit << "\t" << cour[i].count << endl;  // 修正credit
    }
    myfile.close();
}

int Read_course(vector<Course>& cour)
{
    cour.clear();
    ifstream myfile("course.txt");  // 移除binary模式
    if (!myfile)
    {
        cout << "提示:course.txt 不存在,将创建新文件。" << endl;
        return 0;  // 不存在则返回0,不终止程序
    }

    int n;
    myfile >> n;
    // 跳过换行符,避免读取数据错位
    myfile.ignore(numeric_limits<streamsize>::max(), '\n');

    Course temp;
    for (int i = 0; i < n; i++)
    {
        myfile >> temp.id >> temp.name >> temp.nature
            >> temp.hour >> temp.credit >> temp.count;  // 修正credit
        cour.push_back(temp);
    }

    myfile.close();
    return n;
}

void Input_course(vector<Course>& cour)
{
    system("cls");
    cour.clear();
    int i = 0;
    char sign = '0';
    Course temp;

    cout << "=============== 录入课程信息 ===============" << endl;
    while (sign != 'n' && sign != 'N')
    {
    loop:
        cout << "课程ID: ";
        cin >> temp.id;

        // 检查ID重复(修正循环逻辑)
        for (int c = 0; c < cour.size(); c++)
        {
            if (!strcmp(temp.id, cour[c].id))
            {
                cout << "ID重复,请重新输入!" << endl;
                goto loop;
            }
        }

        cout << "课程名称: ";
        cin >> temp.name;
        cout << "课程类型(0=选修 1=必修): ";
        cin >> temp.nature;
        cout << "课时: ";
        cin >> temp.hour;
        cout << "学分: ";
        cin >> temp.credit;  // 修正credit
        temp.count = 0;

        cour.push_back(temp);

        cout << "是否继续录入(y/n): ";
        cin >> sign;
        i++;
    }

    Write_course(cour, i);
}

void Delete_course(vector<Course>& cour)
{
    system("cls");
    int n = Read_course(cour);
    if (n == 0)
    {
        cout << "暂无课程数据!" << endl;
        system("pause");
        return;
    }

    char id[20];
    cout << "=============== 删除课程信息 ===============" << endl;
    cout << "请输入要删除的课程ID: ";
    cin >> id;

    int idx = -1;
    for (int i = 0; i < n; i++)
    {
        if (!strcmp(id, cour[i].id))
        {
            idx = i;
            break;
        }
    }

    if (idx == -1)
    {
        cout << "未找到该课程!" << endl;
        system("pause");
        return;
    }

    if (cour[idx].count > 0)
    {
        cout << "该课程已有学生选课,无法删除!" << endl;
        system("pause");
        return;
    }

    char sign;
    cout << "确认删除(y/n): ";
    cin >> sign;
    if (sign != 'n' && sign != 'N')
    {
        cour.erase(cour.begin() + idx);  // 直接删除指定位置,更高效
        Write_course(cour, n - 1);
        cout << "删除成功!" << endl;
    }
    else
    {
        cout << "取消删除!" << endl;
    }
    system("pause");
}

void Modify_course(vector<Course>& cour)
{
    system("cls");
    int n = Read_course(cour);
    if (n == 0)
    {
        cout << "暂无课程数据!" << endl;
        system("pause");
        return;
    }

    char id[20];
    cout << "=============== 修改课程信息 ===============" << endl;
    cout << "请输入要修改的课程ID: ";
    cin >> id;

    int idx = -1;
    for (int i = 0; i < n; i++)
    {
        if (!strcmp(id, cour[i].id))
        {
            idx = i;
            break;
        }
    }

    if (idx == -1)
    {
        cout << "未找到该课程!" << endl;
        system("pause");
        return;
    }

    if (cour[idx].count > 0)
    {
        cout << "该课程已有学生选课,无法修改!" << endl;
        system("pause");
        return;
    }

    // 显示原信息
    cout << "----------------------------------------------------" << endl;
    cout << "ID\t名称\t类型\t课时\t学分\t选课人数" << endl;
    cout << "----------------------------------------------------" << endl;
    cout << cour[idx].id << "\t" << cour[idx].name << "\t" << cour[idx].nature << "\t"
        << cour[idx].hour << "\t" << cour[idx].credit << "\t" << cour[idx].count << endl;

    // 重新输入
    cout << "请重新输入课程信息:" << endl;
    cout << "课程名称: ";
    cin >> cour[idx].name;
    cout << "课程类型(0=选修 1=必修): ";
    cin >> cour[idx].nature;
    cout << "课时: ";
    cin >> cour[idx].hour;
    cout << "学分: ";
    cin >> cour[idx].credit;

    char sign;
    cout << "保存修改(y/n): ";
    cin >> sign;
    if (sign != 'n' && sign != 'N')
    {
        Write_course(cour, n);
        cout << "修改成功!" << endl;
    }
    else
    {
        cout << "取消修改!" << endl;
    }
    system("pause");
}

void Lookup_course(vector<Course>& cour)
{
    system("cls");
    int n = Read_course(cour);
    if (n == 0)
    {
        cout << "暂无课程数据!" << endl;
        system("pause");
        return;
    }

    char id[20];
    cout << "=============== 查询课程信息 ===============" << endl;
    cout << "请输入要查询的课程ID: ";
    cin >> id;

    int idx = -1;
    for (int i = 0; i < n; i++)
    {
        if (!strcmp(id, cour[i].id))
        {
            idx = i;
            break;
        }
    }

    if (idx == -1)
    {
        cout << "未找到该课程!" << endl;
    }
    else
    {
        cout << "---------------------------------------------" << endl;
        cout << "ID: " << cour[idx].id << endl;
        cout << "名称: " << cour[idx].name << endl;
        cout << "类型: " << (cour[idx].nature ? "必修" : "选修") << endl;
        cout << "课时: " << cour[idx].hour << endl;
        cout << "学分: " << cour[idx].credit << endl;
        cout << "选课人数: " << cour[idx].count << endl;
    }
    system("pause");
}

void Show_course(vector<Course>& cour)
{
    system("cls");
    int n = Read_course(cour);
    if (n == 0)
    {
        cout << "暂无课程数据!" << endl;
        system("pause");
        return;
    }

    cout << "================ 显示所有课程 ================" << endl;
    cout << "----------------------------------------------------" << endl;
    cout << "ID\t名称\t类型\t课时\t学分\t选课人数" << endl;
    cout << "----------------------------------------------------" << endl;
    for (int i = 0; i < n; i++)
    {
        cout << cour[i].id << "\t" << cour[i].name << "\t" << cour[i].nature << "\t"
            << cour[i].hour << "\t" << cour[i].credit << "\t" << cour[i].count << endl;
    }
    system("pause");
}

void Add_course(vector<Course>& cour)
{
    system("cls");
    int n = Read_course(cour);
    char sign = '0';
    Course temp;

    cout << "=============== 添加课程信息 ===============" << endl;
    while (sign != 'n' && sign != 'N')
    {
    loop:
        cout << "课程ID: ";
        cin >> temp.id;

        // 检查ID重复
        for (int c = 0; c < cour.size(); c++)
        {
            if (!strcmp(temp.id, cour[c].id))
            {
                cout << "ID重复,请重新输入!" << endl;
                goto loop;
            }
        }

        cout << "课程名称: ";
        cin >> temp.name;
        cout << "课程类型(0=选修 1=必修): ";
        cin >> temp.nature;
        cout << "课时: ";
        cin >> temp.hour;
        cout << "学分: ";
        cin >> temp.credit;
        temp.count = 0;

        cour.push_back(temp);
        n++;

        cout << "是否继续添加(y/n): ";
        cin >> sign;
    }

    Write_course(cour, n);
    cout << "添加完成!" << endl;
    system("pause");
}

// ============================================ 学生相关函数 ============================================== //

void Write_stu(vector<Student>& stu, int n)
{
    ofstream myfile("student.txt");  // 移除binary模式
    if (!myfile)
    {
        cout << "ERROR! student.txt 打开失败!" << endl;
        abort();
    }

    myfile << n << endl;
    for (int i = 0; i < n; i++)
    {
        myfile << stu[i]._id << "\t" << stu[i]._class << "\t"
            << stu[i]._name << "\t"
            << stu[i]._cour_compulsory[0].id << "\t"
            << stu[i]._cour_compulsory[0].name << "\t"
            << stu[i]._cour_compulsory[1].id << "\t"
            << stu[i]._cour_compulsory[1].name << "\t"
            << stu[i]._cour_elective[0].id << "\t"
            << stu[i]._cour_elective[0].name << "\t"
            << stu[i]._num_compulsory << "\t" << stu[i]._num_elective << endl;
    }

    myfile.close();
}

int Read_stu(vector<Student>& stu)
{
    stu.clear();
    ifstream myfile("student.txt");  // 移除binary模式
    if (!myfile)
    {
        cout << "提示:student.txt 不存在,将创建新文件。" << endl;
        return 0;
    }

    int n;
    myfile >> n;
    myfile.ignore(numeric_limits<streamsize>::max(), '\n');  // 跳过换行符

    Student temp;
    for (int i = 0; i < n; i++)
    {
        myfile >> temp._id >> temp._class
            >> temp._name
            >> temp._cour_compulsory[0].id
            >> temp._cour_compulsory[0].name
            >> temp._cour_compulsory[1].id
            >> temp._cour_compulsory[1].name
            >> temp._cour_elective[0].id
            >> temp._cour_elective[0].name
            >> temp._num_compulsory >> temp._num_elective;
        stu.push_back(temp);
    }

    myfile.close();
    return n;
}

void Input_stu(vector<Student>& stu)
{
    system("cls");
    stu.clear();
    int i = 0;
    char sign = '0';
    Student temp;

    cout << "============ 录入学生信息 ============" << endl;
    while (sign != 'n' && sign != 'N')
    {
    loop:
        cout << "学生ID: ";
        cin >> temp._id;

        // 检查ID重复
        for (int c = 0; c < stu.size(); c++)
        {
            if (!strcmp(temp._id, stu[c]._id))
            {
                cout << "ID重复,请重新输入!" << endl;
                goto loop;
            }
        }

        cout << "学生姓名: ";
        cin >> temp._name;
        cout << "班级: ";
        cin >> temp._class;

        // 初始化选课信息
        temp._num_compulsory = 0;
        temp._num_elective = 0;
        strcpy(temp._cour_compulsory[0].id, "None");
        strcpy(temp._cour_compulsory[0].name, "None");
        strcpy(temp._cour_compulsory[1].id, "None");
        strcpy(temp._cour_compulsory[1].name, "None");
        strcpy(temp._cour_elective[0].id, "None");
        strcpy(temp._cour_elective[0].name, "None");

        stu.push_back(temp);
        cout << "是否继续录入(y/n): ";
        cin >> sign;
        i++;
    }
    Write_stu(stu, i);
    cout << "录入完成!" << endl;
    system("pause");
}

void Delete_stu(vector<Student>& stu)
{
    system("cls");
    int n = Read_stu(stu);
    int m = Read_course(cour);
    if (n == 0)
    {
        cout << "暂无学生数据!" << endl;
        system("pause");
        return;
    }

    char id[20];
    cout << "============ 删除学生信息 ============" << endl;
    cout << "请输入要删除的学生ID: ";
    cin >> id;

    int idx = -1;
    for (int i = 0; i < n; i++)
    {
        if (!strcmp(id, stu[i]._id))
        {
            idx = i;
            break;
        }
    }

    if (idx == -1)
    {
        cout << "未找到该学生!" << endl;
        system("pause");
        return;
    }

    // 归还选课名额
    for (int c = 0; c < stu[idx]._num_compulsory; c++)
    {
        for (int j = 0; j < m; j++)
        {
            if (!strcmp(stu[idx]._cour_compulsory[c].id, cour[j].id))
            {
                cour[j].count--;
                break;
            }
        }
    }
    for (int c = 0; c < stu[idx]._num_elective; c++)
    {
        for (int j = 0; j < m; j++)
        {
            if (!strcmp(stu[idx]._cour_elective[c].id, cour[j].id))
            {
                cour[j].count--;
                break;
            }
        }
    }

    char sign;
    cout << "确认删除(y/n): ";
    cin >> sign;
    if (sign != 'n' && sign != 'N')
    {
        stu.erase(stu.begin() + idx);
        Write_stu(stu, n - 1);
        Write_course(cour, m);
        cout << "删除成功!" << endl;
    }
    else
    {
        cout << "取消删除!" << endl;
    }
    system("pause");
}

void Modify_stu(vector<Student>& stu)
{
    system("cls");
    int n = Read_stu(stu);
    if (n == 0)
    {
        cout << "暂无学生数据!" << endl;
        system("pause");
        return;
    }

    char id[20];
    cout << "============ 修改学生信息 ============" << endl;
    cout << "请输入要修改的学生ID: ";
    cin >> id;

    int idx = -1;
    for (int i = 0; i < n; i++)
    {
        if (!strcmp(id, stu[i]._id))
        {
            idx = i;
            break;
        }
    }

    if (idx == -1)
    {
        cout << "未找到该学生!" << endl;
        system("pause");
        return;
    }

    // 显示原信息
    cout << "-------------------------------------------------------" << endl;
    cout << "ID: " << stu[idx]._id << endl;
    cout << "班级: " << stu[idx]._class << endl;
    cout << "姓名: " << stu[idx]._name << endl;
    cout << "-------------------------------------------------------" << endl;

    // 重新输入
    cout << "请重新输入学生信息:" << endl;
    cout << "班级: ";
    cin >> stu[idx]._class;
    cout << "姓名: ";
    cin >> stu[idx]._name;

    char sign;
    cout << "保存修改(y/n): ";
    cin >> sign;
    if (sign != 'n' && sign != 'N')
    {
        Write_stu(stu, n);
        cout << "修改成功!" << endl;
    }
    else
    {
        cout << "取消修改!" << endl;
    }
    system("pause");
}

void Lookup_stu(vector<Student>& stu)
{
    system("cls");
    int n = Read_stu(stu);
    if (n == 0)
    {
        cout << "暂无学生数据!" << endl;
        system("pause");
        return;
    }

    char id[20];
    cout << "============ 查询学生信息 ============" << endl;
    cout << "请输入要查询的学生ID: ";
    cin >> id;

    int idx = -1;
    for (int i = 0; i < n; i++)
    {
        if (!strcmp(id, stu[i]._id))
        {
            idx = i;
            break;
        }
    }

    if (idx == -1)
    {
        cout << "未找到该学生!" << endl;
    }
    else
    {
        cout << "---------------------------------------------" << endl;
        cout << "ID: " << stu[idx]._id << endl;
        cout << "班级: " << stu[idx]._class << endl;
        cout << "姓名: " << stu[idx]._name << endl;
        cout << "必修课程: ";
        for (int c = 0; c < stu[idx]._num_compulsory; c++)
        {
            cout << stu[idx]._cour_compulsory[c].name << " ";
        }
        if (stu[idx]._num_compulsory == 0) cout << "无";
        cout << endl;

        cout << "选修课程: ";
        for (int c = 0; c < stu[idx]._num_elective; c++)
        {
            cout << stu[idx]._cour_elective[c].name << " ";
        }
        if (stu[idx]._num_elective == 0) cout << "无";
        cout << endl;
    }
    system("pause");
}

void Add_stu(vector<Student>& stu)
{
    system("cls");
    int n = Read_stu(stu);
    char sign = '0';
    Student temp;

    cout << "============ 添加学生信息 ============" << endl;
    while (sign != 'n' && sign != 'N')
    {
    loop:
        cout << "学生ID: ";
        cin >> temp._id;

        // 检查ID重复
        for (int c = 0; c < stu.size(); c++)
        {
            if (!strcmp(temp._id, stu[c]._id))
            {
                cout << "ID重复,请重新输入!" << endl;
                goto loop;
            }
        }

        cout << "班级: ";
        cin >> temp._class;
        cout << "姓名: ";
        cin >> temp._name;

        // 初始化选课信息
        temp._num_compulsory = 0;
        temp._num_elective = 0;
        strcpy(temp._cour_compulsory[0].id, "None");
        strcpy(temp._cour_compulsory[0].name, "None");
        strcpy(temp._cour_compulsory[1].id, "None");
        strcpy(temp._cour_compulsory[1].name, "None");
        strcpy(temp._cour_elective[0].id, "None");
        strcpy(temp._cour_elective[0].name, "None");

        stu.push_back(temp);
        n++;

        cout << "是否继续添加(y/n): ";
        cin >> sign;
    }

    Write_stu(stu, n);
    cout << "添加完成!" << endl;
    system("pause");
}

void Show_stu(vector<Student>& stu)
{
    system("cls");
    int n = Read_stu(stu);
    if (n == 0)
    {
        cout << "暂无学生数据!" << endl;
        system("pause");
        return;
    }

    cout << "================ 显示所有学生 ================" << endl;
    cout << "--------------------------------------------------------------------------" << endl;
    cout << "ID\t班级\t姓名\t必修课程\t\t选修课程" << endl;
    cout << "--------------------------------------------------------------------------" << endl;
    for (int i = 0; i < n; i++)
    {
        cout << stu[i]._id << "\t" << stu[i]._class << "\t" << stu[i]._name << "\t";
        // 显示必修课程
        for (int c = 0; c < stu[i]._num_compulsory; c++)
        {
            cout << stu[i]._cour_compulsory[c].name << " ";
        }
        if (stu[i]._num_compulsory == 0) cout << "无\t\t";
        else cout << "\t\t";

        // 显示选修课程
        for (int c = 0; c < stu[i]._num_elective; c++)
        {
            cout << stu[i]._cour_elective[c].name << " ";
        }
        if (stu[i]._num_elective == 0) cout << "无";
        cout << endl;
    }
    system("pause");
}

void Select(vector<Course>& cour, vector<Student>& stu)
{
    system("cls");
    int n_cour = Read_course(cour);
    int n_stu = Read_stu(stu);
    if (n_cour == 0 || n_stu == 0)
    {
        cout << "课程或学生数据为空,无法选课!" << endl;
        system("pause");
        return;
    }

    char id_c[20];
    char id_s[20];
    cout << "============ 选课系统 ============" << endl;
    cout << "请输入学生ID: ";
    cin >> id_s;

    // 查找学生
    int stu_idx = -1;
    for (int i = 0; i < n_stu; i++)
    {
        if (!strcmp(stu[i]._id, id_s))
        {
            stu_idx = i;
            break;
        }
    }
    if (stu_idx == -1)
    {
        cout << "未找到该学生!" << endl;
        system("pause");
        return;
    }

    cout << "请输入要选的课程ID: ";
    cin >> id_c;

    // 查找课程
    int cour_idx = -1;
    for (int j = 0; j < n_cour; j++)
    {
        if (!strcmp(cour[j].id, id_c))
        {
            cour_idx = j;
            break;
        }
    }
    if (cour_idx == -1)
    {
        cout << "未找到该课程!" << endl;
        system("pause");
        return;
    }

    // 检查课程人数上限
    if (cour[cour_idx].count >= 60)
    {
        cout << "该课程选课人数已满,选课失败!" << endl;
        system("pause");
        return;
    }

    // 检查是否重复选课
    if (cour[cour_idx].nature)  // 必修课
    {
        // 检查已选必修课是否重复
        for (int c = 0; c < stu[stu_idx]._num_compulsory; c++)
        {
            if (!strcmp(cour[cour_idx].id, stu[stu_idx]._cour_compulsory[c].id))
            {
                cout << "已选该必修课程,选课失败!" << endl;
                system("pause");
                return;
            }
        }
        // 检查必修课数量上限
        if (stu[stu_idx]._num_compulsory >= 2)
        {
            cout << "必修课已选满2门,选课失败!" << endl;
            system("pause");
            return;
        }
        // 选课
        stu[stu_idx]._cour_compulsory[stu[stu_idx]._num_compulsory] = cour[cour_idx];
        stu[stu_idx]._num_compulsory++;
        cour[cour_idx].count++;
    }
    else  // 选修课
    {
        // 检查已选选修课是否重复
        for (int c = 0; c < stu[stu_idx]._num_elective; c++)
        {
            if (!strcmp(cour[cour_idx].id, stu[stu_idx]._cour_elective[c].id))
            {
                cout << "已选该选修课程,选课失败!" << endl;
                system("pause");
                return;
            }
        }
        // 检查选修课数量上限
        if (stu[stu_idx]._num_elective >= 1)
        {
            cout << "选修课已选满1门,选课失败!" << endl;
            system("pause");
            return;
        }
        // 选课
        stu[stu_idx]._cour_elective[stu[stu_idx]._num_elective] = cour[cour_idx];
        stu[stu_idx]._num_elective++;
        cour[cour_idx].count++;
    }

    // 保存数据
    Write_course(cour, n_cour);
    Write_stu(stu, n_stu);
    cout << "选课成功!" << endl;
    system("pause");
}

void Deselect(vector<Course>& cour, vector<Student>& stu)
{
    system("cls");
    int n_cour = Read_course(cour);
    int n_stu = Read_stu(stu);
    if (n_cour == 0 || n_stu == 0)
    {
        cout << "课程或学生数据为空,无法退课!" << endl;
        system("pause");
        return;
    }

    char id_c[20];
    char id_s[20];
    cout << "============ 退课系统 ============" << endl;
    cout << "请输入学生ID: ";
    cin >> id_s;

    // 查找学生
    int stu_idx = -1;
    for (int i = 0; i < n_stu; i++)
    {
        if (!strcmp(stu[i]._id, id_s))
        {
            stu_idx = i;
            break;
        }
    }
    if (stu_idx == -1)
    {
        cout << "未找到该学生!" << endl;
        system("pause");
        return;
    }

    cout << "请输入要退选的课程ID: ";
    cin >> id_c;

    // 查找课程
    int cour_idx = -1;
    for (int j = 0; j < n_cour; j++)
    {
        if (!strcmp(cour[j].id, id_c))
        {
            cour_idx = j;
            break;
        }
    }
    if (cour_idx == -1)
    {
        cout << "未找到该课程!" << endl;
        system("pause");
        return;
    }

    // 检查是否选过该课程(先查必修)
    bool is_selected = false;
    int del_idx = -1;
    for (int c = 0; c < stu[stu_idx]._num_compulsory; c++)
    {
        if (!strcmp(stu[stu_idx]._cour_compulsory[c].id, id_c))
        {
            is_selected = true;
            del_idx = c;
            break;
        }
    }

    // 再查选修
    if (!is_selected)
    {
        for (int c = 0; c < stu[stu_idx]._num_elective; c++)
        {
            if (!strcmp(stu[stu_idx]._cour_elective[c].id, id_c))
            {
                is_selected = true;
                del_idx = c;
                break;
            }
        }
    }

    if (!is_selected)
    {
        cout << "你未选择该课程,退课失败!" << endl;
        system("pause");
        return;
    }

    // 退课逻辑(必修)
    if (cour[cour_idx].nature)
    {
        stu[stu_idx]._num_compulsory--;
        // 移动后续课程填补空位
        for (int c = del_idx; c < stu[stu_idx]._num_compulsory; c++)
        {
            stu[stu_idx]._cour_compulsory[c] = stu[stu_idx]._cour_compulsory[c + 1];
        }
        // 清空最后一个位置
        strcpy(stu[stu_idx]._cour_compulsory[stu[stu_idx]._num_compulsory].id, "None");
        strcpy(stu[stu_idx]._cour_compulsory[stu[stu_idx]._num_compulsory].name, "None");
    }
    else  // 选修
    {
        stu[stu_idx]._num_elective--;
        // 移动后续课程填补空位
        for (int c = del_idx; c < stu[stu_idx]._num_elective; c++)
        {
            stu[stu_idx]._cour_elective[c] = stu[stu_idx]._cour_elective[c + 1];
        }
        // 清空最后一个位置
        strcpy(stu[stu_idx]._cour_elective[stu[stu_idx]._num_elective].id, "None");
        strcpy(stu[stu_idx]._cour_elective[stu[stu_idx]._num_elective].name, "None");
    }

    // 归还课程名额
    cour[cour_idx].count--;

    // 保存数据
    Write_course(cour, n_cour);
    Write_stu(stu, n_stu);
    cout << "退课成功!" << endl;
    system("pause");
}

// =========================================== 菜单函数 ========================================== //

int choose_user()
{
loop:
    system("cls");
    int c = 0;
    cout << "=================================================================" << endl;
    cout << "-------------- 欢迎使用课程选课系统 ---------------" << endl;
    cout << "请选择身份(1=管理员 2=学生),输入0退出: ";
    cin >> c;

    if (c == 0) return 0;

    char passwd[20];
    if (c == 1)
    {
        cout << "请输入管理员密码: ";
        cin >> passwd;
        if (!strcmp(passwd, "123456"))
        {
            flag = 1;
            cout << "登录成功!" << endl;
            system("pause");
        }
        else
        {
            cout << "密码错误!" << endl;
            system("pause");
            goto loop;
        }
    }
    else if (c == 2)
    {
        flag = 0;
        cout << "学生身份登录成功!" << endl;
        system("pause");
    }
    else
    {
        cout << "输入错误,请输入0-2!" << endl;
        system("pause");
        goto loop;
    }

    return c;
}

void menu_course()
{
    int c = 0;
    while (1)
    {
        system("cls");
        cout << "============ 课程管理菜单 ============" << endl;
        cout << "               1. 录入课程               " << endl;
        cout << "               2. 删除课程               " << endl;
        cout << "               3. 修改课程               " << endl;
        cout << "               4. 查询课程               " << endl;
        cout << "               5. 添加课程               " << endl;
        cout << "               6. 显示所有课程           " << endl;
        cout << "               0. 返回上一级             " << endl;
        cout << "----------------------------------------" << endl;
        cout << "请选择操作(0-6): ";
        cin >> c;
        switch (c)
        {
        case 1:
            if (flag) Input_course(cour);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 2:
            if (flag) Delete_course(cour);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 3:
            if (flag) Modify_course(cour);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 4:
            Lookup_course(cour);
            break;
        case 5:
            if (flag) Add_course(cour);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 6:
            Show_course(cour);
            break;
        case 0:
            cout << "返回成功!" << endl;
            system("pause");
            return;
        default:
            cout << "输入错误,请输入0-6!" << endl;
            system("pause");
            break;
        }
    }
}

void menu_student()
{
    int c = 0;
    while (1)
    {
        system("cls");
        cout << "============ 学生管理菜单 ============" << endl;
        cout << "               1. 录入学生               " << endl;
        cout << "               2. 删除学生               " << endl;
        cout << "               3. 修改学生               " << endl;
        cout << "               4. 查询学生               " << endl;
        cout << "               5. 添加学生               " << endl;
        cout << "               6. 显示所有学生           " << endl;
        cout << "               7. 选课                   " << endl;
        cout << "               8. 退课                   " << endl;
        cout << "               0. 返回上一级             " << endl;
        cout << "----------------------------------------" << endl;
        cout << "请选择操作(0-8): ";  // 修正提示文字错误(0-6→0-8)
        cin >> c;
        switch (c)
        {
        case 1:
            if (flag) Input_stu(stu);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 2:
            if (flag) Delete_stu(stu);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 3:
            if (flag) Modify_stu(stu);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 4:
            Lookup_stu(stu);
            break;
        case 5:
            if (flag) Add_stu(stu);
            else { cout << "权限不足!仅管理员可操作!" << endl; system("pause"); }
            break;
        case 6:
            Show_stu(stu);
            break;
        case 7:
            Select(cour, stu);
            break;
        case 8:
            Deselect(cour, stu);
            break;
        case 0:
            cout << "返回成功!" << endl;
            system("pause");
            return;
        default:
            cout << "输入错误,请输入0-8!" << endl;  // 修正提示文字
            system("pause");
            break;
        }
    }
}

int menu_main()
{
    int c = 0;
    while (1)
    {
        system("cls");
        cout << "====================================================" << endl;
        cout << "               1. 课程管理                    " << endl;
        cout << "               2. 学生管理                   " << endl;
        cout << "               0. 返回身份选择菜单           " << endl;
        cout << "请选择操作: ";
        cin >> c;

        if (c >= 0 && c <= 2) break;
        else { cout << "输入错误,请输入0-2!" << endl; system("pause"); }
    }

    return c;
}

int main()
{
    // 设置控制台编码(可选,解决中文乱码)
    system("chcp 65001 > nul");
    cour.reserve(100);
    stu.reserve(100);

    while (1)
    {
        if (!choose_user())
        {
            cout << "=============== 感谢使用! ===============" << endl;
            system("pause");
            return 0;
        }

        while (1)
        {
            switch (menu_main())
            {
            case 1:
                menu_course();
                break;
            case 2:
                menu_student();
                break;
            case 0:
                cout << "返回身份选择菜单!" << endl;
                system("pause");
                goto loop_main;  // 回到身份选择
            }
        }
    loop_main:;
    }
    return 0;
}
4. 主要问题 在使用了这个程序之后,我发现了以下几个问题:

原代码用char[]容易出现内存越界;
原代码用goto loop处理 ID 重复;
原代码只检查 ID 重复

接下来,我将对这些问题进行改进
5. 改进
发现char [] 固定长度,输入超长度会内存越界,strcpy/strcmp 无边界检查易出错。
想到用替换 char [] 为 std::string。

点击查看代码
class Course {
private:
    string courseId;
    string courseName;
public:
    void setCourseId(const string& inputId) {
        courseId = inputId;
    }
    void setCourseName(const string& inputName) {
        courseName = inputName;
    }
    string getCourseId() const { return courseId; }
    string getCourseName() const { return courseName; }
    bool isSameId(const string& targetId) const {
        return courseId == targetId;
    }
};

发现goto 跳转导致逻辑混乱,易出错,可读性差。想到用 while 循环 + 布尔标记替代 goto,单独检查 ID 重复。

点击查看代码
bool isCourseIdDuplicate(const string& id) {
    for (const auto& course : courses) {
        return course.getCourseId() == id;
    }
    return false;
}

void inputCourseId(Course& temp) {
    string inputId;
    bool isDuplicate = true;
    while (isDuplicate) {
        cout << "课程ID: ";
        cin >> inputId;
        if (isCourseIdDuplicate(inputId)) {
            cout << "ID重复,请重新输入!" << endl;
            isDuplicate = true;
        } else {
            isDuplicate = false;
        }
    }
    temp.setCourseId(inputId);
}

发现只查 ID 重复,无类型、范围、空输入校验,易导致程序崩溃。想到封装校验函数,校验字符串非空、整数范围、布尔值。

点击查看代码
string inputNonEmptyString(const string& prompt) {
    string input;
    while (true) {
        cout << prompt;
        getline(cin, input);
        if (!input.empty()) {
            return input;
        }
        cout << "输入不能为空!请重新输入!" << endl;
    }
}

int inputValidInt(const string& prompt, int minVal = 1, int maxVal = INT_MAX) {
    int input;
    while (true) {
        cout << prompt;
        if (cin >> input && input >= minVal && input <= maxVal) {
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            return input;
        }
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout << "输入非法!请输入" << minVal << "-" << maxVal << "之间的整数!" << endl;
    }
}

void inputCourseInfo(Course& temp) {
    string courseId;
    bool isDuplicate = true;
    while (isDuplicate) {
        courseId = inputNonEmptyString("课程ID: ");
        if (isCourseIdDuplicate(courseId)) {
            cout << "ID重复,请重新输入!" << endl;
        } else {
            isDuplicate = false;
        }
    }
    temp.setCourseId(courseId);

    temp.setCourseName(inputNonEmptyString("课程名称: "));

    int nature = inputValidInt("课程类型(0=选修 1=必修): ", 0, 1);
    temp.setIsCompulsory(nature == 1);

    temp.setClassHours(inputValidInt("课时: ", 1));

    temp.setCredits(inputValidInt("学分: ", 1));
}
6. 重构结果

微信截图_20260310214825

微信截图_20260310214904
7. 总结
在这次工程和改进过程中,我遇到了以下几个难点和挑战:
难点:

  1. string 与 char [] 混用易致输入吞行、编译报错,需加头文件,统一用 get/set 函数访问类成员;
  2. 移除 goto 后循环标记位易设错,引发死循环 / 漏校验,需单一标记位、先梳理输入 - 校验 - 退出逻辑;
  3. 输入校验易传错参数,需按场景选函数并保留 cin.clear/ignore;
  4. 调试难,逻辑错分步打印,乱码固定 chcp 936 + 多字节字符集。

花时间比较久的部分:

  1. string 与输入流混用的输入逻辑调试;
  2. 类成员访问逐行替换为 get/set 并排错;
  3. 校验函数全场景测试调参。

我对这个软件工程的一些思考:
我发现写代码不只是 “能跑就行”。一开始用 char []、goto 写的代码,虽然能实现选课、录入功能,但容易出现内存出错、逻辑绕不清楚的问题,后续改起来也特别费劲;补充输入校验后,系统不会因为输错内容就出问题,而规范代码写法(比如不直接改类里的内容),也让后续调整功能更顺手。这让我明白,写代码要考虑后续好不好改、能不能应对各种错误输入。