C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)

C与C++游戏项目练习10:机房预约系统

之前写接金币小游戏时,我踩了个大雷,居然拿父类的vector容器去装派生子类的实例化对象。
这是会丢东西的,万万要不得的,年轻人不讲武德,我以后得耗子尾汁。

宝书镇楼。
本来按照顺序应该做飞机大战游戏的N.0版本的,但是,这里有一点点小小的知识点需要我先回顾一下查漏补缺~~~
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第1张图片

我主要的错误原因是没给整清楚多态的应用,于是我翻出了我自学C++时在B站看的网课,其中这个机房预约系统的项目中就是多态的典型应用,我决定再把这个项目实现一次,来巩固这方面的知识。

这不是广告
这不是广告
这不是广告
我当时自学C++入门看的是如下这个视频:
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第2张图片
B站传送门:https://www.bilibili.com/video/BV1et411b73Z
多态的体现在于这里:
截图来自老师配套讲义:C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第3张图片
其中,Identity类里面,将显示登录菜单设计为虚函数,让他的三个子类各自用这个函数实现不同的功能:
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第4张图片
正好这块知识点我也比较薄弱,一起复习一下吧:
https://blog.csdn.net/u010802169/article/details/88537490
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第5张图片
”可以在基类中将被重写的成员函数设置为虚函数,其含义是:当通过基类的指针或者引用调用该成员函数时,将根据指针指向的对象类型确定调用的函数,而非指针的类型,如此,便可以将基类与派生类的同名方法区分开,实现多态。“

这位博主总结得太精辟了,可以说是超赞C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第6张图片
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第7张图片
https://www.runoob.com/w3cnote/cpp-virtual-functions.html

”虚就虚在所谓"推迟联编"或者"动态联编"上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被称为"虚"函数。“
虚函数只能借助于指针或者引用来达到多态的效果。"

C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第8张图片
OpenMenu()属于纯虚函数,即在基类中声明的虚函数,没有有意义的实现,具体实现由学生、老师、管理员三个派生类来决定。
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第9张图片
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第10张图片
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第11张图片
错误记录:在做去重操作(检验有无重复的id)的时候,去重的目的一直没有达到,调试发现vStu、vTea两个容器里面都是空的,说明根本没有把现成信息读进去,比对了initVector、checkRepeat、addPerson、几个函数均为发现错误,最后回看视频和讲义发现是在构造函数中忘记调用initVector导致根本没有执行把文件里面的信息读入容器中的操作。
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第12张图片
一些编写程序过程中的其他要点:
1.先写管理类,第二写学生,第三写老师。
管理类Manager要统筹整个系统,必须先实现这个类,才能实现后面比如说添加学生老师账号等操作。
老师的一些操作是要基于学生的动作的(比如审核机房预约),如果不先写好学生类,老师的功能实现也无从谈起。
2.面向对象编程不等于所有方法都必须写在类里
如果我没记错的话,C++兼容所有的C语言知识,有时候如果需要,也可以写全局函数,不一定非得把所有函数都死板地交给某个类实例化对象来调用。
比如这个Login函数,就是全局函数:

void LogIn(string filename, int type)
{
	Identity* person = NULL;

	ifstream ifs;
	ifs.open(filename,ios::in);
	if (!ifs.is_open())
	{
		cout << "文件不存在!" << endl;
		ifs.close();//打开之后的输出流要及时关闭
		system("pause");
		system("cls");
		return;
	}
	int id = 0;
	string name="";
	string pwd="";
	if (type == 1 || type == 2)//学生或者教师有id号
	{
		cout << "请输入您的学号或职工号" << endl;
		cin >> id;
	}
	cout << "请输入用户名:" << endl;
	cin >> name;
	cout << "请输入密码:" << endl;
	cin >> pwd;

	int fId;
	string fName = "";
	string fPwd = ""; 

	if (type == 1)
	{
		//学生登录验证
		while (ifs >> fId && ifs >> fName  && ifs >> fPwd)
		{
			if (id == fId && name == fName && pwd == fPwd)
			{
				cout << "学生登录验证成功!" << endl;
				system("pause");
				system("cls");
				person = new Student(id,name,pwd);
				return;
			}
		}
	}
	else if (type == 2)
	{
		//老师登录验证
		while (ifs >> fId && ifs >> fName && ifs >> fPwd)
		{
			if (id == fId && name == fName && pwd == fPwd)
			{
				cout << "教师验证登录成功!" << endl;
				system("pause");
				system("cls");
				person = new Teacher(id, name, pwd);
				return;
			}
		}
	}
	else if (type == 3)
	{
		//管理员登录验证
		while (ifs >> fName && ifs >> fPwd)
		{
			if (name == fName && pwd == fPwd)
			{
				cout << "管理员验证登录成功!" << endl;
				system("pause");
				system("cls");
				person = new Manager(name, pwd);
				ManagerMenu(person);
				return;
			}
		}
	}
	cout << "验证登录失败!" << endl;
	system("pause");
	system("cls");
	return;
}

还有这个管理员菜单ManagerMenu:

void ManagerMenu(Identity *&manager)
{
	while (true)
	{
		manager->OpenMenu();//父类指针调用子类管理员子菜单

		Manager* man = (Manager*)manager;//强制转换未子类对象,方便调用子类增加的其他接口

		int select = 0;
		cin >> select;
		if (select == 1)//添加账号
		{
			//cout << "添加账号"<< endl;
			man->addPerson();
		}
		else if (select == 2) //查看账号
		{
			//cout << "查看账号" << endl;
			man->showPerson();
		}
		else if (select == 3) //查看机房
		{
			//cout << "查看机房" << endl;
			man->showComputer();
		}
		else if (select == 4) //清空预约
		{
			//cout << "清空预约" << endl;
			man->cleanFile();
		}
		else
		{
			delete manager;
			//cout << "注销成功" << endl;
			system("pause");
			system("cls");
			return;
		}
	}
	
}

3.发现这个参数长得有一点点奇怪:
在这里插入图片描述
https://www.matools.com/blog/190528998
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第13张图片
Identity作为一个整体,表示参数类型是指针,student传进来的实参是一个Identity类的实例person,所以这里相当于是传了指针的引用给指针类型的参数?
person的定义
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第14张图片
4.这个程序的层级关系
第一遍学C++入门的时候还是云里雾里的,今天终于搞明白了点他这么多函数的层级关系是咋回事了。

1.Login最上层。确定登录的身份是管理员、学生还是老师。
2.确定了之后,父类身份多态调用ManagerMenu、StudentMenu或者TeacherMenu
3.在子类菜单界面选择子类特有的功能,比如查看预约,查看机房等

5.map容器的使用
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第15张图片
这个容器使用得很巧妙,内部嵌套了一个map容器,内部的map通过冒号前后的内容区分索引和键值,例如(date:周一,date是索引,周一是键值),外部的map又通过记录条数和记录内容来作为索引和键值,比如(第一条是索引,内容是第一条里面记载的date周几,interval上午下午,room机房号数)
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第16张图片
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第17张图片
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第18张图片
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第19张图片
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第20张图片
6.string字符串转换为C语言字符串再与int类型做比较
C与C++游戏项目练习10:机房预约系统(内有虚函数相关知识)_第21张图片

**

全代码展示

:**有一说一老师的代码框架是写的真的好,让我现在自己设计是真不OK

机房预约系统.cpp 所有代码总控

#include
#include"Identity.h"
#include"globalFile.h"
#include
#include
#include"Student.h"
#include"Teacher.h"
#include"Manager.h"
using namespace std;

void TeacherMenu(Identity* &teacher)
{
	while (true)//只有注销登录才会退出
	{
		teacher->OpenMenu();
		Teacher* tea = (Teacher*)teacher;//便于调用Teacher类其他函数
		int select = 0;
		cin >> select;
		if (select == 1)
		{
			//查看所有预约
			tea->showAllOrder();
		}
		else if (select == 2)
		{
			//审核预约
			tea->validOrder();
		}
		else
		{
			delete teacher;
			cout << "注销成功" << endl;
			system("pause");
			system("cls");
			return;
		}
	}
}

void ManagerMenu(Identity* &manager)
{
	while (true)
	{
		manager->OpenMenu();//父类指针调用子类管理员子菜单

		Manager* man = (Manager*)manager;//强制转换未子类对象,方便调用子类增加的其他接口

		int select = 0;
		cin >> select;
		if (select == 1)//添加账号
		{
			//cout << "添加账号"<< endl;
			man->addPerson();
		}
		else if (select == 2) //查看账号
		{
			//cout << "查看账号" << endl;
			man->showPerson();
		}
		else if (select == 3) //查看机房
		{
			//cout << "查看机房" << endl;
			man->showComputer();
		}
		else if (select == 4) //清空预约
		{
			//cout << "清空预约" << endl;
			man->cleanFile();
		}
		else
		{
			delete manager;
			//cout << "注销成功" << endl;
			system("pause");
			system("cls");
			return;
		}
	}
	
}

void StudentMenu(Identity* &student)
{
	while (true)
	{
		//学生菜单
		student->OpenMenu();//多态,此刻student是父类Identity的指针,调用的是Student类的菜单
		Student* stu = (Student*)student;//转换为Student类型,便于调用子类衍生出的更多功能的函数
		int select = 0;
		cin >> select;
		if (select == 1)//申请预约
		{
			stu->applyOrder();
		}
		else if (select == 2)//查看自身预约
		{
			stu->showMyOrder();
		}
		else if (select == 3)//查看所有预约
		{
			stu->showAllOrder();
		}
		else if (select = 4)//取消预约
		{
			stu->cancelOrder();
		}
		else
		{
			delete student;
			cout << "注销成功!" << endl;
			system("pause");
			system("cls");
		}
	}
}

void LogIn(string filename, int type)
{
	Identity* person = NULL;

	ifstream ifs;
	ifs.open(filename,ios::in);
	if (!ifs.is_open())
	{
		cout << "文件不存在!" << endl;
		ifs.close();//打开之后的输出流要及时关闭
		system("pause");
		system("cls");
		return;
	}
	int id = 0;
	string name="";
	string pwd="";
	if (type == 1 || type == 2)//学生或者教师有id号
	{
		cout << "请输入您的学号或职工号" << endl;
		cin >> id;
	}
	cout << "请输入用户名:" << endl;
	cin >> name;
	cout << "请输入密码:" << endl;
	cin >> pwd;

	int fId;
	string fName = "";
	string fPwd = ""; 

	if (type == 1)
	{
		//学生登录验证
		while (ifs >> fId && ifs >> fName  && ifs >> fPwd)
		{
			if (id == fId && name == fName && pwd == fPwd)
			{
				cout << "学生登录验证成功!" << endl;
				system("pause");
				system("cls");
				person = new Student(id,name,pwd);
				StudentMenu(person);
				return;
			}
		}
	}
	else if (type == 2)
	{
		//老师登录验证
		while (ifs >> fId && ifs >> fName && ifs >> fPwd)
		{
			if (id == fId && name == fName && pwd == fPwd)
			{
				cout << "教师验证登录成功!" << endl;
				system("pause");
				system("cls");
				person = new Teacher(id, name, pwd);
				TeacherMenu(person);
				return;
			}
		}
	}
	else if (type == 3)
	{
		//管理员登录验证
		while (ifs >> fName && ifs >> fPwd)
		{
			if (name == fName && pwd == fPwd)
			{
				cout << "管理员验证登录成功!" << endl;
				system("pause");
				system("cls");
				person = new Manager(name, pwd);
				ManagerMenu(person);
				return;
			}
		}
	}
	cout << "验证登录失败!" << endl;
	system("pause");
	system("cls");
	return;
}
int main()
{
	int select = 0;
	while (true)
	{
		cout << "======================  欢迎来到传智播客机房预约系统  =====================" << endl;
		cout << endl << "请输入您的身份" << 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|          0.退    出           |\n";
		cout << "\t\t|                               |\n";
		cout << "\t\t -------------------------------\n";
		cout << "请输入您的选择: ";
		cin >> select;//接受用户选择
		switch (select)
		{
		case 1://学生登录
			LogIn(STUDENT_FILE, select);
			break;
		case 2://教师登录
			LogIn(TEACHER_FILE, select);
			break;
		case 3://管理员登录
			LogIn(ADMIN_FILE, select);
			break;
		case 0://退出系统
			cout << "欢迎下次使用!" << endl;
			system("pause");
			return 0;
			break;
		default:
			cout << "输入有误,请重新选择!" << endl;
			system("pause");
			system("cls");
			break;
		}
	}
	system("pause");
	return 0;
}

**管理者类:**Manager.h

#pragma once
#include
#include"Identity.h"
#include
#include"Student.h"
#include"Teacher.h"
#include"computerRoom.h"

using namespace std;
class Manager : public Identity
{
public:
	Manager();//默认构造

	Manager(string name,string pwd);//有参构造  管理员姓名,密码

	virtual void OpenMenu();//选择菜单

	void addPerson();//添加账号  

	void showPerson();//查看账号

	void showComputer();//查看机房信息

	void cleanFile();//清空预约记录

	void InitVector();//初始化容器

	bool checkRepeat(int id, int type);//检测重复 参数:(传入id,传入类型) 返回值:(true 代表有重复,false代表没有重复)

	vector<Student> vStu;

	vector<Teacher> vTea;

	vector<computerRoom> vCom;

};

Manager.cpp

#include"Manager.h"
#include
#include"globalFile.h"
#include"Student.h"
#include"Teacher.h"
#include
#include
Manager::Manager()//默认构造
{

}

Manager::Manager(string name, string pwd)//有参构造  管理员姓名,密码
{
	this->m_Name = name;
	this->m_Pwd = pwd;
	this->InitVector();

	ifstream ifs;
	ifs.open(COMPUTER_FILE, ios::in);
	computerRoom com;
	while (ifs >> com.m_Comid && ifs >> com.m_MaxNum)
	{
		vCom.push_back(com);
	}
	ifs.close();
	cout << "机房的数量为:" << vCom.size() << endl;
}

void Manager::OpenMenu()//选择菜单
{
	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;
}

void Manager::addPerson()//添加账号  
{

	string fileName = "";
	string tip = "";
	ofstream ofs;
	string errorTip = "";//重复错误提示
	int select = 0;
	do
	{
		cout << "请输入添加账号的类型" << endl;
		cout << "1、添加学生" << endl;
		cout << "2、添加老师" << endl;
		cin >> select;
		if (select == 1)
		{
			fileName = STUDENT_FILE;
			tip = "请输入学号: ";
			errorTip = "学号重复,请重新输入";
			break;
		}
		else if (select == 2)
		{
			fileName = TEACHER_FILE;
			tip = "请输入职工编号:";
			errorTip = "职工号重复,请重新输入";
			break;
		}
		cout << "输入有误,请重新输入。" << endl;
	} while (select != 1 && select != 2);

	ofs.open(fileName, ios::out | ios::app);//以追加的方式写入文件
	int id;
	string name = "";
	string pwd = "";
	cout << tip << endl;
	while (true)
	{
		cin >> id;
		bool ret = this->checkRepeat(id,select);//根据参数判断新加的是老师还是学生
		if (ret == true)
		{
			cout << errorTip << endl;
			
		}
		else//表示id没重复
		{
			break;
		}
	}
	
	cout << "请输入姓名: " << endl;
	cin >> name;

	cout << "请输入密码: " << endl;
	cin >> pwd;

	ofs << id << " " << name << " " << pwd << endl;//写入文件
	cout << "添加成功!" << endl;

	system("pause");
	system("cls");
	ofs.close();
	this->InitVector();//添加完一个新的学生之后马上初始化容器,免得本次添加的两个学号重复而无法识别
	return;
}

void printStudent(Student &s)
{
	cout << "学号:" << s.m_Id << " 姓名:" << s.m_Name << " 密码:" << s.m_Pwd << endl;
}

void printTeacher(Teacher& t)
{
	cout << "职工号:" << t.m_EmpId << " 姓名:" <<t.m_Name << " 密码:" << t.m_Pwd << endl;
}

void Manager::showPerson()//查看账号
{
	cout << "请选择查看内容:" << endl;
	cout << "1、查看所有学生" << endl;
	cout << "2、查看所有老师" << endl;

	int select = 0;
	cin >> select;
	if (select == 1)
	{
		for_each(vStu.begin(), vStu.end(), printStudent);//注意此处的写法
	}
	else
	{
		for_each(vTea.begin(), vTea.end(), printTeacher);//注意此处的写法
	}
}

void Manager::showComputer()//查看机房信息(因为机房在此项目中不是重点操作对象,所以只需要查看就行了)
{
	cout << "机房信息如下:" << endl;
	for (vector<computerRoom>::iterator it = vCom.begin(); it != vCom.end(); it++)
	{
		cout << "机房编号: " << it->m_Comid << "	机房最大容量: " << it->m_MaxNum << endl;
	}
	system("pause");
	system("cls");
}

void Manager::cleanFile()//清空预约记录
{
	ofstream ofs;
	ofs.open(ORDER_FILE, ios::trunc);//清除文件重新打开,相当于清空文件了
	ofs.close();
	cout << "文件已清空!" << endl;
	system("pause");
	system("cls");
}

void Manager::InitVector()//初始化容器//* 去除重复的账号,首先要先将学生和教师的账号信息获取到程序中,方可检测
{
	//一定要加上作用域
	//*在manager.h中,添加两个容器,用于存放学生和教师的信息
	ifstream ifs;
	//读取学生文件中信息
	ifs.open(STUDENT_FILE, ios::in);
	if (!ifs.is_open())
	{
		cout << "文件读取失败!" << endl;
		system("pause");
		system("cls");
		return ;
	}

	vStu.clear();
	vTea.clear();
	
	string fname = "";
	string fpwd = "";
	int id;

	Student s;
	while (ifs >> s.m_Id && ifs >> s.m_Name && ifs >> s.m_Pwd)
	{
		vStu.push_back(s);
	}
	cout << "当前学生数量为: " << vStu.size() << endl;
	ifs.close(); //学生初始化

	//读取老师文件信息
	ifs.open(TEACHER_FILE, ios::in);

	Teacher t;
	while (ifs >> t.m_EmpId && ifs >> t.m_Name && ifs >> t.m_Pwd)
	{
		vTea.push_back(t);
	}
	cout << "当前教师数量为: " << vTea.size() << endl;

	ifs.close();
}

bool Manager::checkRepeat(int id, int type)
{
	if (type == 1)
	{
		for (vector<Student>::iterator it = vStu.begin(); it != vStu.end(); it++)
		{
			if (it->m_Id == id)
			{
				return  true;
			}
		}
	}
	else
	{
		for (vector<Teacher>::iterator it = vTea.begin(); it != vTea.end(); it++)
		{
			if (it->m_EmpId == id)
			{
				return true;
			}
		}
	}
	return false;
	
}

**学生类:**Student.h

#pragma once
#include
#include"Identity.h"
#include
#include"computerRoom.h"
using namespace std;

class Student : public Identity
{
public:
	Student();//默认构造

	Student(int id,string name,string pwd);//有参构造(学号、姓名、密码)

	virtual void OpenMenu();//菜单界面

	void applyOrder();//申请预约

	void showMyOrder();//查看我的预约

	void showAllOrder();//查看所有预约

	void cancelOrder();//取消预约

	int m_Id;//学生学号

	vector<computerRoom> vCom;
};

Student.cpp

#include"Student.h"
#include"globalFile.h"
#include
#include"orderFile.h"
#include
//注意作用域放在函数名之前,不是返回值类型之前

Student::Student()//默认构造
{

}

Student::Student(int id, string name, string pwd)//有参构造(学号、姓名、密码)
{
	this->m_Id = id;
	this->m_Name = name;
	this->m_Pwd = pwd;
	ifstream  ifs;
	ifs.open(COMPUTER_FILE, ios::in);
	computerRoom com;
	while (ifs >> com.m_Comid && ifs >> com.m_MaxNum)
	{
		vCom.push_back(com);
	}
	ifs.close();

}

void Student::OpenMenu()//菜单界面
{
	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;
}

void Student::applyOrder()//申请预约
{
	
	int date = 0;//机房多久开
	do
	{
		cout << "机房开放时间为周一至周五!" << endl;
		cout << "请输入申请预约的时间:" << endl;
		cout << "1、周一" << endl;
		cout << "2、周二" << endl;
		cout << "3、周三" << endl;
		cout << "4、周四" << endl;
		cout << "5、周五" << endl;
		cin >> date;
		if (date >= 1 && date <= 5)
		{
			break;
		}
		else
		{
			cout << "输入有误,请重新输入" << endl;
		}
	} while (true);
	int interval = 0;//上午/下午
	do
	{
		cout << "请输入申请预约的时间段:" << endl;
		cout << "1、上午" << endl;
		cout << "2、下午" << endl;
		cin >> interval;
		if (interval == 1 || interval == 2)
		{
			break;
		}
		else
		{
			cout << "输入有误,请重新输入" << endl;
		}
	} while (true);
	int  room = 0;//机房号码
	do
	{
		cout << "请选择机房:" << endl;
		cout << "1号机房容量:" << vCom[0].m_MaxNum << endl;
		cout << "2号机房容量:" << vCom[1].m_MaxNum << endl;
		cout << "3号机房容量:" << vCom[2].m_MaxNum << endl;
		cin >> room;
		if (room >= 1 && room <= 3)
		{
			break;
		}
		else
		{
			cout << "输入有误,请重新输入" << endl;
		}
	} while (true);
	cout << "预约成功!审核中····" << endl;
	ofstream ofs;
	ofs.open(ORDER_FILE, ios::app);//以追加的方式写入文件
	ofs << "date:" << date << " ";
	ofs << "interval:" << interval << " ";
	ofs << "stuId:" << this->m_Id << " ";
	ofs << "stuName:" << this->m_Name << " ";
	ofs << "roomId:" << room << " ";
	ofs << "status:" << 1 << endl;
	ofs.close();
	system("pause");
	system("cls");
}

void Student::showMyOrder()//查看我的预约
{
	OrderFile of;
	if (of.m_Size == 0)
	{
		cout << "无预约记录" << endl;
		system("pause");
		system("cls");
		return;
	}
	for (int i = 0; i < of.m_Size; i++)
	{
		if (this->m_Id == atoi(of.m_orderdata[i]["stuId"].c_str()))
		{
			cout << "预约日期:周" << of.m_orderdata[i]["date"]<<" ";
			cout << "时段:" << (of.m_orderdata[i]["interval"] == "1" ? "上午":"下午")<<" ";
			cout << "机房:" << of.m_orderdata[i]["roomId"]<<" ";
			string status = " 状态: ";  // 0 取消的预约   1 审核中   2 已预约 -1 预约失败
			if (of.m_orderdata[i]["status"] == "1") 
			{
				status += "审核中";
			}
			else if (of.m_orderdata[i]["status"] == "2")
			{
				status += "预约成功";
			}
			else if (of.m_orderdata[i]["status"] == "-1")
			{
				status += "审核未通过,预约失败";
			}
			else
			{
				status += "预约已取消";
			}
			cout << status << endl;
		}
	}
	system("pause");
	system("cls");
}

void Student::showAllOrder()//查看所有预约
{
	OrderFile of;
	if (of.m_Size == 0)
	{
		cout << "无预约记录" << endl;
		system("pause");
		system("cls");
		return;
	}
	for (int i = 0; i < of.m_Size; i++)
	{
		cout << i + 1 << "、 ";

		cout << "预约日期: 周" << of.m_orderdata[i]["date"];
		cout << " 时段:" << (of.m_orderdata[i]["interval"] == "1" ? "上午" : "下午");
		cout << " 学号:" << of.m_orderdata[i]["stuId"];
		cout << " 姓名:" << of.m_orderdata[i]["stuName"];
		cout << " 机房:" << of.m_orderdata[i]["roomId"];
		string status = " 状态: ";  // 0 取消的预约   1 审核中   2 已预约 -1 预约失败
		if (of.m_orderdata[i]["status"] == "1")
		{
			status += "审核中";
		}
		else if (of.m_orderdata[i]["status"] == "2")
		{
			status += "预约成功";
		}
		else if (of.m_orderdata[i]["status"] == "-1")
		{
			status += "审核未通过,预约失败";
		}
		else
		{
			status += "预约已取消";
		}
		cout << status << endl;
	}
	system("pause");
	system("cls");
}

void Student::cancelOrder()//取消预约
{
	OrderFile of;
	if (of.m_Size == 0)
	{
		cout << "无预约记录" << endl;
		system("pause");
		system("cls");
		return;
	}
	cout << "审核中或预约成功的记录可以取消,请输入取消的记录" << endl;
	int index = 0;
	vector<int> v;
	for (int i = 0; i < of.m_Size; i++)
	{
		if (this->m_Id == atoi(of.m_orderdata[i]["stuId"].c_str()))//学号匹配
		{
			if (of.m_orderdata[i]["status"] == "1" || of.m_orderdata[i]["status"] == "2")//状态匹配,只有审核中或者预约成功的记录可以取消
			{
				v.push_back(i);//把当前记录是在总文件中的第几条写入容器
				cout << index++ << " 、";
				cout << "预约时间:周" << of.m_orderdata[i]["date"] << " ";
				cout << (of.m_orderdata[i]["interval"] == "1" ? "上午" : "下午") << " ";
				cout << " 机房:" << of.m_orderdata[i]["roomId"];
				string status = " 状态: ";  // 0 取消的预约   1 审核中   2 已预约  -1 预约失败
				if (of.m_orderdata[i]["status"] == "1")
				{
					status += "审核中";
				}
				else if (of.m_orderdata[i]["status"] == "2")
				{
					status += "预约成功";
				}
				cout << status << endl;

			}
		}
	}
	cout << "请输入取消的记录,0代表返回" << endl;
	int select = 0;
	while (true)
	{	
		cin >> select;
		if (select >= 0 && select <= v.size())
		{
			if (select == 0)//退出取消预约
			{
				break;
			}
			else
			{
				of.m_orderdata[v[select - 1]]["status"] = "0";//select-1找到v容器的下标,这个下标对应的数据存放的是在所有数据中的预约条数
				of.updateOrder();//把更新之后的数据写入文件
				cout << "已取消预约" << endl;
				break;
			}
		}
		cout << "输入有误,请重新输入" << endl;
	}
	system("pause");
	system("cls");
}

教师类:Teacher.h

#pragma once
#include
#include"Identity.h"
#include
#include"orderFile.h"
using namespace std;

class Teacher : public Identity
{
public:
	Teacher();//默认构造

	Teacher(int empId,string name,string pwd);//有参构造 (职工编号,姓名,密码)

	virtual void OpenMenu();//菜单界面

	void showAllOrder();//查看所有预约

	void validOrder();//审核预约

	int m_EmpId;//教师编号
};

Teacher.cpp

#include"Teacher.h"

Teacher::Teacher()//默认构造
{

}

Teacher::Teacher(int empId, string name, string pwd)//有参构造 (职工编号,姓名,密码)
{
	this->m_EmpId = empId;
	this->m_Name = name;
	this->m_Pwd = pwd;
}

void Teacher::OpenMenu()//菜单界面
{
	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|          0.注销登录              |\n";
	cout << "\t\t|                                  |\n";
	cout << "\t\t ----------------------------------\n";
	cout << "请选择您的操作: " << endl;
}

void Teacher::showAllOrder()//查看所有预约
{
	OrderFile of;
	if (of.m_Size == 0)
	{
		cout << "无预约记录" << endl;
		system("pause");
		system("cls");
		return;
	}
	for (int i = 0; i < of.m_Size; i++)
	{
		cout << i + 1 << "、 ";

		cout << "预约日期: 周" << of.m_orderdata[i]["date"];
		cout << " 时段:" << (of.m_orderdata[i]["interval"] == "1" ? "上午" : "下午");
		cout << " 学号:" << of.m_orderdata[i]["stuId"];
		cout << " 姓名:" << of.m_orderdata[i]["stuName"];
		cout << " 机房:" << of.m_orderdata[i]["roomId"];
		string status = " 状态: ";  // 0 取消的预约   1 审核中   2 已预约 -1 预约失败
		if (of.m_orderdata[i]["status"] == "1")
		{
			status += "审核中";
		}
		else if (of.m_orderdata[i]["status"] == "2")
		{
			status += "预约成功";
		}
		else if (of.m_orderdata[i]["status"] == "-1")
		{
			status += "审核未通过,预约失败";
		}
		else
		{
			status += "预约已取消";
		}
		cout << status << endl;
	}
	system("pause");
	system("cls");
}

void Teacher::validOrder()//审核预约
{
	OrderFile of;
	if (of.m_Size == 0)
	{
		cout << "无预约记录" << endl;
		system("pause");
		system("cls");
		return;
	}
	vector<int> v;
	int index = 0;
	cout << "待审核的预约记录如下:" << endl;
	for (int i = 0; i < of.m_Size; i++)
	{
		if (of.m_orderdata[i]["status"] == "1")
		{
			v.push_back(i);
			cout << ++index << "、 ";
			cout << "预约日期: 周" << of.m_orderdata[i]["date"];
			cout << " 时段:" << (of.m_orderdata[i]["interval"] == "1" ? "上午" : "下午");
			cout << " 机房:" << of.m_orderdata[i]["roomId"];
			string status = " 状态: 审核中";  // 0取消的预约   审核中1    2 已预约  -1 预约失败
			cout << status << endl;
		}
	}
	cout << "请输入审核的预约记录,0代表返回" << endl;
	int select = 0;//接受用户选择
	int ret = 0;//接受预约结果,是否通过
	while (true)
	{
		cin >> select;
		if (select >= 0 && select <= v.size())
		{
			if (select == 0)
			{
				break;
			}
			else
			{
				cout << "请输入审核结果" << endl;
				cout << "1、通过" << endl;
				cout << "2、不通过" << endl;
				cin >> ret;
				if (ret == 1)
				{
					of.m_orderdata[v[select - 1]]["status"] = "2";
				}
				else
				{
					of.m_orderdata[v[select - 1]]["status"] = "-1";
				}
				of.updateOrder();
				cout << "审核完毕!" << endl;
				break;
			}
		}
		cout << "输入有误,请重新输入" << endl;
	}
	system("pause");
	system("cls");
}

机房类:computerRoom.h

#pragma once
#include
using namespace std;
class computerRoom
{
public:
	int m_Comid;//机房编号
	int m_MaxNum;//机房最大容量
};

computerRoom.cpp
空实现(因为本课重点是三个用户身份的操作实现,对机房属性的要求相对弱化,所以没怎么做关于机房的功能)

预约类OrderFile.h

#pragma once
#include
#include"globalFile.h"
#include
#include
using namespace std;

class OrderFile
{
public:
	OrderFile();
	void updateOrder();
	int  m_Size;
	map<int, map<string, string >> m_orderdata;//key记录条数,value具体记录键值对应信息
};

OrderFile.cpp

#include"orderFile.h"
#include
OrderFile::OrderFile()
{
	ifstream ifs;
	ifs.open(ORDER_FILE, ios::in);
	string date = ""; //日期
	string interval = "";//时间段
	string stuId = "";//学生编号
	string stuName = "";//学生姓名
	string roomId = "";//机房编号
	string status = "";//预约状态
	this->m_Size = 0;//记录预约人数
	while (ifs >> date && ifs >> interval && ifs >> stuId && ifs >> stuName && ifs >> roomId && ifs >> status)
	{
		string key = "";
		string value = "";
		map<string, string> m;
		int pos = date.find(":");
		if (pos != -1)
		{
			key = date.substr(0, pos);
			value = date.substr(pos + 1, date.size() - pos - 1);//万能公式 
			m.insert(make_pair(key, value));
		}

		pos = interval.find(":");
		if (pos != -1)
		{
			key = interval.substr(0, pos);
			value = interval.substr(pos + 1, interval.size() - pos - 1);//万能公式 
			m.insert(make_pair(key, value));
		}

		pos = stuId.find(":");
		if (pos != -1)
		{
			key = stuId.substr(0, pos);
			value = stuId.substr(pos + 1, stuId.size() - pos - 1);//万能公式 
			m.insert(make_pair(key, value));
		}

		pos = stuName.find(":");
		if (pos != -1)
		{
			key = stuName.substr(0, pos);
			value = stuName.substr(pos + 1, stuName.size() - pos - 1);//万能公式 
			m.insert(make_pair(key, value));
		}

		pos = roomId.find(":");
		if (pos != -1)
		{
			key = roomId.substr(0, pos);
			value = roomId.substr(pos + 1, roomId.size() - pos - 1);//万能公式 
			m.insert(make_pair(key, value));
		}

		pos = status.find(":");
		if (pos != -1)
		{
			key = status.substr(0, pos);
			value = status.substr(pos + 1, status.size() - pos - 1);//万能公式 
			m.insert(make_pair(key, value));
		}
		m_orderdata.emplace(make_pair(this->m_Size, m));//记录条数和该条记录的所有内容配对为外部map的一个值
		this->m_Size++;
	}

	ifs.close();
}

void OrderFile::updateOrder()
{
	if (this->m_Size == 0)
	{
		return;
	}
	ofstream ofs;
	ofs.open(ORDER_FILE, ios::out|ios::trunc);
	for (int i = 0; i < m_Size; i++)
	{
		ofs << "date:" << this->m_orderdata[i]["date"] << " ";
		ofs << "interval:" << this->m_orderdata[i]["interval"] << " ";
		ofs << "stuId:" << this->m_orderdata[i]["stuId"] << " ";
		ofs << "stuName:" << this->m_orderdata[i]["stuName"] << " ";
		ofs << "roomId:" << this->m_orderdata[i]["roomId"] << " ";
		ofs << "status:" << this->m_orderdata[i]["status"] << endl;
	}
	ofs.close();
}

三个用户身份的基类Identity.h

#pragma once
#include
using namespace std;
class Identity//身份抽象类
{
public:
	string m_Name;//用户名
	string m_Pwd;//密码

	virtual void OpenMenu() = 0;//操作菜单,纯虚函数,此类为抽象类,不能实例化对象,也不需要.cpp文件实现
};

储存所有文件别名globalFile.h

#pragma once//不同的身份可能会用到不同的文件操作,我们可以将所有的文件名定义到一个全局的文件中,注意要把文件放在跟头文件和源文件同级目录里
//管理员文件
#define ADMIN_FILE     "admin.txt"
//学生文件
#define STUDENT_FILE   "student.txt"
//教师文件
#define TEACHER_FILE   "teacher.txt"
//机房信息文件
#define COMPUTER_FILE  "computerRoom.txt"
//订单文件
#define ORDER_FILE     "order.txt"

项目源码也会上传至本人个人空间,欢迎提取,有任何不足之处烦请各位大神批评指正~

感谢您能看到这里,一起努力成为更好的自己~~~

你可能感兴趣的:(C与C++游戏开发练习)