8、 学生模块
8.1 学生子菜单、登录和注销
实现步骤:
- 在Student.cpp的有参构造函数中,初始化学生信息
- 在Student.cpp中,实现成员函数
void Student::operMenu()
,显示学生子菜单界面 - 在机房预约系统.cpp中,当用户登录的是学生,添加学生菜单接口,添加全局函数
void studentMenu(Identity * &manager)
- 在机房预约系统.cpp的studentMenu函数中,将学生功能框架搭建起来,不同的分支提供出来:
- 申请预约
- 查看我的预约
- 查看所有预约
- 取消预约
- 注销登录
- 在机房预约系统.cpp的studentMenu函数中,实现注销功能
- 在机房预约系统.cpp的LoginIn函数中,学生成功登录后,调用学生的子菜单界面,实现接口对接。
Student.cpp 初始化学生属性 代码展示:
//有参构造(学号、姓名、密码)
Student::Student(int id, string name, string pwd)
{
//初始化属性
this->m_Id = id;
this->m_Name = name;
this->m_Pwd = pwd;
}
//菜单界面
void Student::operMenu()
{
cout << "欢迎学生代表:" << this->m_Name << "登录!" << endl;
cout << "\t\t ----------------------------------\n";
cout << "\t\t| |\n";
cout << "\t\t| 1.申请预约 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 2.查看我的预约 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 3.查看所有预约 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 4.取消预约 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 0.注销登录 |\n";
cout << "\t\t| |\n";
cout << "\t\t ----------------------------------\n";
cout << "请选择您的操作: " << endl;
}
机房预约系统.cpp studentMenu函数 学生子菜单框架 代码展示:
这部分和管理员的子菜单类似,不赘诉
//全局函数 进入学生子菜单界面
void studentMenu(Identity*& student)
{
while (1)
{
//调用子菜单
student->openMenu();
//将父类指针转为子类指针,调用子类的其他接口
Student* stu = (Student*)student;
//接收用户选择功能
int select = 0;
cin >> select;
switch (select)
{
case 1://申请预约
cout << "申请预约" << endl;
stu->applyOrder();
break;
case 2://查看自身预约
cout << "查看自身预约" << endl;
stu->showmyOrder();
break;
case 3://查看所有预约
cout << "查看所有预约" << endl;
stu->showallOrder();
break;
case 4://取消预约
cout << "取消预约" << endl;
stu->cancleOrder();
break;
default://默认情况下注销登录 释放堆区数据
delete stu;//释放堆区数据 手动开辟手动释放
cout << "注销成功!" << endl;
system("pause");
system("cls");
return;
}
}
}
机房预约系统.cpp LoginIn函数 接口对接 代码位置:
登录验证通过:
学生子菜单和注销登录:
8.2 申请预约
8.2.1 获取机房信息
实现步骤:
- 在申请预约时,学生需要看到机房信息进行预约,因此需要让学生获取到机房信息,故在Student.h中添加新的成员函数,
vector<ComputerRoom> vCom;
- 在Student.cpp的有参构造函数中,读取机房信息。打开机房信息文件后,逐行读取信息,再存入vCom。
Student.h
//机房容器
vector<ComputerRoom> vCom;
Student.cpp 有参构造函数 代码展示
//有参构造(学号、姓名、密码)
Student::Student(int id, string name, string password)
{
this->m_Id = id;
this->m_Name = name;
this->m_Password = password;
//初始化机房信息 读取信息
ifstream ifs;
ifs.open(COMPUTER_FILE, ios::in);
ComputerRoom com;
while (ifs >> com.m_ComId && ifs >> com.m_MaxNum)
{
vCom.push_back(com);//读到的信息存在vector容器中
}
ifs.close();
}
8.2.2 预约功能实现
实现步骤:
- 在student.cpp中实现成员函数
void Student::applyOrder()
,这部分分为预约信息输入和预约信息写入。 - 预约信息包括预约日期、预约时间段、预约机房编号;预约信息写入时,包括预约的日期、时间段、学生学号、学生姓名、机房编号、机房状态,默认机房状态都在审核中。
- 预约日期/时间段/机房时,提示用户选择预约的日期/时间段/机房并输入,通过死循环控制用户是否输入正确。
- 最后提示用户预约成功,再进行预约信息写入。
- 预约信息写入时,每一行包括约的日期、时间段、学生学号、学生姓名、机房编号、机房状态
student.cpp 申请预约 代码展示:
//申请预约
void Student::applyOrder()
{
int n = 15;
int data = 0;//接收预约日期变量
cout << string(n, '*') << " 机房开放时间为周一至周五! " << string(n, '*') << endl;
cout << string(n, ' ') << " 请输入申请预约的时间: " << string(n, ' ') << endl;
cout << string(n, ' ') << " 1—— 周一 " << string(n, ' ') << endl;
cout << string(n, ' ') << " 2—— 周二 " << string(n, ' ') << endl;
cout << string(n, ' ') << " 3—— 周三 " << string(n, ' ') << endl;
cout << string(n, ' ') << " 4—— 周四 " << string(n, ' ') << endl;
cout << string(n, ' ') << " 5—— 周五 " << string(n, ' ') << endl;
//cout << "请输入申请预约的时间:" << endl;
//cout << "1—— 周一" << endl;
//cout << "2—— 周二" << endl;
//cout << "3—— 周三" << endl;
//cout << "4—— 周四" << endl;
//cout << "5—— 周五" << endl;1
//预约日期输入判断
while (true)
{
cin >> data;
if (1 <= data <= 5)//输入正确
{
break;
}
cout << "输入有误,请重新输入!" << endl;
}
int period = 0;//接收预约时间段变量
cout << string(n, '-') << " 请输入申请预约的时间段: " << string(n, '-') << endl;
cout << string(16, ' ') << "1—— 上午" << string(n, ' ') << endl;
cout << string(16, ' ') << "2—— 下午" << string(n, ' ') << endl;
while (true)
{
cin >> period;
if (period == 1 || period == 2)
{
break;
}
cout << "输入有误,请重新输入!" << endl;
}
int room = 0;//接收预约机房编号变量
cout << string(n, '-') << " 请输入申请预约的机房: " << string(n, '-') << endl;
for (vector<ComputerRoom>::iterator it = vCom.begin(); it != vCom.end(); it++)
{
cout << string(16, ' ') << "机房编号为:" << it->m_ComId << "\t机房容量为:" << it->m_MaxNum << endl;
}
/*for (int i = 0; i < vCom.size(); i++)
{
cout << "机房编号为:" << vCom[i].m_ComId << "\t机房容量为:" << vCom[i].m_MaxNum << endl;
}*/
while (true)
{
cin >> room;
if (1 <= room <= 3)
{
break;
}
cout << "输入有误,请重新输入!" << endl;
}
cout << string(n, '*') << " 预约成功,审核中! " << string(n, '*') << endl;
//预约信息写入
ofstream ofs;
ofs.open(ORDER_FILE, ios::app);
ofs << "data:" << data << " ";
ofs << "period:" << period << " ";
ofs << "stuID:" << this->m_Id << " ";
ofs << "stuName:" << this->m_Name << " ";
ofs << "roomID:" << room << " ";
ofs << "status:" << 1 << " " << endl;
ofs.close();
system("pause");
system("cls");
}
测试效果:
在order.txt文件中生成如下内容:
8.3 显示预约
8.3.1 创建预约类-预约信息解析
功能描述: 显示预约记录时,需要从order.txt文件中获取到所有预约记录并显示。因此,创建预约类来管理预约记录以及更新预约的状态。
实现过程与代码:
- 在头文件以及源文件下分别创建orderFile.h 和 orderFile.cpp文件
- 在orderFile.h文件中,包括构造函数、更新预约记录函数、记录预约信息的容器、记录预约条数
- 更新预约记录函数中,主要是更新机房的预约状态,包括审核中、通过、未通过、取消预约
- 记录预约条数则是维护了order.txt文件中有多少条预约信息
- 记录预约信息的容器,一个map嵌套map容器,解释如图示:
- 在orderFile.cpp中,写OrderFile()构造函数的具体实现-读取信息部分
- 读取order.txt预约文件信息,创建接收文件中预约信息的变量,通过逐段读取并测试是否读取成功。
- 测试前,在Student.h中包含OrderFile.h文件,
#include "orderFile.h"
- 在Student.cpp的查看自身预约函数 showmyOrder()中创建对象,调用orderFile的构造函数
- 在orderFile.cpp中,写OrderFile()构造函数的具体实现-截取信息部分
- 创建接收小容器,即
map<string, string> m;
,以及临时接受key和value值的string变量。虽然除了姓名是字符串,其他信息都是数字,但是为了方便,统一用string类型来接收key和value。
- 每一键值对都是用冒号: 隔开,因此用find查找冒号: 的位置,冒号: 前是小容器map的key,冒号: 后是小容器map的value,find返回值是冒号: 的位置,用一个int类型变量pos接收。要注意,截取key和value前要对pos进行检测。
- 每一键值对的key和value可以用substr来截取,具体如下:
- 对于key,substr截取的长度是0到pos;
- 对于value的起始位置,应该是冒号: 的下一个位置,即pos+1,substr截取的长度从pos+1开始;
- 对于value的结束位置,应该是冒号: 的全部信息,这个长度可以间接获取。统计整段要截取的长度,再减去冒号前的长度,就是所求长度了。具体而言,以stuName:Bella为例,stuName:Bella的长度是
stuName.size()
,stuName: 的长度可以用pos表示,那么Bella的长度是stuName.size() - pos - 1
。 - 上面这个例子也很好地说明了,为什么value的截取不能是pos+1到pos+2了。如果仅是pos+2作为结尾位置,只能截取姓名的第一个字符,而不是完整字符,而且只适用于目前记录的日期、时间段、学号、机房号、状态这些信息的截取。另外,如果日期、时间段、学号、机房号、状态这些信息不是只用一个数字表示的话,pos+2也不适用了。(不知道表诉清楚没)
- 每一键值对的key和value都截取后,放进小容器m中。由于这部分是重复的代码,我封装成函数了subdata(),注意这个函数是有两个返回值的,用到pair类型。
- 在orderFile.h写声明
pair<string, string> subdata(string data);
,在orderFile.cpp写实现,并测试。要注意函数的类型是pair<string, string> subdata(string data);
,因为截取完后,key和value都要存入小容器m中。 - 所有信息截取完后,小容器m嵌套在大容器中,并且预约条数要更新,小容器m要释放,下一条记录
- 最后关闭文件,并对大容器的内容测试。
orderFile.h 完整代码展示
#pragma once
#include<iostream>
using namespace std;
using std::pair;
#include <map>
#include "globalFile.h"
#include <fstream>
#include <algorithm>
class orderFile
{
public:
//构造函数
orderFile();
//更新预约机房状态函数
void updateOrder();
//记录预约信息容器 key记录条数 value记录具体键值对信息 没有重复情况
map<int, map<string, string>> m_order;
//记录预约条数
int m_Size;
//截取小容器key 和 value
pair<string, string> subdata(string data);
};
OrderFile.cpp 构造函数 截取函数 完整代码展示
#include "orderFile.h"
//构造函数
orderFile::orderFile()
{
ifstream ifs(ORDER_FILE, ios::in);
//接收预约文件各信息变量
string date;
string period;
string stuID;
string stuName;
string roomID;
string status;
this->m_Size = 0;//初始化为0
while ( ifs >> date && ifs >> period && ifs >> stuID
&& ifs >> stuName && ifs >> roomID && ifs >> status)
{
//测试
/*cout << data << endl;
cout << period << endl;
cout << stuID << endl;
cout << stuName << endl;
cout << roomID << endl;
cout << status << endl;*/
map<string, string> m;
//截取日期
/*
//截取key value值并存入map小容器中 统一用string
string key;
string value;
map<string, string> m;
//截取日期
int pos = data.find(':', 0);
key = data.substr(0, pos);
value = data.substr(pos + 1, data.size() - pos - 1);
m.insert(make_pair(key, value));
*/
m.insert(subdata(date));
//截取时间段
m.insert(subdata(period));
//截取学生学号
m.insert(subdata(stuID));
//截取学生姓名
m.insert(subdata(stuName));
//截取机房号
m.insert(subdata(roomID));
//截取机房预约状态
m.insert(subdata(status));
//放进大容器中
m_order.insert(make_pair(this->m_Size, m));
//更新
this->m_Size++;
m.clear();//释放 存放下一条预约记录
}
ifs.close();
//测试
/*for (map<int, map<string, string>>::iterator it = m_order.begin(); it != m_order.end(); it++)
{
cout << "条数为:" << it->first << "\tvalue如下:" << endl;
for (map<string, string>::iterator mit = it->second.begin(); mit != it->second.end(); mit++)
{
cout << "key = " << mit->first << "\tvalue = " << mit->second << endl;
}
cout << endl << endl;
}*/
}
//截取小容器key 和 value
pair<string, string> orderFile::subdata(string data)
{
string key;
string value;
map<string, string> m;
int pos = data.find(':');
if (pos != -1)
{
key = data.substr(0, pos);
value = data.substr(pos + 1, data.size() - pos - 1);
m.insert(make_pair(key, value));
}
return make_pair(key, value);
//测试
/*cout << "key = " << key << endl;
cout << "value = " << value << endl;*/
}
小容器测试 截取每一键值对的key和value测试
读取信息测试: 看是否与order.txt信息对应上
大容器内容测试: 看是否正确存入预约信息
8.3.2 创建预约类-预约信息更新
功能描述: 更新所有预约信息,[]访问数据,这是一个map容器嵌套map容器
//更新预约机房状态函数
void orderFile::updateOrder()
{
if (this->m_Size == 0)
{
cout << "没有预约记录!" << endl;
return;
}
ofstream ofs(ORDER_FILE, ios::out | ios::trunc);
for (int i = 0; i < this->m_Size; i++)
{
cout << i + 1 << "、" << endl;
ofs << "date:" << this->m_order[i]["date"] << " ";
ofs << "period:" << this->m_order[i]["period"] << " ";
ofs << "stuID:" << this->m_order[i]["stuID"] << " ";
ofs << "stuName:" << this->m_order[i]["stuName"] << " ";
ofs << "roomID:" << this->m_order[i]["roomID"] << " ";
ofs << "status:" << this->m_order[i]["status"] << endl;
}
ofs.close();
}
解释:
- 首先,要对文件预约信息条数进行判断:
- 如果没有预约记录直接返回,对预约记录文件进行删除重建,
- 如果有预约记录,再重新写入预约记录
- 对存放预约记录的容器m_order的内容重新写入
其中,this->m_order[i]
表示第i条预约信息,这是一个map容器嵌套map容器。this->m_order[i]
底层还是一个map,可以通过[]访问,通过key直接索引value
8.3.2 显示自身预约
实现步骤:
- 首先我们先添加几条预约记录,可以用程序添加或者直接修改order.txt文件。
- 文件预约信息条数进行判断,如果没有预约记录直接返回。
- 如果有预约记录,根据学号找到自身的预约记录,并输出打印
- 在Student.cpp的showMyOrder()写具体代码实现
Student.cpp 代码展示
//查看自身预约
void Student::showmyOrder()
{
orderFile order;
if (order.m_Size == 0)
{
cout << "没有预约记录!" << endl;
system("pause");
system("cls");
return;
}
//对比学号
for (int i = 0; i < order.m_Size; i++)
{
//找到自身预约 并显示
if (this->m_Id == atoi(order.m_order[i]["stuID"].c_str()))
{
cout << "预约日期:周" << order.m_order[i]["date"];
cout << "预约时间段:" << (order.m_order[i]["period"] == "1" ? "上午" : "下午");
cout << "\t机房号:" << order.m_order[i]["roomID"];
string status = "\t状态:";
if (order.m_order[i]["status"] == "1")
{
status += "审核中";
}
else if (order.m_order[i]["status"] == "2")
{
status += "预约成功";
}
else if (order.m_order[i]["status"] == "-1")
{
status += "预约失败,审核未通过";
}
else
{
status += "预约已取消";
}
cout << status << endl;
}
}
system("pause");
system("cls");
}
注意点:
order.m_order[i]["stuID"]
,表示第i条预约记录的学生学号,这是一个string类型的数据,而自身学号是一个int类型,需要做数据类型转换才可以进行学号比较,从而找到自身预约记录。
- 先用
.c_str()
转成c语言风格的字符串const char *
再用atoi
转成int类型,atoi返回的是int类型,即atoi(order.m_order[i]["stuID"].c_str()
测试前,先添加预约信息,如下:
8.3.3 显示所有预约
- 只要遍历order.m_order容器,输出预约信息即可
- 遍历前需要对order.m_Size进行判断,如果没有预约记录,直接返回
- 如果有预约记录,在Student.cpp的
void Student::showAllOrder()
成员函数写具体实现
//查看所有预约
void Student::showallOrder()
{
orderFile order;
if (order.m_Size == 0)
{
cout << "没有预约记录!" << endl;
system("pause");
system("cls");
return;
}
for (int i = 0; i < order.m_Size; i++)
{
cout << "\n第" << i + 1 << "条预约记录:";
cout << "预约日期:周" << order.m_order[i]["date"];
cout << "预约时间段:" << (order.m_order[i]["period"] == "1" ? "上午" : "下午");
cout << "\t预约学生学号:" << order.m_order[i]["stuID"];
cout << "\t预约学生姓名:" << order.m_order[i]["stuName"];
cout << "\t机房号:" << order.m_order[i]["roomID"];
string status = "\t状态:";
if (order.m_order[i]["status"] == "1")
{
status += "审核中";
}
else if (order.m_order[i]["status"] == "2")
{
status += "预约成功";
}
else if (order.m_order[i]["status"] == "-1")
{
status += "预约失败,审核未通过";
}
else
{
status += "预约已取消";
}
cout << status << endl;
}
system("pause");
system("cls");
}
测试效果如图:
8.4 取消预约
实现步骤:
- 取消预约记录前,需要对order.m_Size进行判断,看是否有预约记录,如果没有预约记录,直接返回
- 如果有预约记录,在Student.cpp的
void Student::cancelOrder()
成员函数写具体实现 - 这块分两部分,第一个是对预约记录文件进行解析,读取预约记录文件的信息;第二部分是对预约记录文件进行更新,对审核中或预约成功的预约记录进行取消。
- 预约记录文件解析时,首先判断是否有预约记录,如果没有预约记录,直接返回
- 预约记录文件更新时,找到该学生所有预约记录,通过学号索引,再找到预约状态是审核中或预约成功的记录,进行取消。
- 取消部分理解的话,老师审核预约也很好理解了,都是一样的,只是操作对象不一样而已。
Student.cpp
//取消预约
void Student::cancleOrder()
{
orderFile order;
if (order.m_Size == 0)
{
cout << "没有预约记录!" << endl;
system("pause");
system("cls");
return;
}
cout << "审核中或预约成功的记录可以取消,请输入取消的记录" << endl;
int index = 1;//记录该学生有多少条预约记录
vector<int> v;//存放该学生符合取消条件的预约记录
//找到要取消预约的学生 以及该学生可以取消的预约记录
for (int i = 0; i < order.m_Size; i++)
{
//找到要取消预约的学生 string→const char *→int
if (atoi(order.m_order[i]["stuID"].c_str()) == this->m_Id)
{
//找到符合取消的预约记录 审核中1 预约成功2
if (order.m_order[i]["status"] == "1" || order.m_order[i]["status"] == "2")
{
//保存可以取消的预约记录的真实下标,对应m_order的key
v.push_back(i);
//展示该学生预约的所有记录 从1开始遍历 输出index 再+1
cout << index++ << "、 ";//有可能张三的记录在第一个、第二个、第四个
cout << "预约日期:周" << order.m_order[i]["date"];
cout << "预约时间段:" << (order.m_order[i]["period"] == "1" ? "上午" : "下午");
cout << "\t机房号:" << order.m_order[i]["roomID"];
string status = "\t状态:";
if (order.m_order[i]["status"] == "1")
{
status += "审核中";
}
else if (order.m_order[i]["status"] == "2")
{
status += "预约成功";
}
cout << status << endl;
}
}
}
//取消预约
cout << "请输入要取消的预约记录,0代表返回" << endl;
int select = 0;
while (true)
{
cin >> select;
//select范围:0-所有符合取消条件的预约记录的个数
if (select >= 0 && select <= v.size())
{
if (select == 0)
{
break;
}
else
{
order.m_order[v[select - 1]]["status"] = "0";
order.updateOrder();
cout << "已取消预约" << endl;
break;
}
}
else
{
cout << "输入有误,请重新输入" << endl;
}
}
system("pause");
system("cls");
}
取消预约代码思路解释:
一、找到预约记录:
如图所示,假设order.m_order容器中存放了四条记录,张三的有三条,要取消最后一条记录,也就是在order.m_order容器中删除最后一条记录。那么,怎么删除最后一条呢?进一步说,怎么获取最后一条记录的下标?
- 首先,通过遍历order.m_order容器,要找到张三和张三所有可以取消的预约记录,通过学号和预约状态可以找到,
atoi(order.m_order[i]["stuID"].c_str()) == this->m_Id
,找到张三,这里的类型转变前面讲过,不赘诉order.m_order[i]["status"] == "1" || order.m_order[i]["status"] == "2"
,找到张三所有可以取消的预约记录
- 在order.m_order容器中的第0、1、3记录是张三的且可以取消,这几条记录需要展示给张三看,让他选择取消取消哪一条记录。
- 因此,可以用一个int变量index来维护,记录张三可以取消预约记录的顺序。
- 遍历容器时
for (int i = 0; i < order.m_Size; i++)
,index随 i 变化,即index++ 。 - 此时,预约记录的顺序是index,分别为1、2、3。
- 另外,后面张三输入取消预约记录的选择select,也只能从index的表示的这三条预约记录中选择。select表示张三的取消预约记录的选择。
- 那么如何找到这个预约记录在order.m_order容器中的真实下标呢?也就是怎么找到该在order.m_order容器中的key值?并且如何保存呢?
- 其实,在遍历容器order.m_order时,i 就是符合条件的预约记录在容器的key值。
vector<int> v
存放的是张三可以取消的预约记录的真实下标,即对应order.m_order中的key。 - 在index++随 i 变化时,index表示符合要求的预约记录的顺序,i表示符合要求的预约记录的真实下标。通过vector容器保存该记录在order.m_order容器中的key值。即容器v维护的不是index,而是i值,即预约信息在order.m_order容器中的key值。
- 为什么不用index来找预约记录呢?如果通过index去索引order.m_order容器的预约记录,找到的并不是张三要取消预约的记录。比如index=2时,
order.m_order[index]
找到的是李四的预约记录。因此容器v保存的是张三要取消预约记录的真实下标,即i,也即order.m_order容器中的key。 - 具体做法:for循环遍历容器order.m_order,遍历预约记录(index也同步变化,index++)时,每找到一条张三可以取消的预约记录,就保存该预约记录在order.m_order容器的key值,
v.push_back(i)
。
二、预约记录怎么和用户的输入关联?
前面提到,index和select是对应的,即index是1、2、3,那么用户的选择select也只能是1、2、3。并且v中保存了对应预约记录的真实下标。找到预约记录的真实下标后,怎么和用户的选择联系起来呢?如图:
- 首先,这三条可以取消的记录1、2、3,在v容器中是0、1、2,在order.m_order容器的下标是0、1、3 。
- 那么要取消的最后一条记录,首先是3-1,即
select-1
,表示v下标,通过下标找到v中保存的信息,也就是找到记录的真实下标。即v[select - 1]
,表示通过select-1
索引到v中保存的该记录的真实下标,即该记录对应在order.m_order容器的key - 再进一步通过key索引order.m_order容器保存的记录,即order.m_order[v[select - 1]]
- 再者,要取消第二条记录 应该是2-1,找到v中的下标,再进一步索引order.m_order容器中这个下标对应的记录
- 要删除的记录是用户选择输入的,用一个变量来接收select ,范围是0-index,即1、2、3
- 具体做法,通过输入的值select,找到v存放的取消记录的真实下标v[select-1],对应order.m_order容器的key值。索引到order.m_order容器存放的记录order.m_order[v[select-1]],再通过字段找到预约状态,并设置为-1,即
order.m_order[v[select - 1]]["status"] = "0";
。最后更新容器order.m_order,并提示用户。
变量说明
m_order[i]---------------------------第i条记录
i------------------------------------对应m_order容器中的key,第i条记录的真实下标
index--------------------------------对应第i条记录的顺序,从1开始,index++,随着i变化
select-------------------------------对应学生选择的可以取消的预约记录的顺序,[0, index]范围
m_order[i]["status"]=="1" / "2"-----状态为审核中/预约成功的第i条记录
v.push_back(i);----------------------存 状态为审核中/预约成功的第i条记录的 真实下标,m_order中key值
v[select - 1]------------------------对应存放在v容器中 学生选择的 顺序为select-1 预约记录的真实下标,m_order中key值
m_order[v[select - 1]]["status"]-----对应学生选择的 顺序为select-1 的预约记录的 预约状态
测试取消预约前-order.txt:
测试取消预约前-张三预约记录:
测试取消预约显示:
测试取消预约后-order.txt:
测试取消预约后-张三预约记录:
至此,学生模块功能全部实现