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




点击查看代码
#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;
}
原代码用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));
}


7. 总结
在这次工程和改进过程中,我遇到了以下几个难点和挑战:
难点:
- string 与 char [] 混用易致输入吞行、编译报错,需加
头文件,统一用 get/set 函数访问类成员; - 移除 goto 后循环标记位易设错,引发死循环 / 漏校验,需单一标记位、先梳理输入 - 校验 - 退出逻辑;
- 输入校验易传错参数,需按场景选函数并保留 cin.clear/ignore;
- 调试难,逻辑错分步打印,乱码固定 chcp 936 + 多字节字符集。
花时间比较久的部分:
- string 与输入流混用的输入逻辑调试;
- 类成员访问逐行替换为 get/set 并排错;
- 校验函数全场景测试调参。
我对这个软件工程的一些思考:
我发现写代码不只是 “能跑就行”。一开始用 char []、goto 写的代码,虽然能实现选课、录入功能,但容易出现内存出错、逻辑绕不清楚的问题,后续改起来也特别费劲;补充输入校验后,系统不会因为输错内容就出问题,而规范代码写法(比如不直接改类里的内容),也让后续调整功能更顺手。这让我明白,写代码要考虑后续好不好改、能不能应对各种错误输入。