C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现

7、 管理员模块

学生、老师、管理员这三个身份类中,首先实现管理员模块,因为管理员可以添加账号,添加新的学生、老师账号。在上一篇中已经实现了管理员的登录验证功能,但是管理员的子菜单还没有显示,接下来继续完善管理员的其他功能。

7.1 管理员登录和注销

7.1.1 构造函数

在Manager类的构造函数中,初始化管理员信息,记录管理员的姓名和密码。
这里维护的密码姓名属性意义不大,但如果后期有修改密码等功能 这里维护的密码就有用了。

代码展示:

//有参构造(管理员姓名,密码)
Manager::Manager(string name, string password)
{
	//初始化管理员信息
	this->m_Name = name;
	this->m_Password = password;
}

7.1.2 管理员子菜单和注销登录功能

实现步骤:

  • 在机房预约系统.cpp中,当用户登录的是管理员,添加管理员菜单接口
  • 将不同的分支提供出来
    • 添加账号
    • 查看账号
    • 查看机房
    • 清空预约
    • 注销登录
  • 实现注销功能

在机房预约系统.cpp中添加全局函数 void managerMenu(Identity * &manager),代码如下:

//全局函数 进入管理员子菜单界面
void managerMenu(Identity*& manager)//传进管理员 先用父类指针传入
{
	while (1)
	{
		//调用管理员子菜单
		manager->openMenu();//利用多态 父类指针创建子类对象

		//将父类指针转为子类指针,调用子类的其他接口
		Manager* admin = (Manager*)manager;

		//接收用户选择功能
		int select = 0;
		cin >> select;

		//框架搭建 建立接口
		switch (select)
		{
		case 1://添加账号
			admin->addPerson();
			break;
		case 2://查看账号
			admin->showPerson();
			break;
		case 3://查看机房信息
			admin->showComputer();
			break;
		case 4://清空预约
			admin->clearFile();
			break;
		default://默认情况下注销登录 释放堆区数据
			delete manager;//释放堆区数据 手动开辟手动释放
			cout << "注销成功!" << endl;
			system("pause");
			system("cls");
			return;
		}
	}
}

注意点:

  1. managerMenu全局函数的形参是通过父类指针创建子类对象(多态),用父类指针接收上一个登录模块中创建出来的管理员对象。
  2. 用父类指针创建的对象只能调用公共接口,即子类中重写了父类的纯虚函数,operMenu子菜单接口
  3. 因此还需要强转成子类指针,才能调用子类特有接口,否则只能调用父类公共接口
  4. switch的默认分支中,释放子类指针,堆区数据手动开辟手动释放

7.1.3 菜单功能实现

  • 在实现成员函数void Manager::operMenu() 代码如下:
//选择菜单
void Manager::operMenu()
{
	cout << "欢迎管理员:"<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;
}

7.1.4 接口对接

  • 管理员成功登录后,调用管理员子菜单界面。在管理员登录验证分支中,添加代码。
C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第1张图片

测试登录:
C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第2张图片

测试注销:

C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第3张图片

7.2 添加账号

功能描述: 给学生或教师添加新的账号

功能要求: 添加时学生学号不能重复、教师职工号不能重复

7.2.1 添加功能实现

实现步骤:

  • 在Manager的addPerson成员函数中,实现添加新账号功能
  • 首先,提示用户添加的是学生还是老师
  • 然后,根据身份的不同,选择操纵不同的文件,并且记录一些提示
  • 最后,向文件中写入身份信息,并测试。测试前,先把student.txt和teacher.txt中内容清空。

代码展示:

//添加账号
void Manager::addPerson()
{
	//提示用户 添加身份类型
	cout << "请输入添加账号类型" << endl;
	cout << "1——添加学生" << endl;
	cout << "2——添加学生" << endl;

	string filename;//操作的文件名 id
	string tip;//提示用户输入的id
	ofstream ofs;//文件操作对象

	//接受用户选择身份类型
	int select = 0;
	cin >> select;

	if (select == 1)//添加学生
	{
		filename = STUDENT_FILE;
		tip = "请输入学号:";
	}
	else//添加老师
	{
		filename = TEACHER_FILE;
		tip = "请输入工号:";
	}

	//利用追加的方式写文件
	ofs.open(filename, ios::out | ios::app);

	//接收用户添加信息
	int id;
	string name;
	string pwd;

	cout << tip;
	cin >> id;

	cout << "请输入姓名:";
	cin >> name;

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

	//向文件添加数据 空格分割
	ofs << id << " " << name << " " << pwd << " " << endl;
	cout << "添加成功!" << endl;

	ofs.close();
	system("pause");
	system("cls");
}

测试添加学生:
C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第4张图片

测试添加教师:
C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第5张图片

7.2.2 去重操作

功能描述: 添加新账号时,如果是重复的学生学号,或是重复的教师工号,提示有误,要求用户重新输入。

7.2.2.1 读取信息

实现步骤:

  • 要去除重复的账号,首先要先将学生和教师的账号信息获取到程序中,方可检测
  • 在Manager.h中,添加两个容器,用于存放学生和教师的信息
  • 添加一个新的成员函数 void initVector() 初始化容器,并在Manager.cpp中具体实现
  • 在Manager.cpp的有参构造函数中,调用初始化容器函数,获取目前的学生和教师信息

Manager.h中-添加位置如图:

C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第6张图片

initVector初始化容器-代码展示:

//初始化容器
void Manager::initVector()
{
	//学生 老师容器 清空
	vStu.clear();
	vTea.clear();

	//读取信息 学生
	ifstream ifs;
	ifs.open(STUDENT_FILE, ios::in);

	//文件打开判断
	if (!ifs.is_open())
	{
		cout << "文件打开失败!" << endl;
		return;
	}

	//创建学生对象
	Student s;

	//读取学生信息并放入vStu中
	while (ifs >> s.m_Id && ifs >> s.m_Name && ifs >> s.m_Password)
	{
		vStu.push_back(s);
	}
	ifs.close();
	cout << "当前学生数量为:" << vStu.size() << endl;//测试

	//读取信息老师
	ifs.open(TEACHER_FILE, ios::in);
	if (!ifs.is_open())
	{
		cout << "文件打开失败!" << endl;
		return;
	}
	Teacher t;
	while (ifs >> t.m_teaId && ifs >> t.m_Name && ifs >> t.m_Password)
	{
		vTea.push_back(t);
	}
	ifs.close();
	cout << "当前老师数量为:" << vTea.size() << endl;
}

Manager.cpp中-添加位置如图:

C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第7张图片

测试前:

C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第8张图片

可以看到student.txt和teacher.txt记录学生和教师的数量

测试效果:

C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第9张图片

7.2.2.2 去重函数封装

功能描述: 根据 学生/老师 的身份检测是否重复添加了 学生/老师 的学号/工号。

实现步骤:

  1. 首先,在Manager.h文件中添加成员函数 bool checkRepeat(int id, int type);,声明函数;
  2. 其次,在Manager.cpp文件中实现成员函数 bool checkRepeat(int id, int type);,写函数实现;
  3. 然后,由于检测操作通常是在输入学号或者工号后进行,因此需要在addPerson函数中调用checkRepeat函数

** 函数声明:**

bool checkRepeat(int id, int type);
  • 在manager.h文件中添加
  • 由于这个函数只需要判断学号/工号是否重复,因此返回值使用bool类型,true 代表有重复,false代表没有重复
  • 该函数需要根据身份类型和用户输入的id来判断,因此需要传入一个表示学号/工号的参数id 和一个表示身份的参数type

函数实现:

//检测重复 参数1 检测学号/工号 参数2 检测身份类型
bool Manager::checkRepeat(int id, int type)
{
	//检测类型 有重复提示
	if (type == 1)
	{
		//检测学生学号
		for (vector::iterator it = this->vStu.begin(); it != this->vStu.end(); it++)
		{
			if (id == it->m_Id)
			{
				return true;
			}
		}
	}
	else
	{
		//检测老师工号
		for (vector::iterator it = this->vTea.begin(); it != this->vTea.end(); it++)
		{
			if (id == it->m_teaId)
			{
				return true;
			}
		}
	}
	//默认没有重复 
	return false;
}
  • 在manager.cpp文件中添加
  • 如果传入学生的身份,遍历存放学生信息的容器,比较传入的学生id和容器中的id是否有重复
  • 如果传入老师的身份,遍历存放老师信息的容器,比较传入的老师id和容器中的id是否有重复

函数调用:

//添加账号
void Manager::addPerson()
{
	//提示用户 添加身份类型
	cout << "请输入添加账号类型" << endl;
	cout << "1——添加学生" << endl;
	cout << "2——添加学生" << endl;

	string filename;//操作的文件名 id
	string tip;//提示用户输入的id
	string errortip;//id重复提示
	ofstream ofs;//文件操作对象

	//接受用户选择身份类型
	int select = 0;
	cin >> select;

	if (select == 1)//添加学生
	{
		filename = STUDENT_FILE;
		tip = "请输入学号:";
		errortip = "学号重复,请重新输入";
	}
	else//添加老师
	{
		filename = TEACHER_FILE;
		tip = "请输入工号:";
		errortip = "工号重复,请重新输入";
	}

	//利用追加的方式写文件
	ofs.open(filename, ios::out | ios::app);

	//接收用户添加信息
	int id;
	string name;
	string pwd;

	cout << tip;
	//对输入的学号进行重复判断
	while (1)
	{
		cin >> id;
		bool ret = checkRepeat(id, select);
		if (ret)
		{
			cout << errortip << endl;
		}
		else
		{
			break;
		}
	}

	cout << "请输入姓名:";
	cin >> name;

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

	//向文件添加数据 空格分割
	ofs << id << " " << name << " " << pwd << " " << endl;
	cout << "添加成功!" << endl;

	ofs.close();
	system("pause");
	system("cls");

	//调用初始化容器接口,重新获取文件中的数据 及时更新数据
	this->initVector();
}
  • 在manager.cpp的addPerson成员函数添加,添加代码如图所示
  • 首先,加一个id重复提示errortip,根据身份提示不同的内容
  • 其次,提示用户输入id后,调用重复检测函数checkRepeat,此时传入的参数是用户实际输入的id和身份类型select
  • 然后,根据函数返回的结果,即是否重复来做出不同的输出。如果重复,输出errortip;否则跳出重复检测循环

问题描述: 虽然可以检测重复的账号,但是如果是刚添加的账号由于没有更新到容器中,因此不会做检测。会出现刚加入的账号的学号或者工号,再次添加时依然可以重复

解决方案: 在每次添加新账号时,重新初始化容器

检测效果: 在读取信息时,已经知道student.txt和teacher.txt中学生和老师的信息,接下来对学生和老师的学号/工号进行检测
C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第10张图片

C++ 机房预约系统(四):管理员模块——管理员登录和注销、添加账号功能、重复添加检测的具体实现_第11张图片

你可能感兴趣的:(C++,基础系统合集,c++)