(一)需求和规格说明
问题描述:在高校的教学改革中,有很多学校实行了本科生导师制。一个班级的学生被分给几个老师,每个老师带领 n 个学生,如果老师还带研究生,那么研究生也可直接负责本科生。
本科生导师制问题中的数据元素具有如下形式:
⑴ 导师带研究生:(老师,((研究生 1,(本科生 1, …, 本科生 m)), … ))
⑵ 导师不带研究生: (老师,(本科生 1, …, 本科生 m))
导师的自然情况只包括姓名、职称;
研究生的自然情况只包括姓名、班级;
本科生的自然情况只包括姓名、班级。
编程任务:
- 插入:将某位本科生或研究生插入到广义表的相应位置;
- 删除:将某本科生或研究生从广义表中删除;
- 查询:查询导师、本科生(研究生)的情况;
- 统计:某导师带了多少个研究生和本科生;
- 输出:将某导师所带学生情况输出。
(二)设计
1.设计思想
本题的设计思想是利用广义表来实现对学生、导师和研究生的管理和操作。广义表是一种特殊的链表,它允许在链表的任意位置插入或删除元素,并支持快速查询、统计和输出。
具体来说,本题将学生、导师和研究生的信息存储在一个广义表中,每个节点包含一个标签(如“老师”、“本科生”或“研究生”)和一个子节点列表。通过插入、删除、查询等操作,可以灵活地管理这些信息。同时,通过统计函数和输出函数,可以方便地获取某导师带了多少个研究生和本科生以及他们的情况。
这种设计思想的优点在于:
1. 灵活性:广义表可以在链表的任意位置插入或删除元素,因此可以方便地添加、删除或修改学生、导师和研究生的信息。
2. 查询效率:由于广义表支持快速查询,因此可以高效地获取某个导师的学生情况。
3. 统计功能:通过统计函数,可以方便地获取某导师带了多少个研究生和本科生以及他们的情况。
总之,本题的设计思想是利用广义表来实现对学生、导师和研究生的管理和操作,以提高系统的灵活性、查询效率和统计功能。
2. 设计表示
- 结点结构:
结构体名称 | 成员数据类型 | 成员名 | 描述 |
Undergraduate | string | name | 存储的本科生的名字 |
string | class | 储存的本科生的班级 | |
string | help | 储存的本科生的研究生助教名字(没有助教为“no”) | |
Graduate | string | name | 储存的研究生名字 |
string | class | 储存的研究生班级 |
- 类:
类名 | 成员类别 | 类型 | 成员名 | 描述 |
Teacher | 函数 | void | Create(string name,string title) | 对Teacher类中一部分数据初始化 |
void | insertGraduate() | 插入研究生键盘键入数据) | ||
void | insertUndergraduate() | 插入本科生(键盘键入数据) | ||
void | deleteStudent() | 删除学生(键盘键入数据) | ||
void | queryTeacher() | 查询导师信息 | ||
void | queryGraduate() | 查询研究生信息(键盘键入数据) | ||
void | queryUndergraduate() | 查询本科生信息(键盘键入数据) | ||
void | countStudents() | 统计学生数量 | ||
void | printStudents() | 输出学生信息 | ||
数据 | string | name | 导师姓名 | |
string | title | 导师职称 | ||
vector | studnets | 一个包含本科生和研究生的容器 |
注:上面容器为:vector<pair<Graduate,Undergraduate>>
- 函数:
数据类型 | 函数名称 | 描述 |
int | systems() | 显示主菜单 |
3.实现注释
该代码实现了一个导师类,包括创建、插入研究生和本科生、删除学生、查询导师信息、查询研究生信息、查询本科生信息、统计学生数量和输出学生信息等功能。在完成基本要求的基础上,还实现了对研究生和本科生的分别插入和删除操作,并且只用一个容器数组就完成的数据的储存,优化了占用空间。
4. 详细设计表示
以上代码的详细设计表示如下:
1. 创建一个导师类,包含以下属性和成员函数接口:
- name:导师姓名;
- title:导师职称;
- create(string name, string title):构造函数,初始化name和title属性;
- insertGraduate():插入研究生成员函数,向学生列表中添加一个新的研究生元素;
- insertUndergraduate():插入本科生成员函数,向学生列表中添加一个新的本科生元素;
- deleteStudent():删除学生成员函数,从学生列表中移除指定的学生元素;
- queryTeacher():查询导师信息成员函数,输出导师姓名和职称信息;
- queryGraduate():查询研究生信息成员函数,遍历学生列表并输出研究生姓名和班级信息;
- queryUndergraduate():查询本科生信息成员函数,遍历学生列表并输出本科生姓名和班级信息;
- printStudents():输出学生信息成员函数,遍历学生列表并输出所有学生的姓名、班级和是否为研究生的信息。
- countStudents():统计学生数量成员函数,遍历学生列表并计算研究生数量和本科生数量。
- students:存储所有学生的二维数组对象。
2. 创建一个systems()函数当成主菜单,通过这个主菜单来调用Teacher类中的各个函数,并且每次调用该函数时进行清屏。
3. 在主函数中调用系统循环,根据用户输入选择不同的操作进行执行,并在每次执行完毕后输出结果。
(三)用户手册
程序运行显示输入导师的名字和职称,输入完成后将清屏并跳转到主菜单界面。
选择要调用的功能并从键盘输入功能前的序号(int)按回车键提交进入相应函数,屏幕上将出现结果或根据提示输入相应信息后输出结果,出现结果后按下任意键将跳回主界面,键入数字0-8。
选择输入1后,根据输出提示从键盘输入本科生的名字(string)和班级(string)按回车键提交,然后按照提示从键盘输入功能前的序号(int),并按回车键提交。如提交功能1则直接将该本科生插入在导师下,若提交功能2则还需根据提示从键盘输入要插入的研究生名字,如果输入的研究生名字不存在则跳出提示“研究生不存在”并跳回主菜单,需要重新操作。如果输入的研究生存在则将本科生插入在该研究生下。输入sting类字符和数字1或2。
选择输入2后,根据输出提示从键盘输入研究生的名字(string)和班级(string)按回车键提交,输入提交后将该研究生插入到导师下并自动跳回主菜单,键入string类字符。
选择输入3后,根据提示从键盘输入要删除的学生名字(string),并按回车键提交,如果输入的学生存在则将该学生从广义表中删除并提示“删除成功”并自动跳回主菜单,如果输入的学生不存在则输出“学生不存在”并自动跳回主菜单,键入string类字符。
选择输入4后,系统将在屏幕上输出研究生和本科生相应的数量,然后自动退回到主菜单。
选择输入5后,系统将在屏幕上输出导师的名字和职称,然后自动退回到主菜单。
选择输入6后,根据提示从键盘输入要查询的研究生名字(string),并按回车键提交,如果输入的学生存在则将该研究生的名字和班级从屏幕输出并自动跳回主菜单,如果输入的学生不存在则输出“学生不存在”并自动跳回主菜单,键入string类字符。
选择输入7后,根据提示从键盘输入要查询的本科生名字(string),并按回车键提交,如果输入的学生存在则将该本科生的名字和班级从屏幕输出并自动跳回主菜单,如果输入的学生不存在则输出“学生不存在”并自动跳回主菜单,键入string类字符。
选择输入8后,系统将在屏幕上输出导师名字和职称,并将所有研究生及该研究生负责的本科生输出,最后输出那些没有研究生负责的本科生。
选择输入0后,系统退出。
(四)调试及测试
1. 测试数据:
2.源代码:
- #include <iostream>
- #include <vector>
- #include <string>
- using namespace std;
- // 研究生结构体
- struct Graduate {
- string name;
- string clazz;
- };
- // 本科生结构体
- struct Undergraduate {
- string name;
- string clazz;
- string help;
- };
- // 导师类
- class Teacher {
- public:
- // 构造函数
- Teacher() {
- }
- void create(string name,string title) {
- this->name = name;
- this->title = title;
- }
- // 插入研究生
- void insertGraduate() {
- cout << "输入名字和班级" << endl;
- string name;
- string clazz;
- cin >> name >> clazz;
- Graduate graduate = { name, clazz };
- students.push_back({ graduate, {} });
- }
- // 插入本科生
- void insertUndergraduate() {
- int z;
- string s_name;
- string name;
- string clazz;
- cout << "输入名字和班级" << endl;
- cin >> name >> clazz;
- cout << "1.插入在导师下2.插入在某研究生中" << endl;
- cin >> z;
- string i_name = "no";
- Undergraduate undergraduate;
- if (z == 2) {
- cout << "输入该研究生名字" << endl;
- cin >> s_name;
- for (auto is = students.begin(); is != students.end(); is++) {
- if (is->first.name == s_name) {
- i_name = s_name;
- undergraduate = { name, clazz,i_name};
- continue;
- }
- }
- if (i_name!= s_name) {
- cout << "该研究生不存在,请重新输入" << endl;
- system("pause");
- return;
- }
- }
- else{ undergraduate = { name, clazz,"no" };
- }
- students.push_back({ {}, undergraduate });
- }
- // 删除学生
- void deleteStudent() {
- cout << "删除学生名字" << endl;
- string name;
- cin >> name;
- auto it = students.begin();
- for (; it != students.end(); it++) {
- if (it->first.name == name) {
- students.erase(it);
- return;
- }
- if (it->second.name == name) {
- students.erase(it);
- return;
- }
- }
- if (it == students.end()) {
- cout << "没有该学生请重新输入" << endl;
- system("pause");
- }
- }
- // 查询导师信息
- void queryTeacher() {
- cout << "姓名:" << name << endl;
- cout << "职称:" << title << endl;
- system("pause");
- }
- // 查询研究生信息
- void queryGraduate() {
- cout << "输入查询学生名字" << endl;
- string name;
- cin >> name;
- for (auto it = students.begin(); it != students.end(); it++) {
- if (it->first.name == name) {
- cout << "姓名:" << it->first.name << endl << "班级:" << it->first.clazz << endl;
- system("pause");
- return;
- }
- }
- cout << "未找到该研究生" << endl;
- system("pause");
- }
- // 查询本科生信息
- void queryUndergraduate() {
- cout << "输入查询学生名字" << endl;
- string name;
- cin >> name;
- for (auto it = students.begin(); it != students.end(); it++) {
- if (it->second.name == name) {
- cout << "姓名:" << it->second.name << endl;
- cout << "班级:" << it->second.clazz << endl;
- system("pause");
- return;
- }
- }
- cout << "未找到该本科生" << endl;
- system("pause");
- }
- // 统计学生数量
- void countStudents() {
- int graduateCount = 0;
- int undergraduateCount = 0;
- for (auto it = students.begin(); it != students.end(); it++) {
- if (it->first.name != "")graduateCount++;
- if (it->second.name != "")
- undergraduateCount++;
- }
- cout << "研究生数量:" << graduateCount << endl;
- cout << "本科生数量:" << undergraduateCount << endl;
- system("pause");
- }
- // 输出学生信息
- void printStudents() {
- cout << "导师:" << name << endl;
- for (auto it = students.begin(); it != students.end(); it++) {
- if (it->first.name != "") {
- cout << "研究生:" << it->first.name << " ";
- cout << "班级:" << it->first.clazz << endl;
- for (auto its = students.begin(); its != students.end(); its++) {
- if ((its->second.help == it->first.name) ) {
- cout << "本科生:" << its->second.name << " ";
- cout << "班级:" << its->second.clazz << endl;
- }
- }
- }
- }
- for (auto it = students.begin(); it != students.end(); it++) {
- if (it->second.help == "no") {
- cout << "本科生:" << it->second.name << " ";
- cout << "班级:" << it->second.clazz << endl;
- }
- }
- system("pause");
- }
- private:
- string name;
- string title;
- vector<pair<Graduate, Undergraduate>> students;
- };
- Teacher teacher;
- int systems() {
- 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;
- int x = 0;
- cin >> x;
- switch (x)
- {
- case 2:
- teacher.insertGraduate();
- return 1;
- break;
- case 1:
- teacher.insertUndergraduate();
- return 1;
- break;
- case 3:
- teacher.deleteStudent();
- return 1;
- break;
- case 4:
- teacher.countStudents();
- break;
- case 5:
- teacher.queryTeacher();
- return 1;
- break;
- case 6:
- teacher.queryGraduate();
- return 1;
- break;
- case 7:
- teacher.queryUndergraduate();
- return 1;
- break;
- case 8:
- teacher.printStudents();
- return 1;
- case 0:
- return 0;
- break;
- default:
- break;
- }
- }
- int main() { // 创建导师对象
- cout << "输入该导师名字与职称" << endl;
- string sm;
- string sz;
- cin >> sm >> sz;
- teacher.create(sm, sz);
- for (int i = 1; i > 0;) {
- i = systems();
- }
- system("pause");
- return 0;
- }