黑马C++视频的第二个案例:职工管理系统

黑马C++视频的第二个案例:职工管理系统

一.要求分析

  • 员工分为三类:普通职工,经理和老板。他们都有员工ID,姓名和职责类型共同属性,以及显示员工信息的共同函数。所以可以将员工类作为抽象类,普通职工类,经理类和老板类作为员工的子类利用多态以实现不同功能。

  • 利用一个员工管理类来实现具体的功能函数,且员工类中包含员工人数信息,利用一个指针数组来维护员工信息,再用一个bool变量来判断要求读入的文件是否为空。

  • 接下来就是具体功能函数的实现。

二.代码分析

1.利用数组维护员工信息

Worker** workerArr = new Worker*[worker_num];

类似一个workerArr数组,数组中存放的是worker的指针变量,指向堆中具体开辟出的worker空间,所以此处的 workerArr是二级指针。

2.员工管理类的初始化

//构造函数,构造函数时还需判断文件是否存在
WorkerManager::WorkerManager()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);
	char ch;

	//文件不存在情况下初始化
	if (!ifs.is_open())
	{
		this->fileIsEmpty = true;
		this->workerArr = NULL;
		this->worker_num = 0;
		//cout << "文件不存在" << endl;(测试用)
		ifs.close(); 
		return;
	}
	
	//文件存在但是为空情况下初始化
	ifs >> ch;
	if (ifs.eof())
	{
		this->fileIsEmpty = true;
		this->workerArr = NULL;
		this->worker_num = 0;
		//cout << "文件为空" << endl;(测试用)
		ifs.close();
		return;
	}

	//文件存在且不为空的情况下初始化
	this->fileIsEmpty = false;
	this->worker_num = getWorkerNum();
	this->workerArr = new Worker * [this->worker_num];
	initialize();
	//测试代码
	//for (int i = 0; i < worker_num; i++)
	//{
	//	cout << workerArr[i]->m_ID << "\t"
	//		<< workerArr[i]->m_name << "\t"
	//		<< workerArr[i]->getDeptName() << endl;
	//}
}
void WorkerManager::initialize()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);

	int id;
	string name;
	int deptID;
	int index = 0;
	while (ifs >> id && ifs >> name && ifs >> deptID)
	{
		Worker* worker;
		switch (deptID)
		{
		case 0:
			worker = new Employee(id, name);
			this->workerArr[index] = worker;
			break;
		case 1:
			worker = new Management(id, name);
			this->workerArr[index] = worker;
			break;
		case 2:
			worker = new Boss(id, name);
			this->workerArr[index] = worker;
			break;
		}
		index++;
	}
}

员工管理类的初始化有些麻烦,分为三种情况:文件不存在,文件存在但是为空和文件存在且不为空。需要通过文件输入流ifstream的对象进行判断,分为三种情况构造对象。利用fileIsEmpty变量判断文件情况。

3.添加员工函数中的部分代码

int newNum = this->worker_num + num;
	Worker** newSpace = new Worker * [newNum];

	//将原来的指针数组转移至新的数组
	if (workerArr != NULL)
	{
		for (int i = 0; i < worker_num; i++)
		{
			newSpace[i] = workerArr[i];
		}
	}

在添加前先计算添加员工后的员工人数,再通过新的员工人数构建新的指针数组,将原来的指针数组复制到新的数组中。

delete[] workerArr;
	workerArr = newSpace;
	worker_num = newNum;
	save();
	if (fileIsEmpty == true)
	{
		fileIsEmpty = false;
	}

添加员工完之后别忘了删除原来的指针数组,释放空间。

4.析构函数

WorkerManager::~WorkerManager()
{
	for (int i = 0; i < worker_num; i++)
	{
		delete[] workerArr[i];
		workerArr[i] = NULL;
		cout << "删除成功" << endl;
	}
}

三.代码展示

员工管理类代码:

#include"WorkerManager.h"

//构造函数,构造函数时还需判断文件是否存在
WorkerManager::WorkerManager()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);
	char ch;

	//文件不存在情况下初始化
	if (!ifs.is_open())
	{
		this->fileIsEmpty = true;
		this->workerArr = NULL;
		this->worker_num = 0;
		//cout << "文件不存在" << endl;(测试用)
		ifs.close(); 
		return;
	}
	
	//文件存在但是为空情况下初始化
	ifs >> ch;
	if (ifs.eof())
	{
		this->fileIsEmpty = true;
		this->workerArr = NULL;
		this->worker_num = 0;
		//cout << "文件为空" << endl;(测试用)
		ifs.close();
		return;
	}

	//文件存在且不为空的情况下初始化
	this->fileIsEmpty = false;
	this->worker_num = getWorkerNum();
	this->workerArr = new Worker * [this->worker_num];
	initialize();
	//测试代码
	//for (int i = 0; i < worker_num; i++)
	//{
	//	cout << workerArr[i]->m_ID << "\t"
	//		<< workerArr[i]->m_name << "\t"
	//		<< workerArr[i]->getDeptName() << endl;
	//}
}

//析构函数
WorkerManager::~WorkerManager()
{
	for (int i = 0; i < worker_num; i++)
	{
		delete[] workerArr[i];
		workerArr[i] = NULL;
		cout << "删除成功" << endl;
	}
}

//界面展示
void WorkerManager::showSelection()
{
	cout << "--------------------------------------------------------" << endl;
	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 << "--------------------------------------------------------" << endl;
}

//第一个方法:添加员工,写入文件
void WorkerManager::addWorker()
{
	cout << "请选择要添加的员工人数" << endl;
	int num;
	cin >> num;
	int newNum = this->worker_num + num;
	Worker** newSpace = new Worker * [newNum];

	//将原来的指针数组转移至新的数组
	if (workerArr != NULL)
	{
		for (int i = 0; i < worker_num; i++)
		{
			newSpace[i] = workerArr[i];
		}
	}

	//添加新的员工
	for (int i = 0; i < num; i++)
	{
		cout << endl;
		cout << "下面添加第" << i + 1 << "位员工" << endl;
		int id;
		cout << "请输入员工的ID" << endl;
		cin >> id;

		string name;
		cout << "请输入员工的姓名" << endl;
		cin >> name;

		int selection;
		cout << "请输入数字选择员工的职位:" << endl;
		cout << "1:普通员工" << endl;
		cout << "2:经理" << endl;
		cout << "3:总裁" << endl;
		cin >> selection;

		Worker* worker;
		switch (selection)
		{
		case 1:
			worker = new Employee(id, name);
			newSpace[worker_num + i] = worker;
			break;
		case 2:
			worker = new Management(id, name);
			newSpace[worker_num + i] = worker;
			break;
		case 3:
			worker = new Boss(id, name);
			newSpace[worker_num + i] = worker;
			break;
		default:
			cout << "选择有误" << endl;
			break;
		}
	}
	delete[] workerArr;
	workerArr = newSpace;
	worker_num = newNum;
	save();
	if (fileIsEmpty == true)
	{
		fileIsEmpty = false;
	}
	system("pause");
	system("cls");
}

//第二个方法:显示当前列表中的员工信息
void WorkerManager::display()
{
	if (fileIsEmpty == true)
	{
		cout << "文件不存在或为空" << endl;
	}
	else
	{
		for (int i = 0; i < worker_num; i++)
		{
			workerArr[i]->showInfo();
		}
	}

	system("pause");
	system("cls");
}

//第三个方法:删除员工
void WorkerManager::deleteWorker()
{
	if (fileIsEmpty == true)
	{
		cout << "文件不存在或为空" << endl;
	}
	else
	{
		cout << "请输入你想删除的员工编号" << endl;
		int deleteNum;
		cin >> deleteNum;

		if (isExist(deleteNum) == -1)
		{
			cout << "查无此人" << endl;
		}
		else
		{
			int pointer = isExist(deleteNum);
			for (; pointer < worker_num - 1; pointer++)
			{
				workerArr[pointer] = workerArr[pointer + 1];
			}
			workerArr[worker_num - 1] = NULL;
			worker_num--;
			cout << "删除成功" << endl;
		}
		save();
	}
	system("pause");
	system("cls");
}

//第四个方法:修改员工信息
void WorkerManager::modMessage()
{
	if (fileIsEmpty == true)
	{
		cout << "文件不存在或为空" << endl;
	}
	else
	{
		int selection;
		cout << "请输入要修改的员工编号" << endl;
		cin >> selection;
		int pointer = isExist(selection);
		if (pointer == -1)
		{
			cout << "查无此人" << endl;
		}
		else
		{
			cout << "找到该员工,下面输入修改后的信息" << endl;
			int tempID;
			string tempName;
			int tempDeptID;
			cout << "请输入员工编号" << endl;
			cin >> tempID;
			cout << "请输入员工姓名" << endl;
			cin >> tempName;
			cout << "请选择员工职位" << endl;
			cout << "1.普通员工" << endl;
			cout << "2.经理" << endl;
			cout << "3.总裁" << endl;
			int tempSelection;
			cin >> tempSelection;

			Worker* worker;
			switch (tempSelection)
			{
			case 1:
				worker = new Employee(tempID, tempName);
				workerArr[pointer] = worker;
				break;
			case 2:
				worker = new Management(tempID, tempName);
				workerArr[pointer] = worker;
				break;
			case 3:
				worker = new Boss(tempID, tempName);
				workerArr[pointer] = worker;
				break;
			default:
				cout << "选择有误" << endl;
				break;
			}
			cout << "修改成功" << endl;
		}
		save();
	}
	system("pause");
	system("cls");
}

//第五个方法:通过员工编号或姓名查找员工
void WorkerManager::seekWorker()
{
	if (fileIsEmpty == true)
	{
		cout << "文件不存在或为空" << endl;
	}
	else
	{
		cout << "请选择你的查找方式" << endl;
		cout << "1.通过员工编号查找" << endl;
		cout << "2.通过员工姓名查找" << endl;
		int selection = 0;
		cin >> selection;
		switch (selection)
		{
		case 1:
		{
			cout << "请选择你要查找的员工编号" << endl;
			int searchID;
			cin >> searchID;
			int pointer = isExist(searchID);
			if (pointer == -1)
			{
				cout << "查无此人" << endl;
				system("pause");
				system("cls");
				return;
			}
			else
			{
				cout << "查找员工的信息如下" << endl;
				workerArr[pointer]->showInfo();
				system("pause");
				system("cls");
				return;
			}
		}
		case 2:
		{
			cout << "输入要查找的员工姓名" << endl;
			string searchName;
			cin >> searchName;
			bool isExist = false;
			for (int i = 0; i < worker_num; i++)
			{
				if (workerArr[i]->m_name == searchName)
				{
					workerArr[i]->showInfo();
					isExist = true;
				}
			}
			if (isExist == false)
			{
				cout << "查无此人" << endl;
				system("pause");
				system("cls");
				return;
			}
			system("pause");
			system("cls");
			return;
		}
		default:
			cout << "输入有误" << endl;
			break;
		}
	}
	system("pause");
	system("cls");
}

//第六个方法:将文件中的员工通过员工编号排序
void WorkerManager::sortByID()
{
	if (fileIsEmpty == true)
	{
		cout << "文件不存在或为空" << endl;
	}
	else
	{
		cout << "请选择你的排序方式" << endl;
		cout << "1.通过编号升序排列" << endl;
		cout << "2.通过编号降序排列" << endl;
		int selection = 0;
		cin >> selection;
		if (selection == 1)
		{
			for (int i = 0; i < worker_num; i++)
			{
				for (int j = i + 1; j < worker_num; j++)
				{
					if (workerArr[i]->m_ID > workerArr[j]->m_ID)
					{
						Worker* tempWorker;
						tempWorker = workerArr[i];
						workerArr[i] = workerArr[j];
						workerArr[j] = tempWorker;
					}
				}
			}
			cout << "排序成功" << endl;
			save();
		}
		else if (selection == 2)
		{
			for (int i = 0; i < worker_num; i++)
			{
				for (int j = i + 1; j < worker_num; j++)
				{
					if (workerArr[i]->m_ID < workerArr[j]->m_ID)
					{
						Worker* tempWorker;
						tempWorker = workerArr[i];
						workerArr[i] = workerArr[j];
						workerArr[j] = tempWorker;
					}
				}
			}
			cout << "排序成功" << endl;
			save();
		}
		else
		{
			cout << "输入有误" << endl;
		}
	}
	system("pause");
	system("cls");
}

//第七个方法:清空文件
void WorkerManager::emptyFile()
{
	if (fileIsEmpty == true)
	{
		cout << "文件不存在或为空" << endl;
	}
	else
	{
		cout << "是否确认清空文件?" << endl;
		cout << "输入:Y/N" << endl;
		char selection;
		cin >> selection;
		if (selection == 'Y' || selection == 'y')
		{
			ofstream ofs;
			ofs.open(FILENAME, ios::trunc);
			ofs.close();

			if (workerArr != NULL)
			{
				for (int i = 0; i < worker_num; i++)
				{
					delete workerArr[i];
					workerArr[i] = NULL;
				}
			}
			delete[] workerArr;
			workerArr = NULL;
			fileIsEmpty = true;
			cout << "清空成功" << endl;
		}
		else if (selection == 'N' || selection == 'n')
		{
			cout << "不执行清空操作" << endl;
		}
		else
		{
			cout << "输入有误" << endl;
		}
		system("pause");
		system("cls");
	}
}

//第八个方法:退出程序
void WorkerManager::exitProcedure()
{
	cout << "欢迎下次使用" << endl;
	exit(0);
}

//子方法:保存当前worker数组信息到文件当中
void WorkerManager::save()
{
	ofstream ofs;
	ofs.open(FILENAME, ios::out);

	for (int i = 0; i < worker_num; i++)
	{
		ofs << workerArr[i]->m_ID << " "
			<< workerArr[i]->m_name << " "
			<< workerArr[i]->dept_ID << endl;
	}
	ofs.close();
}

//子方法:帮助初始化
void WorkerManager::initialize()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);

	int id;
	string name;
	int deptID;
	int index = 0;
	while (ifs >> id && ifs >> name && ifs >> deptID)
	{
		Worker* worker;
		switch (deptID)
		{
		case 0:
			worker = new Employee(id, name);
			this->workerArr[index] = worker;
			break;
		case 1:
			worker = new Management(id, name);
			this->workerArr[index] = worker;
			break;
		case 2:
			worker = new Boss(id, name);
			this->workerArr[index] = worker;
			break;
		}
		index++;
	}
}

//子方法:得到文件中的员工数
int WorkerManager::getWorkerNum()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);

	int id;
	string name;
	int deptID;
	this->worker_num = 0;

	while (ifs >> id && ifs >> name && ifs >> deptID)
	{
		this->worker_num++;
	}

	return this->worker_num;
}

//子方法:判断所输入的员工编号,查找此人是否存在
int WorkerManager::isExist(int searchID)
{
	for (int i = 0; i < worker_num; i++)
	{
		if (workerArr[i]->m_ID == searchID)
		{
			return i;
		}
	}
	return -1;
}

抽象类员工类代码:

class Worker
{
public:
	int m_ID;//员工ID
	int dept_ID;//员工的职位编号
	string m_name;//员工姓名

	virtual void showInfo() = 0;//显示员工信息
	virtual string getDeptName() = 0;//得到员工职位名字
};

主函数代码:

#include<iostream>
#include"WorkerManager.h"
using namespace std;

int main()
{
	WorkerManager wm;

	while (true)
	{
		wm.showSelection();

		cout << "请输入你的操作" << endl;
		int selection;
		cin >> selection;

		switch (selection)
		{
		case 1://增加职工信息
			wm.addWorker();
			break;

		case 2://显示职工信息
			wm.display();
			break;

		case 3://删除职工信息
			wm.deleteWorker();
			break;

		case 4://修改职工信息
			wm.modMessage();
			break;

		case 5://查找职工信息
			wm.seekWorker();
			break;

		case 6://按照编号排序
			wm.sortByID();
			break;

		case 7://清空所有文档
			wm.emptyFile();
			break;

		case 8://退出管理程序
			wm.exitProcedure();
			break;

		default:
		{
			cout << "输入有误" << endl;
			exit(0);
		}
			break;
		}
	}
	system("pause");
	return 0;
}

三种员工类代码就不逐一展示。

posted @ 2022-01-12 15:19  bbq-carol  阅读(119)  评论(0编辑  收藏  举报