赞
踩
本文是对本人之前写过的一个学生选课系统的优化,整体上的逻辑是和我上一篇博客一样的(链接在此:https://blog.csdn.net/weixin_73870552/article/details/135298985?spm=1001.2014.3001.5501)。本文将具体介绍优化的部分,而不对基本的实现做过多阐述。
课程类:
class Course { // 输入输出流重载 friend ostream& operator<<(ostream& out, const Course& c); friend fstream& operator<<(fstream& fout, const Course& c); // friend istream& operator>>(istream& in, Course& c); 这个重载不好实现,因为要查重 friend fstream& operator>>(fstream& fin, Course& c); friend ostream& operator<<(ostream& out, const Student& s); public: // 构造函数初始化 Course() : _id("None") , _name("None") , _type(0) , _hour(0) , _credir(0) , _count(0) {} // 相关接口 const string c_id() { return _id; } // 编号的接口 const string c_name() { return _name; } // 名字的接口 int& c_count() { return _count; } // 选课人数的接口 const bool c_type() { return _type; } // 类型接口 // 文件操作 void Write(vector<Course>& cour, int n) {} // 向文件写入数据 int Read(vector<Course>& cour) {} // 从文件读取数据 void Add(vector<Course>& cour) {} // 增 void Delete(vector<Course>& cour) {} // 删 void Modify(vector<Course>& cour) {} // 改 void Lookup(vector<Course>& cour) {} // 查 void Show(vector<Course>& cour) {} // 展示所有信息 private: string _id; // 编号 string _name; // 课程名 bool _type; // 课程类型,1必修,0选修 int _hour; // 学时 int _credir; // 学分 int _count; // 选课人数 };
1.这个课程类的成员变量中记录了课程的基本信息,其中编号和课程名,这种有字符串属性的数据,我使用了string
来存储。方便后续直接使用==
或!=
进行字符串的比较。
2.写了构造函数用来初始化数据。
3.将对课程的操作都写成成员函数,封装起来。后续的操作函数使用涉及到匿名对象,不了解的同学可以看下我之前的博客,这里就不再过多赘述了。
4.设计了一些接口,以便可以在类外访问私有成员变量。其中只有选课人数的接口是没有const
修饰的,因为要在类外对其进行修改。
5.声明了输入输出流的重载,用来简化代码。学生类的输出流重载也要在课程类中友元声明一下,因为后续要在这个重载函数中访问课程的一些私有变量,且在这个重载函数中接口会失效。
学生类:
class Student { // 输入输出流重载 friend ostream& operator<<(ostream& out, const Student& s); friend fstream& operator<<(fstream& fout, const Student& s); // friend istream& operator>>(istream& in, Student& s); 这个重载不好实现,因为要查重 friend fstream& operator>>(fstream& fin, Student& s); public: Student() : _id("None") // 学号 , _class("None") // 班级 , _name("None") // 姓名 , _num_compulsory(0) , _num_elective(0) {} void Write(vector<Student>& stu, int n) {} int Read(vector<Student>& stu) {} void Add(vector<Student>& stu) {} void Delete(vector<Student>& stu) {} void Modify(vector<Student>& stu) {} void Lookup(vector<Student>& stu) {} void Show(vector<Student>& stu) {} void Select(vector<Course>& cour, vector<Student>& stu) {} // 选课 void Deselect(vector<Course>& cour, vector<Student>& stu) {} // 退选 private: string _id; // 学号 string _class; // 班级 string _name; // 名字 Course _cour_compulsory[SIZE_COMP]; // 必修课信息 Course _cour_elective[SIZE_ELECT]; // 选修课信息 int _num_compulsory; // 已选必修课数量 int _num_elective; // 已选选修课数量 };
1.学生类的成员变量记录了学生的基本信息。其中,课程的信息我用两个数组存了起来,SIZE_COMP
和SIZE_ELECT
是两个宏,分别对应学生所能选择的必修课和选修课最大数量。
2.学生相关的操作函数作为成员函数,写在Studnet
类中,相比课程类多了选课和退选的模块。
3.写了构造函数来初始化数据。
4.声明了输入输出流重载,简化代码。
课程类的输入输出重载:
ostream& operator<<(ostream& out, const Course& c) { out << c._id << "\t" << c._name << "\t" << (c._type ? "必修" : "选修") << "\t" << c._hour << "\t" << c._credir << "\t" << c._count; return out; } fstream& operator<<(fstream& fout, const Course& c) { fout << c._id << "\t" << c._name << "\t" << c._type << "\t" << c._hour << "\t" << c._credir << "\t" << c._count; return fout; } fstream& operator>>(fstream& fin, Course& c) { fin >> c._id >> c._name >> c._type >> c._hour >> c._credir >> c._count; return fin; }
要写一个io流的输出重载,还要写一个文件流的输入输出重载。由于课程类在输入信息时还需要判断课程的编号是否重复,输入流重载略显复杂,还不如直接输入,所以这里就不再实现了。
学生类的输入输出重载:
ostream& operator<<(ostream& out, const Student& s) { out << s._id << "\t" << s._class << "\t" << s._name << "\t"; for (int i = 0; i < SIZE_COMP; i++) out << s._cour_compulsory[i]._name << " "; out << "\t"; for (int i = 0; i < SIZE_ELECT; i++) out << s._cour_elective[i]._name << " "; return out; } fstream& operator<<(fstream& fout, const Student& s) { fout << s._id << "\t" << s._class << "\t" << s._name << "\t"; for (int i = 0; i < SIZE_COMP; i++) fout << s._cour_compulsory[i] << "\t"; for (int i = 0; i < SIZE_ELECT; i++) fout << s._cour_elective[i] << "\t"; fout << s._num_compulsory << "\t" << s._num_elective; return fout; } fstream& operator>>(fstream& fin, Student& s) { fin >> s._id >> s._class >> s._name; for (int i = 0; i < SIZE_COMP; i++) fin >> s._cour_compulsory[i]; for (int i = 0; i < SIZE_ELECT; i++) fin >> s._cour_elective[i]; fin >> s._num_compulsory >> s._num_elective; return fin; }
学生类的io流输入和课程类同理,要判断学号是否重复,所以这里不再实现重载。应注意,学生类的io流输出重载中,课程信息只输出课程名;学生类的文件流输入输出重载中,复用了课程类的文件输入输出重载。
实现增删查改,需要借助两个全局的动态数组。vector<Course> cour
和vector<Student> stu
。
课程类:
class Course { friend ostream& operator<<(ostream& out, const Course& c); friend fstream& operator<<(fstream& fout, const Course& c); // friend istream& operator>>(istream& in, Course& c); 这个重载不好实现,因为要查重 friend fstream& operator>>(fstream& fin, Course& c); friend ostream& operator<<(ostream& out, const Student& s); public: Course() : _id("None") , _name("None") , _type(0) , _hour(0) , _credir(0) , _count(0) {} const string c_id() { return _id; } // 编号的接口 const string c_name() { return _name; } // 名字的接口 int& c_count() { return _count; } // 选课人数的接口 const bool c_type() { return _type; } // 类型接口 void Write(vector<Course>& cour, int n) { fstream myfile; myfile.open("course.txt", ios::out | ios::binary); if (!myfile) { cout << "course.txt can't open." << endl; abort(); } myfile << n << endl << endl; for (int i = 0; i < n; i++) myfile << cour[i] << endl; myfile.close(); } int Read(vector<Course>& cour) { cour.clear(); fstream myfile; myfile.open("course.txt", ios::in | ios::binary); if (!myfile) { cout << "course.txt can't open." << endl; abort(); } int n; myfile.seekg(0); myfile >> n; Course temp; for (int i = 0; i < n; i++) { myfile >> temp; cour.push_back(temp); } myfile.close(); return n; } void Add(vector<Course>& cour) { system("cls"); int n = Read(cour); char sign = '0'; Course temp; cout << "============ 增加课程信息 ============" << endl; while (sign != 'n' && sign != 'N') { loop: cout << "ID: "; cin >> temp._id; // 查重 int c = 0; while (c < n) { c++; if (temp._id == cour[n - c]._id) { cout << "编号重复,请重新输入。" << endl; goto loop; } } cout << "课程名: "; cin >> temp._name; cout << "课程类型(1必修,0选修): "; cin >> temp._type; cout << "学时: "; cin >> temp._hour; cout << "学分: "; cin >> temp._credir; n++; cour.push_back(temp); cout << "是否继续添加(y 或 n)"; cin >> sign; } // 保存进文件 Write(cour, n); } void Delete(vector<Course>& cour) { system("cls"); int n = Read(cour); int i = 0; string id; cout << "============ 删除课程 ============" << endl; cout << "请输入需要删除课程的编号: "; cin >> id; // 检查有没有这个课程 while (i < n && id != cour[i]._id) i++; if (i == n) { cout << "没找到该课程。" << endl; system("pause"); return; } else { if (cour[i]._count) { cout << "所选人数不为零,请联系所有学生退选后,再删除该课程。" << endl; system("pause"); return; } } for (int j = i; j < n - 1; j++) cour[j] = cour[j + 1]; // 编译器自动生成的赋值运算符重载 // 保存 char sign; cout << "是否保存(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { cour.erase(cour.end() - 1); Write(cour, n - 1); cout << "============ 删除成功 ============" << endl; system("pause"); } } void Modify(vector<Course>& cour) { system("cls"); int n = Read(cour); string id; int i = 0; cout << "============ 修改课程信息 ============" << endl; cout << "请输入你想修改的课程id: "; cin >> id; // 看有没有这个课程 cin >> id; while (i < n && id != cour[i]._id) i++; if (i == n) { cout << "没有找到该课程。" << endl; system("pause"); return; } else { if (cour[i]._count) { cout << "所选人数不为零,请联系所有学生退选后,再修改课程信息。" << endl; system("pause"); return; } } cout << "-------------------------------------------------" << endl; cout << "编号" << "\t" << "课程名" << "\t" << "类型" << "\t" << "学时" << "\t" << "学分" << "\t" << "选课人数" << endl; cout << cour[i] << endl; cout << "-------------------------------------------------" << endl; cout << "请重新输入课程信息。" << endl; cout << "课程名: "; cin >> cour[i]._name; cout << "课程类型(1必修,0选修): "; cin >> cour[i]._type; cout << "学时: "; cin >> cour[i]._hour; cout << "学分: "; cin >> cour[i]._credir; // 保存 char sign; cout << "是否保存修改(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { Write(cour, n); cout << "============ 修改成功 ============" << endl; system("pause"); } } void Lookup(vector<Course>& cour) { system("cls"); int n = Read(cour); int i = 0; string id; cout << "============ 查找课程 ============" << endl; cout << "请输入要查找课程的编号: "; cin >> id; // 检查是否存在 while (i < n && id != cour[i]._id) i++; if (i == n) { cout << "没有找到该课程。" << endl; } else { cout << "-------------------------------------------------" << endl; cout << "编号" << "\t" << "课程名" << "\t" << "类型" << "\t" << "学时" << "\t" << "学分" << "\t" << "选课人数" << endl; cout << "-------------------------------------------------" << endl; cout << cour[i] << endl; } system("pause"); } void Show(vector<Course>& cour) { system("cls"); int n = Read(cour); cout << "============ 展示所有课程信息 ============" << endl; cout << "-------------------------------------------------" << endl; cout << "编号" << "\t" << "课程名" << "\t" << "类型" << "\t" << "学时" << "\t" << "学分" << "\t" << "选课人数" << endl; cout << "-------------------------------------------------" << endl; for (int i = 0; i < n; i++) cout << cour[i] << endl; system("pause"); } private: string _id; // 编号 string _name; // 课程名 bool _type; // 课程类型,1必修,0选修 int _hour; // 学时 int _credir; // 学分 int _count; // 选课人数 };
学生类:
class Student { friend ostream& operator<<(ostream& out, const Student& s); friend fstream& operator<<(fstream& fout, const Student& s); // friend istream& operator>>(istream& in, Student& s); 这个重载不好实现,因为要查重 friend fstream& operator>>(fstream& fin, Student& s); public: Student() : _id("None") // 学号 , _class("None") // 班级 , _name("None") // 姓名 , _num_compulsory(0) , _num_elective(0) {} void Write(vector<Student>& stu, int n) { fstream myfile; myfile.open("student.txt", ios::out | ios::binary); if (!myfile) { cout << "student.txt can't open." << endl; abort(); } myfile << n << endl << endl; for (int i = 0; i < n; i++) myfile << stu[i] << endl; myfile.close(); } int Read(vector<Student>& stu) { stu.clear(); fstream myfile; myfile.open("student.txt", ios::in | ios::binary); if (!myfile) { cout << "student.txt can't open." << endl; abort(); } int n; myfile.seekg(0); myfile >> n; Student temp; for (int i = 0; i < n; i++) { myfile >> temp; stu.push_back(temp); } myfile.close(); return n; } void Add(vector<Student>& stu) { system("cls"); int n = Read(stu); char sign = '0'; Student temp; cout << "============ 添加学生 ============" << endl; while (sign != 'n' && sign != 'N') { loop: cout << "学号: "; cin >> temp._id; // 检查重复 int c = 0; while (c < n) { c++; if (temp._id == stu[n - c]._id) { cout << "学号重复,请重新输入。" << endl; goto loop; } } cout << "班级: "; cin >> temp._class; cout << "姓名: "; cin >> temp._name; n++; stu.push_back(temp); cout << "是否继续添加(y 或 n): "; cin >> sign; } Write(stu, n); } void Delete(vector<Student>& stu) { system("cls"); int n = Read(stu); int m = Course().Read(cour); // 课程数量 int i = 0; string id; cout << "============ 删除学生 =============" << endl; cout << "请输入要删除学生的学号: "; cin >> id; while (i < n && id != stu[i]._id) i++; if (i == n) { cout << "没有找到该学生。" << endl; system("pause"); return; } // 找到该学生所选的全部课程,并让这些课程的选课人数-1 if (stu[i]._num_compulsory) { while (stu[i]._num_compulsory > 0) { stu[i]._num_compulsory--; int c = 0; while (c < m) { if (stu[i]._cour_compulsory[stu[i]._num_compulsory].c_id() == cour[c].c_id()) { cour[c].c_count()--; break; } c++; } } } else if (stu[i]._num_elective) { while (stu[i]._num_elective > 0) { stu[i]._num_elective--; int c = 0; while (c < m) { if (stu[i]._cour_elective[stu[i]._num_elective].c_id() == cour[c].c_id()) { cour[c].c_count()--; break; } c++; } } } for (int j = i; j < n - 1; j++) stu[j] = stu[j + 1]; // 保存 char sign; cout << "请确定是否删除(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { stu.erase(stu.end() - 1); Write(stu, n - 1); Course().Write(cour, m); cout << "============ 删除成功 ============" << endl; system("pause"); } } void Modify(vector<Student>& stu) { system("cls"); int n = Read(stu); string id; int i = 0; cout << "============ 修改学生信息 ===========" << endl; cout << "请输入你想修改学生的学号: "; cin >> id; while (i < n && id != stu[i]._id) i++; if (i == n) { cout << "找不到该学生。" << endl; system("pause"); return; } cout << "-------------------------------------------------------" << endl; cout << "学号: " << stu[i]._id << endl; cout << "班级: " << stu[i]._class << endl; cout << "姓名: " << stu[i]._name << endl; cout << "-------------------------------------------------------" << endl; cout << "请重新输入学生信息。" << endl; cout << "班级: "; cin >> stu[i]._class; cout << "姓名: "; cin >> stu[i]._name; // 保存 char sign; cout << "是否保存修改(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { cout << "修改成功。" << endl; Write(stu, n); system("pause"); } } void Lookup(vector<Student>& stu) { system("cls"); int n = Read(stu); Course().Read(cour); int i = 0; string id; cout << "============== 查找学生 ==============" << endl; cout << "请输入要查找学生的学号: "; cin >> id; while (i < n && id != stu[i]._id) i++; if (i == n) { cout << "找不到该学生。" << endl; } else { cout << stu[i] << endl; } system("pause"); } void Show(vector<Student>& stu) { system("cls"); int n = Read(stu); cout << "=============================== 展示所有学生信息 ==============================" << endl; cout << "学号" << "\t" << "班级" << "\t" << "姓名" << "\t" << "必修课" << "\t" << "选修课" << endl; cout << "-------------------------------------------------------------------------------" << endl; for (int i = 0; i < n; i++) cout << stu[i] << endl; system("pause"); } private: string _id; // 学号 string _class; // 班级 string _name; // 名字 Course _cour_compulsory[SIZE_COMP]; // 必修课信息 Course _cour_elective[SIZE_ELECT]; // 选修课信息 int _num_compulsory; // 已选必修课数量 int _num_elective; // 已选选修课数量 };
可以发现,在查找和展示所有的函数中,我使用了输出流重载,让代码的可读性更高,也减少了代码量。
需要注意,和老版本不同,我没有再定义初始化文件的函数Input
。所以这需要我们提前创建好两个文本文件,并进行相应的数据录入,具体格式如下:
course.txt:
student.txt:
int choose_user() { loop: system("cls"); int c = 0; cout << "=================================================================" << endl; cout << "-------------- 欢迎来到学生选课系统 ---------------" << endl; cout << "请选择你的身份(1管理员 或 2学生)(输入0退出): "; cin >> c; string passwd; if (c == 1) { cout << "请输入密码: "; cin >> passwd; if (passwd == string(PASSWORD)) // PASSWORD是一个宏,#define PASSWORD 密码 { flag = 1; cout << "登入成功." << endl; system("pause"); } else { cout << "密码错误." << endl; system("pause"); goto loop; } } else flag = 0; if (c < 0 || c > 2) { 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 << " 0. 返回上级目录 " << endl; cout << "----------------------------------" << endl; cout << "请选择你的操作(0-6): "; cin >> c; switch (c) { case 1: if (flag) Course().Add(cour); else { cout << "request denied." << endl; system("pause"); } break; case 2: if (flag) Course().Delete(cour); else { cout << "request denied." << endl; system("pause"); } break; case 3: if (flag) Course().Modify(cour); else { cout << "request denied." << endl; system("pause"); } break; case 4: Course().Lookup(cour); break; case 5: Course().Show(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 << " 0. 返回 " << endl; cout << "----------------------------------" << endl; cout << "请选择你的操作(0-7): "; cin >> c; switch (c) { case 1: if (flag) Student().Add(stu); else { cout << "request denied." << endl; system("pause"); } break; case 2: if (flag) Student().Delete(stu); else { cout << "request denied." << endl; system("pause"); } break; case 3: if (flag) Student().Modify(stu); else { cout << "request denied." << endl; system("pause"); } break; case 4: Student().Lookup(stu); break; case 5: Student().Show(stu); break; case 6: Student().Select(cour, stu); break; case 7: Student().Deselect(cour, stu); break; case 0: cout << "------------ 返回成功 ------------" << endl; system("pause"); return; default: cout << "请输入 0-7." << 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 << "请选择你的操作(0-2): "; cin >> c; if (c < 0 || c > 2) { cout << "请输入 0-2." << endl; system("pause"); } else break; } return c; } int main() { cour.reserve(100); stu.reserve(100); while (1) { loop: if (!choose_user()) { cout << "=============== 谢谢使用!再见! ===============" << endl; 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; default: cout << "请输入 0-2." << endl; system("pause"); break; } } } return 0; }
这个菜单的实现基本和上一个版本相同,只不过密码处做了些许改动。定义了一个宏PASSWORD
,方便后续的维护。
class Student { public: // ... // 选课 void Select(vector<Course>& cour, vector<Student>& stu) { system("cls"); int n_cour = Course().Read(cour); int n_stu = Read(stu); int i = 0; // 学生 int j = 0; // 课程 string id_c; // 课程 string id_s; // 学生 cout << "============ 开始选课 ============" << endl; cout << "请输入学生学号: "; cin >> id_s; while (i < n_stu && stu[i]._id != id_s) i++; if (i == n_stu) { cout << "找不到该学生。" << endl; system("pause"); return; } cout << ("请输入想选择的课程编号: "); cin >> id_c; while (j < n_cour && cour[j].c_id() != id_c) j++; if (j == n_cour) { cout << "找不到该课程" << endl; system("pause"); return; } if (cour[j].c_count() >= 60) { cout << "课程人数已达上限,选课失败。" << endl; system("pause"); } else { if (cour[j].c_type()) if (stu[i]._num_compulsory < 2) { int c = 0; while (c < stu[i]._num_compulsory && cour[j].c_id() != stu[i]._cour_compulsory[c].c_id()) c++; if (c < stu[i]._num_compulsory) { cout << "请勿重复选择课程。" << endl; system("pause"); return; } stu[i]._cour_compulsory[stu[i]._num_compulsory] = cour[j]; stu[i]._num_compulsory++; cour[j].c_count()++; Course().Write(cour, n_cour); Write(stu, n_stu); cout << "选课成功。" << endl; system("pause"); } else { cout << "必修课数量已达上限,选课失败。" << endl; system("pause"); } else { if (stu[i]._num_elective < 1) { int c = 0; while (c < stu[i]._num_elective && cour[j].c_id() != stu[i]._cour_elective[c].c_id()) c++; if (c < stu[i]._num_elective) { cout << "请勿重复选择课程。" << endl; system("pause"); return; } stu[i]._cour_elective[stu[i]._num_elective] = cour[j]; stu[i]._num_elective++; cour[j].c_count()++; Course().Write(cour, n_cour); Write(stu, n_stu); cout << "选课成功。" << endl; system("pause"); } else { cout << "选修课数量已达上限,选课失败。" << endl; system("pause"); } } } } // 退选 void Deselect(vector<Course>& cour, vector<Student>& stu) { system("cls"); int n_cour = Course().Read(cour); int n_stu = Read(stu); int i = 0; // 学生 int j = 0; // 课程 string id_c; // 课程 string id_s; // 学生 cout << "============ 退选 ============" << endl; cout << "请输入学生学号: "; cin >> id_s; while (i < n_stu && stu[i]._id != id_s) i++; if (i == n_stu) { cout << "找不到该学生。" << endl; system("pause"); return; } cout << ("请输入想要退选的课程编号: "); cin >> id_c; while (j < n_cour && cour[j].c_id() != id_c) j++; if (j == n_cour) { cout << "找不到该课程" << endl; system("pause"); return; } if (stu[i]._num_compulsory) { int c = stu[i]._num_compulsory - 1; while (c >= 0) { if (stu[i]._cour_compulsory[c].c_id() == id_c) { cour[j].c_count()--; stu[i]._num_compulsory--; stu[i]._cour_compulsory[c] = Course(); // 重新排序 for (; c < stu[i]._num_compulsory; c++) swap(stu[i]._cour_compulsory[c], stu[i]._cour_compulsory[c + 1]); Write(stu, n_stu); Course().Write(cour, n_cour); cout << "退选成功。" << endl; system("pause"); return; } c--; } if (stu[i]._cour_elective) { int c = stu[i]._num_elective - 1; while (c >= 0) { if (stu[i]._cour_elective[c].c_id() == id_c) { cour[j].c_count()--; stu[i]._num_elective--; stu[i]._cour_elective[c] = Course(); for (; c < stu[i]._num_elective; c++) swap(stu[i]._cour_elective[c], stu[i]._cour_elective[c + 1]); Write(stu, n_stu); Course().Write(cour, n_cour); cout << "退选成功。" << endl; system("pause"); return; } c--; } cout << "你并未选择该课程。" << endl; system("pause"); return; } } if (stu[i]._cour_elective) { int c = stu[i]._num_elective - 1; while (c >= 0) { if (stu[i]._cour_elective[c].c_id() == id_c) { cour[j].c_count()--; stu[i]._num_elective--; stu[i]._cour_elective[c] = Course(); for (; c < stu[i]._num_elective; c++) swap(stu[i]._cour_elective[c], stu[i]._cour_elective[c + 1]); Write(stu, n_stu); Course().Write(cour, n_cour); cout << "退选成功。" << endl; system("pause"); return; } c--; } cout << "你并未选择该课程。" << endl; system("pause"); return; } } private: string _id; // 学号 string _class; // 班级 string _name; // 名字 Course _cour_compulsory[SIZE_COMP]; // 必修课信息 Course _cour_elective[SIZE_ELECT]; // 选修课信息 int _num_compulsory; // 已选必修课数量 int _num_elective; // 已选选修课数量 };
这一块的实现也和老版本没有多大区别,这里不再过多赘述,细节在我的上一篇博客中都有很详细的讲解。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<fstream> #include<string> #include<vector> using namespace std; #define SIZE_COMP 2 // 可以选择的必修课数量 #define SIZE_ELECT 1 // 可选择的选修课数量 #define PASSWORD "123456" // 管理员密码 int flag = 0; // 确定身份状态的状态变量,0是学生,1是管理员,默认是0 class Student; // 向前声明学生类 class Course { friend ostream& operator<<(ostream& out, const Course& c); friend fstream& operator<<(fstream& fout, const Course& c); // friend istream& operator>>(istream& in, Course& c); 这个重载不好实现,因为要查重 friend fstream& operator>>(fstream& fin, Course& c); friend ostream& operator<<(ostream& out, const Student& s); public: Course() : _id("None") , _name("None") , _type(0) , _hour(0) , _credir(0) , _count(0) {} const string c_id() { return _id; } // 编号的接口 const string c_name() { return _name; } // 名字的接口 int& c_count() { return _count; } // 选课人数的接口 const bool c_type() { return _type; } // 类型接口 void Write(vector<Course>& cour, int n) { fstream myfile; myfile.open("course.txt", ios::out | ios::binary); if (!myfile) { cout << "course.txt can't open." << endl; abort(); } myfile << n << endl << endl; for (int i = 0; i < n; i++) myfile << cour[i] << endl; myfile.close(); } int Read(vector<Course>& cour) { cour.clear(); fstream myfile; myfile.open("course.txt", ios::in | ios::binary); if (!myfile) { cout << "course.txt can't open." << endl; abort(); } int n; myfile.seekg(0); myfile >> n; Course temp; for (int i = 0; i < n; i++) { myfile >> temp; cour.push_back(temp); } myfile.close(); return n; } void Add(vector<Course>& cour) { system("cls"); int n = Read(cour); char sign = '0'; Course temp; cout << "============ 增加课程信息 ============" << endl; while (sign != 'n' && sign != 'N') { loop: cout << "ID: "; cin >> temp._id; // 查重 int c = 0; while (c < n) { c++; if (temp._id == cour[n - c]._id) { cout << "编号重复,请重新输入。" << endl; goto loop; } } cout << "课程名: "; cin >> temp._name; cout << "课程类型(1必修,0选修): "; cin >> temp._type; cout << "学时: "; cin >> temp._hour; cout << "学分: "; cin >> temp._credir; n++; cour.push_back(temp); cout << "是否继续添加(y 或 n)"; cin >> sign; } // 保存进文件 Write(cour, n); } void Delete(vector<Course>& cour) { system("cls"); int n = Read(cour); int i = 0; string id; cout << "============ 删除课程 ============" << endl; cout << "请输入需要删除课程的编号: "; cin >> id; // 检查有没有这个课程 while (i < n && id != cour[i]._id) i++; if (i == n) { cout << "没找到该课程。" << endl; system("pause"); return; } else { if (cour[i]._count) { cout << "所选人数不为零,请联系所有学生退选后,再删除该课程。" << endl; system("pause"); return; } } for (int j = i; j < n - 1; j++) cour[j] = cour[j + 1]; // 编译器自动生成的赋值运算符重载 // 保存 char sign; cout << "是否保存(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { cour.erase(cour.end() - 1); Write(cour, n - 1); cout << "============ 删除成功 ============" << endl; system("pause"); } } void Modify(vector<Course>& cour) { system("cls"); int n = Read(cour); string id; int i = 0; cout << "============ 修改课程信息 ============" << endl; cout << "请输入你想修改的课程id: "; cin >> id; // 看有没有这个课程 cin >> id; while (i < n && id != cour[i]._id) i++; if (i == n) { cout << "没有找到该课程。" << endl; system("pause"); return; } else { if (cour[i]._count) { cout << "所选人数不为零,请联系所有学生退选后,再修改课程信息。" << endl; system("pause"); return; } } cout << "-------------------------------------------------" << endl; cout << "编号" << "\t" << "课程名" << "\t" << "类型" << "\t" << "学时" << "\t" << "学分" << "\t" << "选课人数" << endl; cout << cour[i] << endl; cout << "-------------------------------------------------" << endl; cout << "请重新输入课程信息。" << endl; cout << "课程名: "; cin >> cour[i]._name; cout << "课程类型(1必修,0选修): "; cin >> cour[i]._type; cout << "学时: "; cin >> cour[i]._hour; cout << "学分: "; cin >> cour[i]._credir; // 保存 char sign; cout << "是否保存修改(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { Write(cour, n); cout << "============ 修改成功 ============" << endl; system("pause"); } } void Lookup(vector<Course>& cour) { system("cls"); int n = Read(cour); int i = 0; string id; cout << "============ 查找课程 ============" << endl; cout << "请输入要查找课程的编号: "; cin >> id; // 检查是否存在 while (i < n && id != cour[i]._id) i++; if (i == n) { cout << "没有找到该课程。" << endl; } else { cout << "-------------------------------------------------" << endl; cout << "编号" << "\t" << "课程名" << "\t" << "类型" << "\t" << "学时" << "\t" << "学分" << "\t" << "选课人数" << endl; cout << "-------------------------------------------------" << endl; cout << cour[i] << endl; } system("pause"); } void Show(vector<Course>& cour) { system("cls"); int n = Read(cour); cout << "============ 展示所有课程信息 ============" << endl; cout << "-------------------------------------------------" << endl; cout << "编号" << "\t" << "课程名" << "\t" << "类型" << "\t" << "学时" << "\t" << "学分" << "\t" << "选课人数" << endl; cout << "-------------------------------------------------" << endl; for (int i = 0; i < n; i++) cout << cour[i] << endl; system("pause"); } private: string _id; // 编号 string _name; // 课程名 bool _type; // 课程类型,1必修,0选修 int _hour; // 学时 int _credir; // 学分 int _count; // 选课人数 }; vector<Course> cour; ostream& operator<<(ostream& out, const Course& c) { out << c._id << "\t" << c._name << "\t" << (c._type ? "必修" : "选修") << "\t" << c._hour << "\t" << c._credir << "\t" << c._count; return out; } fstream& operator<<(fstream& fout, const Course& c) { fout << c._id << "\t" << c._name << "\t" << c._type << "\t" << c._hour << "\t" << c._credir << "\t" << c._count; return fout; } fstream& operator>>(fstream& fin, Course& c) { fin >> c._id >> c._name >> c._type >> c._hour >> c._credir >> c._count; return fin; } class Student { friend ostream& operator<<(ostream& out, const Student& s); friend fstream& operator<<(fstream& fout, const Student& s); // friend istream& operator>>(istream& in, Student& s); 这个重载不好实现,因为要查重 friend fstream& operator>>(fstream& fin, Student& s); public: Student() : _id("None") // 学号 , _class("None") // 班级 , _name("None") // 姓名 , _num_compulsory(0) , _num_elective(0) {} void Write(vector<Student>& stu, int n) { fstream myfile; myfile.open("student.txt", ios::out | ios::binary); if (!myfile) { cout << "student.txt can't open." << endl; abort(); } myfile << n << endl << endl; for (int i = 0; i < n; i++) myfile << stu[i] << endl; myfile.close(); } int Read(vector<Student>& stu) { stu.clear(); fstream myfile; myfile.open("student.txt", ios::in | ios::binary); if (!myfile) { cout << "student.txt can't open." << endl; abort(); } int n; myfile.seekg(0); myfile >> n; Student temp; for (int i = 0; i < n; i++) { myfile >> temp; stu.push_back(temp); } myfile.close(); return n; } void Add(vector<Student>& stu) { system("cls"); int n = Read(stu); char sign = '0'; Student temp; cout << "============ 添加学生 ============" << endl; while (sign != 'n' && sign != 'N') { loop: cout << "学号: "; cin >> temp._id; // 检查重复 int c = 0; while (c < n) { c++; if (temp._id == stu[n - c]._id) { cout << "学号重复,请重新输入。" << endl; goto loop; } } cout << "班级: "; cin >> temp._class; cout << "姓名: "; cin >> temp._name; n++; stu.push_back(temp); cout << "是否继续添加(y 或 n): "; cin >> sign; } Write(stu, n); } void Delete(vector<Student>& stu) { system("cls"); int n = Read(stu); int m = Course().Read(cour); // 课程数量 int i = 0; string id; cout << "============ 删除学生 =============" << endl; cout << "请输入要删除学生的学号: "; cin >> id; while (i < n && id != stu[i]._id) i++; if (i == n) { cout << "没有找到该学生。" << endl; system("pause"); return; } // 找到该学生所选的全部课程,并让这些课程的选课人数-1 if (stu[i]._num_compulsory) { while (stu[i]._num_compulsory > 0) { stu[i]._num_compulsory--; int c = 0; while (c < m) { if (stu[i]._cour_compulsory[stu[i]._num_compulsory].c_id() == cour[c].c_id()) { cour[c].c_count()--; break; } c++; } } } else if (stu[i]._num_elective) { while (stu[i]._num_elective > 0) { stu[i]._num_elective--; int c = 0; while (c < m) { if (stu[i]._cour_elective[stu[i]._num_elective].c_id() == cour[c].c_id()) { cour[c].c_count()--; break; } c++; } } } for (int j = i; j < n - 1; j++) stu[j] = stu[j + 1]; // 保存 char sign; cout << "请确定是否删除(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { stu.erase(stu.end() - 1); Write(stu, n - 1); Course().Write(cour, m); cout << "============ 删除成功 ============" << endl; system("pause"); } } void Modify(vector<Student>& stu) { system("cls"); int n = Read(stu); string id; int i = 0; cout << "============ 修改学生信息 ===========" << endl; cout << "请输入你想修改学生的学号: "; cin >> id; while (i < n && id != stu[i]._id) i++; if (i == n) { cout << "找不到该学生。" << endl; system("pause"); return; } cout << "-------------------------------------------------------" << endl; cout << "学号: " << stu[i]._id << endl; cout << "班级: " << stu[i]._class << endl; cout << "姓名: " << stu[i]._name << endl; cout << "-------------------------------------------------------" << endl; cout << "请重新输入学生信息。" << endl; cout << "班级: "; cin >> stu[i]._class; cout << "姓名: "; cin >> stu[i]._name; // 保存 char sign; cout << "是否保存修改(y 或 n): "; cin >> sign; if (sign != 'n' && sign != 'N') { cout << "修改成功。" << endl; Write(stu, n); system("pause"); } } void Lookup(vector<Student>& stu) { system("cls"); int n = Read(stu); Course().Read(cour); int i = 0; string id; cout << "============== 查找学生 ==============" << endl; cout << "请输入要查找学生的学号: "; cin >> id; while (i < n && id != stu[i]._id) i++; if (i == n) { cout << "找不到该学生。" << endl; } else { cout << stu[i] << endl; } system("pause"); } void Show(vector<Student>& stu) { system("cls"); int n = Read(stu); cout << "=============================== 展示所有学生信息 ==============================" << endl; cout << "学号" << "\t" << "班级" << "\t" << "姓名" << "\t" << "必修课" << "\t" << "选修课" << endl; cout << "-------------------------------------------------------------------------------" << endl; for (int i = 0; i < n; i++) cout << stu[i] << endl; system("pause"); } void Select(vector<Course>& cour, vector<Student>& stu) { system("cls"); int n_cour = Course().Read(cour); int n_stu = Read(stu); int i = 0; // 学生 int j = 0; // 课程 string id_c; // 课程 string id_s; // 学生 cout << "============ 开始选课 ============" << endl; cout << "请输入学生学号: "; cin >> id_s; while (i < n_stu && stu[i]._id != id_s) i++; if (i == n_stu) { cout << "找不到该学生。" << endl; system("pause"); return; } cout << ("请输入想选择的课程编号: "); cin >> id_c; while (j < n_cour && cour[j].c_id() != id_c) j++; if (j == n_cour) { cout << "找不到该课程" << endl; system("pause"); return; } if (cour[j].c_count() >= 60) { cout << "课程人数已达上限,选课失败。" << endl; system("pause"); } else { if (cour[j].c_type()) if (stu[i]._num_compulsory < 2) { int c = 0; while (c < stu[i]._num_compulsory && cour[j].c_id() != stu[i]._cour_compulsory[c].c_id()) c++; if (c < stu[i]._num_compulsory) { cout << "请勿重复选择课程。" << endl; system("pause"); return; } stu[i]._cour_compulsory[stu[i]._num_compulsory] = cour[j]; stu[i]._num_compulsory++; cour[j].c_count()++; Course().Write(cour, n_cour); Write(stu, n_stu); cout << "选课成功。" << endl; system("pause"); } else { cout << "必修课数量已达上限,选课失败。" << endl; system("pause"); } else { if (stu[i]._num_elective < 1) { int c = 0; while (c < stu[i]._num_elective && cour[j].c_id() != stu[i]._cour_elective[c].c_id()) c++; if (c < stu[i]._num_elective) { cout << "请勿重复选择课程。" << endl; system("pause"); return; } stu[i]._cour_elective[stu[i]._num_elective] = cour[j]; stu[i]._num_elective++; cour[j].c_count()++; Course().Write(cour, n_cour); Write(stu, n_stu); cout << "选课成功。" << endl; system("pause"); } else { cout << "选修课数量已达上限,选课失败。" << endl; system("pause"); } } } } void Deselect(vector<Course>& cour, vector<Student>& stu) { system("cls"); int n_cour = Course().Read(cour); int n_stu = Read(stu); int i = 0; // 学生 int j = 0; // 课程 string id_c; // 课程 string id_s; // 学生 cout << "============ 退选 ============" << endl; cout << "请输入学生学号: "; cin >> id_s; while (i < n_stu && stu[i]._id != id_s) i++; if (i == n_stu) { cout << "找不到该学生。" << endl; system("pause"); return; } cout << ("请输入想要退选的课程编号: "); cin >> id_c; while (j < n_cour && cour[j].c_id() != id_c) j++; if (j == n_cour) { cout << "找不到该课程" << endl; system("pause"); return; } if (stu[i]._num_compulsory) { int c = stu[i]._num_compulsory - 1; while (c >= 0) { if (stu[i]._cour_compulsory[c].c_id() == id_c) { cour[j].c_count()--; stu[i]._num_compulsory--; stu[i]._cour_compulsory[c] = Course(); // 重新排序 for (; c < stu[i]._num_compulsory; c++) swap(stu[i]._cour_compulsory[c], stu[i]._cour_compulsory[c + 1]); Write(stu, n_stu); Course().Write(cour, n_cour); cout << "退选成功。" << endl; system("pause"); return; } c--; } if (stu[i]._cour_elective) { int c = stu[i]._num_elective - 1; while (c >= 0) { if (stu[i]._cour_elective[c].c_id() == id_c) { cour[j].c_count()--; stu[i]._num_elective--; stu[i]._cour_elective[c] = Course(); for (; c < stu[i]._num_elective; c++) swap(stu[i]._cour_elective[c], stu[i]._cour_elective[c + 1]); Write(stu, n_stu); Course().Write(cour, n_cour); cout << "退选成功。" << endl; system("pause"); return; } c--; } cout << "你并未选择该课程。" << endl; system("pause"); return; } } if (stu[i]._cour_elective) { int c = stu[i]._num_elective - 1; while (c >= 0) { if (stu[i]._cour_elective[c].c_id() == id_c) { cour[j].c_count()--; stu[i]._num_elective--; stu[i]._cour_elective[c] = Course(); for (; c < stu[i]._num_elective; c++) swap(stu[i]._cour_elective[c], stu[i]._cour_elective[c + 1]); Write(stu, n_stu); Course().Write(cour, n_cour); cout << "退选成功。" << endl; system("pause"); return; } c--; } cout << "你并未选择该课程。" << endl; system("pause"); return; } } private: string _id; // 学号 string _class; // 班级 string _name; // 名字 Course _cour_compulsory[SIZE_COMP]; // 必修课信息 Course _cour_elective[SIZE_ELECT]; // 选修课信息 int _num_compulsory; // 已选必修课数量 int _num_elective; // 已选选修课数量 }; vector<Student> stu; ostream& operator<<(ostream& out, const Student& s) { out << s._id << "\t" << s._class << "\t" << s._name << "\t"; for (int i = 0; i < SIZE_COMP; i++) out << s._cour_compulsory[i]._name << " "; out << "\t"; for (int i = 0; i < SIZE_ELECT; i++) out << s._cour_elective[i]._name << " "; return out; } fstream& operator<<(fstream& fout, const Student& s) { fout << s._id << "\t" << s._class << "\t" << s._name << "\t"; for (int i = 0; i < SIZE_COMP; i++) fout << s._cour_compulsory[i] << "\t"; for (int i = 0; i < SIZE_ELECT; i++) fout << s._cour_elective[i] << "\t"; fout << s._num_compulsory << "\t" << s._num_elective; return fout; } fstream& operator>>(fstream& fin, Student& s) { fin >> s._id >> s._class >> s._name; for (int i = 0; i < SIZE_COMP; i++) fin >> s._cour_compulsory[i]; for (int i = 0; i < SIZE_ELECT; i++) fin >> s._cour_elective[i]; fin >> s._num_compulsory >> s._num_elective; return fin; } // --------------------------------------------------------------------------------------------------// int choose_user() { loop: system("cls"); int c = 0; cout << "=================================================================" << endl; cout << "-------------- 欢迎来到学生选课系统 ---------------" << endl; cout << "请选择你的身份(1管理员 或 2学生)(输入0退出): "; cin >> c; string passwd; if (c == 1) { cout << "请输入密码: "; cin >> passwd; if (passwd == string(PASSWORD)) { flag = 1; cout << "登入成功." << endl; system("pause"); } else { cout << "密码错误." << endl; system("pause"); goto loop; } } else flag = 0; if (c < 0 || c > 2) { 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 << " 0. 返回上级目录 " << endl; cout << "----------------------------------" << endl; cout << "请选择你的操作(0-6): "; cin >> c; switch (c) { case 1: if (flag) Course().Add(cour); else { cout << "request denied." << endl; system("pause"); } break; case 2: if (flag) Course().Delete(cour); else { cout << "request denied." << endl; system("pause"); } break; case 3: if (flag) Course().Modify(cour); else { cout << "request denied." << endl; system("pause"); } break; case 4: Course().Lookup(cour); break; case 5: Course().Show(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 << " 0. 返回 " << endl; cout << "----------------------------------" << endl; cout << "请选择你的操作(0-7): "; cin >> c; switch (c) { case 1: if (flag) Student().Add(stu); else { cout << "request denied." << endl; system("pause"); } break; case 2: if (flag) Student().Delete(stu); else { cout << "request denied." << endl; system("pause"); } break; case 3: if (flag) Student().Modify(stu); else { cout << "request denied." << endl; system("pause"); } break; case 4: Student().Lookup(stu); break; case 5: Student().Show(stu); break; case 6: Student().Select(cour, stu); break; case 7: Student().Deselect(cour, stu); break; case 0: cout << "------------ 返回成功 ------------" << endl; system("pause"); return; default: cout << "请输入 0-7." << 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 << "请选择你的操作(0-2): "; cin >> c; if (c < 0 || c > 2) { cout << "请输入 0-2." << endl; system("pause"); } else break; } return c; } int main() { cour.reserve(100); stu.reserve(100); while (1) { loop: if (!choose_user()) { cout << "=============== 谢谢使用!再见! ===============" << endl; 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; default: cout << "请输入 0-2." << endl; system("pause"); break; } } } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。