需求分析
学校有一些规模不同的机房,制作机房预约系统
1、身份简介
分别有三种身份使用该程序,三种身份有各自的功能:
学生:申请预约机房、查看自身的预约、查看所有的预约、取消自身的预约、注销登录 ;
学生的属性:学号、姓名、登录密码。
教师:查看所有预约、审核预约(审核通过或不通过)、注销登录;
教师的属性:职工编号、姓名、登陆密码。
管理员:添加账号(添加老师或学生的账号)、查看账号(查看教师和学生的所有信息)、查看机房信息、清空所有预约记录、注销登录;
管理员的属性:姓名、密码。
2、申请事项
申请的订单由管理员每周负责清空;
学生可以预约未来一周内机房的使用,预约的日期为周一至周五,预约时需要选择预约时段(上午、下午);
教师来审核预约,依据实际情况审核预约通过或不通过。
3、系统操作流程
首先进入登录界面,选择登录身份:学生、教师、管理员
选择1:进入学生子菜单界面; 选择2:进入教师子菜单界面;
选择3:进入管理员子菜单界面; 选择0:退出系统
选择身份后,输入学号/职工编号、姓名、密码登录。输入正确则进入相应子菜单界面,输入错误则重新输入。
进入子菜单界面后可以选择各项功能,如选择0、注销登录,则退出当前账号,返回初始菜单界面。
系统框架搭建
1、文本文件
此预约系统有5个txt文本文件,用于存储数据信息,由程序读写。分别为:student.txt(存储学生学号、姓名、密码);teacher.txt(存储教师职工编号、姓名、密码);admin.txt(存储管理员姓名、密码);computerRoom.txt(存储机房编号、容量大小);order.txt(存储预约信息,包括:预约日期、时段、机房编号、学号、姓名、预约状态)。
其中,student.txt和teacher.txt中内容都由管理员类Manager的成员函数:void addPerson()(添加账号函数)写入。
admin.txt和computerRoom.txt的内容仅供程序调用,不由程序写入,由使用者手动添加。
order.txt可由学生类Student的成员函数:void applyOrder()(申请预约)写入,由void cancelOrder()(取消预约)改变其中记录的预约状态;教师类Teacher的成员函数:void validOrder()(审核预约)也可改变其记录的预约状态。
//管理员文件
#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"
2、创建类
学生、教师、管理员三种身份拥有类似的功能(显示子菜单界面)和属性(姓名、登陆密码),所以创建基类Identity;三个身份又有各自不同的属性和功能,所以分别创建学生类、教师类、管理员类,继承基类。
其中的容器都用于和文本文件进行数据读取。在创建对象执行构造函数时,就从文本文件中读取相关信息,存放在容器中。若其他功能函数需要使用文本文件的数据,无需再打开文件进行读取,直接调用容器即可。
//身份抽象类
class Identity
{
public:
virtual void operMenu() = 0; //纯虚函数:显示子菜单
string m_Name; //用户名
string m_Pwd; //密码
};
//学生类
class Student:public Identity
{
public:
//默认构造函数
Student();
//有参构造函数(学号、姓名、密码)
Student(int id, string name, string pwd);
//菜单界面
virtual void operMenu();
//申请预约
void applyOrder();
//查看我的预约
void showMyOrder();
//查看所有预约
void showAllOrder();
//取消预约
void cancelOrder();
//学生学号
int m_Id;
//机房容器,用于存放机房信息
vector<ComputerRoom>vCom;
};
//教师类
class Teacher :public Identity
{
public:
//默认构造函数
Teacher();
//有参构造函数(职工编号、姓名、密码)
Teacher(int EmpId, string name, string pwd);
//菜单界面
virtual void operMenu();
//查看所有预约
void showAllOrder();
//审核预约
void validOrder();
//教师编号
int m_EmpId;
};
class Manager :public Identity
{
public:
//默认构造函数
Manager();
//有参构造函数(职工编号、姓名、密码)
Manager(string name, string pwd);
//菜单界面
virtual void operMenu();
//添加账号
void addPerson();
//查看账号
void showPerson();
//查看机房信息
void showComputer();
//清空预约记录
void cleanFile();
//初始化容器
void initVector();
//检测重复参数:(传入id,传入类型)返回值:(true代表有重复,false代表无重复)
bool checkRepeat(int id,int type);
//学生容器,用于存放学生账号信息
vector<Student> vStu;
//教师容器,用于存放教师账号信息
vector<Teacher> vTea;
//机房容器,用于存放机房信息
vector<ComputerRoom>vCom;
};
此外,由于对预约记录的处理比较复杂,所以创建类OrderFile,便于和order.txt交换信息。
class OrderFile
{
public:
//构造函数,把order.txt的内容读取到m_OrderData容器中
OrderFile();
//更新预约记录,把m_OrderData容器中的内容写入order.txt
void updateOrder();
//记录的容器 key---记录的条数 value---具体记录的键值对信息
map<int, map<string, string>>m_OrderData;
//预约记录条数
int m_size;
};
3、系统操作流程
控制系统流程的主要函数在main.cpp中实现。
int main()
{
int select = 0;//用于接收用户的选择
while (1)
{
cout << "===================欢迎来到机房预约系统===================" << endl;
cout << endl;
cout << "请输入您的身份" << 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://学生身份
LoginIn(STUDENT_FILE, 1);
break;
case 2://老师身份
LoginIn(TEACHER_FILE, 2);
break;
case 3://管理员身份
LoginIn(ADMIN_FILE, 3);
break;
case 0://退出系统
cout << "欢迎下次使用" << endl;
system("pause");
return 0;
break;
default:
cout << "输入错误,请重新选择" << endl;
system("pause");
system("cls");
break;
}
}
}
main函数重复执行一段关于初始菜单界面的程序。首先显示主菜单,用户选择身份后调用LoginIn函数,向该函数传递不同的身份信息。LoginIn函数实现登录功能,两个形参分别表示导入哪个身份的文本文件,和正在登录的用户身份类型。
例如,若是学生登录,则打开student.txt,读取里面的学号、姓名、密码信息,检测是否与用户输入的信息一致。若一致则创建指向Student类对象的基类指针,同时程序会自动实现Student的构造函数,向容器中写入信息,然后调用学生子菜单函数。
//登录功能 参数1:操作的文件名称 参数2:操作的身份的类型
void LoginIn(string fileName, int type)
{
//父类指针,用于指向子类对象
Identity* Person = NULL;
//读文件
ifstream ifs;
ifs.open(fileName, ios::in);
//判断文件是否存在
if (!ifs.is_open())
{
cout << "文件不存在" << endl;
ifs.close();
return;
}
//准备接收用户的信息
int id=0;
string name;
string pwd;
//判断身份
if (type == 1) //学生身份
{
cout << "请输入您的学号" << endl;
cin >> id;
}
else if (type == 2)
{
cout << "请输入您的职工号" << endl;
cin >> id;
}
cout << "请输入用户名" << endl;
cin >> name;
cout << "请输入密码" << endl;
cin >> pwd;
if(type==1)
{
//学生身份验证
int fId; //从文件中获取的id号
string fName; //从文件中获取的姓名
string fPwd; //从文件中获取的密码
while (ifs >> fId && ifs >> fName && ifs >> fPwd)
{
//与用户输入的信息作对比
if (id == fId && name == fName && pwd == fPwd)
{
cout << "学生验证登录成功!" << endl;
Person = new Student(id, name, pwd);
system("pause");
system("cls");
//进入学生身份的子菜单
studentMenu(Person);
return;
}
}
}
else if (type == 2)
{
//教师身份验证
int fId; //从文件中获取的id号
string fName; //从文件中获取的姓名
string fPwd; //从文件中获取的密码
while (ifs >> fId && ifs >> fName && ifs >> fPwd)
{
//与用户输入的信息作对比
if (id == fId && name == fName && pwd == fPwd)
{
cout << "教师验证登录成功!" << endl;
Person = new Teacher(id, name, pwd);
system("pause");
system("cls");
//进入教师身份的子菜单
teacherMenu(Person);
return;
}
}
}
else if (type == 3)
{
//管理员身份验证
string fName; //从文件中获取的姓名
string fPwd; //从文件中获取的密码
while (ifs >> fName && ifs >> fPwd)
{
//与用户输入的信息作对比
if (name == fName && pwd == fPwd)
{
cout << "管理员验证登录成功!" << endl;
Person = new Manager(name, pwd); //调用有参构造函数
system("pause");
system("cls");
//进入管理员身份的子菜单
managerMenu(Person);
return;
}
}
}
cout << "验证登录失败!" << endl;
system("pause");
system("cls");
}
若不按0注销登录,系统将一直停留在子菜单功能中,由用户选择实现各项功能。
//进入学生子菜单界面
void studentMenu(Identity*& student)
{
//将父类指针转为子类指针,调用子类里的其他接口
Student* stu = (Student*)student;
int select = 0;
while (1)
{
//调用管理员子菜单
student->operMenu();
cin >> select; //接收用户选项
switch (select)
{
case 1:
//申请预约
stu->applyOrder();
break;
case 2:
//查看自身预约
stu->showMyOrder();
break;
case 3:
//查看所有预约
stu->showAllOrder();
break;
case 4:
//取消预约
stu->cancelOrder();
break;
case 0:
//注销登录
delete student; //销毁掉堆区对象
cout << "注销登录!" << endl;
system("pause");
system("cls");
return;
break;
default:
cout << "输入错误,请重新输入" << endl;
system("pause");
system("cls");
break;
}
}
}
//进入管理员子菜单界面
void managerMenu(Identity*& manager)
{
//将父类指针转为子类指针,调用子类里的其他接口
Manager* man = (Manager*)manager;
int select = 0;
while (1)
{
//调用管理员子菜单
manager->operMenu();
cin >> select; //接收用户选项
switch (select)
{
case 1:
//添加账号
man->addPerson();
break;
case 2:
//查看账号
man->showPerson();
break;
case 3:
//查看机房
man->showComputer();
break;
case 4:
//清空预约
man->cleanFile();
break;
case 0:
//注销登录
delete manager; //销毁掉堆区对象
cout << "注销登录!" << endl;
system("pause");
system("cls");
return;
break;
default:
cout << "输入错误,请重新输入" << endl;
system("pause");
system("cls");
break;
}
}
}
//进入教师子菜单界面
void teacherMenu(Identity*& teacher)
{
//将父类指针转为子类指针,调用子类里的其他接口
Teacher* tea = (Teacher*)teacher;
int select = 0;
while (1)
{
//调用管理员子菜单
teacher->operMenu();
cin >> select; //接收用户选项
switch (select)
{
case 1:
//查看所有预约
tea->showAllOrder();
break;
case 2:
//审核预约
tea->validOrder();
break;
case 0:
//注销登录
delete teacher; //销毁掉堆区对象
cout << "注销登录!" << endl;
system("pause");
system("cls");
return;
break;
default:
cout << "输入错误,请重新输入" << endl;
system("pause");
system("cls");
break;
}
}
}