首页 > 编程语言 >C++职工管理系统项目实战

C++职工管理系统项目实战

时间:2023-08-03 21:11:06浏览次数:42  
标签:实战 std cout 管理系统 int EmpArray void C++ id

职工管理系统

1. 管理系统需求

职工管理系统可以用来管理公司内所有员工的信息,利用C++来实现一个基于多态的职工管理系统

公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责

  • 普通员工职责:完成经理交给的任务

  • 经理职责:完成老板交给的任务,并下发任务给员工

  • 老板职责:管理公司所有事务

管理系统中需要实现的功能如下:

  • 退出管理程序:退出当前管理系统
  • 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
  • 显示职工信息:显示公司内部所有职工的信息
  • 删除离职职工:按照编号删除指定的职工
  • 修改职工信息:按照编号修改职工个人信息
  • 查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
  • 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
  • 清空所有文档:清空文件中记录的所有职工信息 (清空前需要再次确认,防止误删)

2. 创建管理类

管理类负责的内容如下:

  • 与用户的沟通菜单界面
  • 对职工增删改查的操作
  • 与文件的读写交互

2.1 创建文件

在头文件和源文件的文件夹下分别创建 workerManager.hworkerManager.cpp 文件

2.2 头文件实现

workerManager.h 中设计管理类

代码如下:

#pragma once
#include <iostream>

class WorkerManager
{
public:
	WorkerManager();

	~WorkerManager();
};

2.3 源文件实现

workerManager.cpp 中将构造和析构函数空实现补全

#include "workerManager.h"

WorkerManager::WorkerManager()
{

}

WorkerManager::~WorkerManager()
{

}

至此职工管理类以创建完毕

3. 菜单功能

3.1 添加成员函数

在管理类 workerManager.h 中添加成员函数 void Show_Menu();

#pragma once
#include <iostream>

class WorkerManager
{
public:
	WorkerManager();

	void showMenu();

	~WorkerManager();
};

3.2 菜单功能实现

在管理类 workerManager.h 中添加成员函数 void Show_Menu();

void WorkerManager::showMenu()
{
	std::cout << "********************************************" << std::endl;
	std::cout << "*********  欢迎使用职工管理系统! **********" << std::endl;
	std::cout << "*************  0.退出管理程序  *************" << std::endl;
	std::cout << "*************  1.增加职工信息  *************" << std::endl;
	std::cout << "*************  2.显示职工信息  *************" << std::endl;
	std::cout << "*************  3.删除离职职工  *************" << std::endl;
	std::cout << "*************  4.修改职工信息  *************" << std::endl;
	std::cout << "*************  5.查找职工信息  *************" << std::endl;
	std::cout << "*************  6.按照编号排序  *************" << std::endl;
	std::cout << "*************  7.清空所有文档  *************" << std::endl;
	std::cout << "********************************************" << std::endl;
	std::cout << std::endl;
}

3.3 测试菜单功能

main.cpp 文件中中测试菜单功能

#include <iostream>
#include "workerManager.h"

int main()
{
	WorkerManager wm;
	wm.showMenu();

	return 0;
}
image-20230731154542863

4. 退出功能

4.1 提供功能接口

在main函数中提供分支选择,提供每个功能接口

int main()
{
	WorkerManager wm;

	int choise = 0;
	while (true)
	{
		wm.showMenu();

		std::cout << "请输入你的选择: " << std::endl;
		std::cin >> choise;
		
		switch (choise)
		{
		case 0: //退出系统
			break;
		case 1: //添加职工
			break;
		case 2: //显示职工
			break;
		case 3: //删除职工
			break;
		case 4: //修改职工
			break;
		case 5: //查找职工
			break;
		case 6: //排序职工
			break;
		case 7: //清空文件
			break;
		default:
			system("cls");
			break;
		}
	}
	return 0;
}

4.2 实现退出功能

workerManager.h 中提供退出系统的成员函数 void exitSystem();

workerManager.cpp 中提供具体的功能实现

void WorkerManager::exitSystem()
{
	cout << "欢迎下次使用" << endl;
	system("pause");
	exit(0);
}

4.3 测试功能

在main函数分支 0 选项中,调用退出程序的接口

image-20230731155904366

5. 创建职工类

5.1 创建职工抽象类

职工的分类为:普通员工、经理、老板

将三种职工抽象到一个类 (worker) 中,利用多态管理不同职工种类

职工的属性为:职工编号、职工姓名、职工所在部门编号

职工的行为为:岗位职责信息描述,获取岗位名称

头文件文件夹下 创建文件 worker.h 文件并且添加如下代码:

#pragma once
#include <iostream>

class Worker
{
public:
	int m_Id;
	std::string m_Name;
	int m_DeptId;

	virtual void showInfo() = 0;
	virtual std::string getDeptName() = 0;
};

5.2 创建普通员工类

普通员工类继承职工抽象类,并重写父类中纯虚函数

在头文件和源文件的文件夹下分别创建 employee.hemployee.cpp 文件

employee.h 中代码如下:

#pragma once
#include <iostream>
#include "worker.h"

class Employee :public Worker
{
public:
	Employee(int id, std::string name, int deptId);

	void showInfo();
	std::string getDeptName();
};

employee.cpp 中代码如下:

#include "employee.h"

Employee::Employee(int id, std::string name, int deptId)
{
	this->m_Id = id;
	this->m_Name = name;
	this->m_DeptId = deptId;
}

void Employee::showInfo()
{
	std::cout
		<< "职工编号: " << this->m_Id
		<< " \t职工姓名: " << this->m_Name
		<< " \t岗位: " << this->getDeptName()
		<< " \t岗位职责: 完成经理交给的任务" << std::endl;
}

std::string Employee::getDeptName()
{
	return std::string("普通员工");
}

5.3 创建经理类

经理类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似

在头文件和源文件的文件夹下分别创建 manager.hmanager.cpp 文件

manager.h 中代码如下:

#pragma once
#include <iostream>
#include "worker.h"

class Manager :public Worker
{
public:
	Manager(int id, std::string name, int deptId);

	void showInfo();
	std::string getDeptName();
};

manager.cpp 中代码如下:

#include "manager.h"

Manager::Manager(int id, std::string name, int deptId)
{
	this->m_Id = id;
	this->m_Name = name;
	this->m_DeptId = deptId;
}

void Manager::showInfo()
{
	std::cout
		<< "职工编号: " << this->m_Id
		<< " \t职工姓名: " << this->m_Name
		<< " \t岗位: " << this->getDeptName()
		<< " \t岗位职责: 完成老板交给的任务,并下发任务给员工" << std::endl;
}

std::string Manager::getDeptName()
{
	return std::string("经理");
}

5.4 创建老板类

老板类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似

在头文件和源文件的文件夹下分别创建 boss.hboss.cpp 文件

boss.h 中代码如下:

#pragma once
#include <iostream>
#include "worker.h"

class Boss :public Worker
{
public:
	Boss(int id, std::string name, int deptId);

	void showInfo();
	std::string getDeptName();
};

boss.cpp 中代码如下:

#include "boss.h"

Boss::Boss(int id, std::string name, int deptId)
{
	this->m_Id = id;
	this->m_Name = name;
	this->m_DeptId = deptId;
}

void Boss::showInfo()
{
	std::cout
		<< "职工编号: " << this->m_Id
		<< " \t职工姓名: " << this->m_Name
		<< " \t岗位: " << this->getDeptName()
		<< " \t岗位职责: 管理公司所有事务" << std::endl;
}

std::string Boss::getDeptName()
{
	return std::string("老板");
}

5.5 测试多态

main.cpp 中添加测试函数,并且运行能够产生多态

测试代码如下:

void test1()
{
	Worker* worker = new Employee(1, "张三", 1);
	worker->showInfo();
	delete worker;

	worker = new Manager(2, "李四", 2);
	worker->showInfo();
	delete worker;

	worker = new Boss(3, "王五", 3);
	worker->showInfo();
	delete worker;
}

image-20230731165904709

6. 添加职工

功能描述:批量添加职工,并且保存到文件中

6.1 功能分析

分析:

用户在批量创建时,可能会创建不同种类的职工

如果想将所有不同种类的员工都放入到一个数组中,可以将所有员工的指针维护到一个数组里

如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用 Worker ** 的指针维护

6.2 功能实现

WorkerManager.h 头文件中添加成员属性代码:

	//职工人数
	int m_EmpNum;
	
	//职工数组
	Worker** m_EmpArray;

WorkerManager 构造函数中初始化属性

WorkerManager::WorkerManager()
{
	this->m_EmpNum = 0;
	this->m_EmpArray = NULL;
}

WorkerManager.h 中添加成员函数

	void add_Emp();

WorkerManager.cpp 中实现该函数

void WorkerManager::add_Emp()
{
	std::cout << "请输入添加职工的数量: " << std::endl;
	int addNum = 0;
	std::cin >> addNum;

	if (addNum > 0)
	{
		int newSize = this->m_EmpNum + addNum;
		Worker** newSpace = new Worker* [newSize];

		//假如文件内不为空,申请数组将文件中的内容读到内存中操作
		if (this->m_EmpArray != NULL)
		{
			//把原有的数组都移动到新开辟的内存中
			for (int i = 0; i < this->m_EmpNum; i++)
			{
				newSpace[i] = this->m_EmpArray[i];
			}
		}

		//假如文件为空或不为空,则直接开辟后添加
		for (int i = 0; i < addNum; i++)
		{
			int id;
			std::string name;
			int deptId;

			std::cout << "请输入第[" << i + 1 << "]个职工编号: ";
			std::cin >> id;

			std::cout << "请输入第[" << i + 1 << "]个职工姓名: ";
			std::cin >> name;

			std::cout << "请选择该职工的岗位" << std::endl;
			std::cout << "1.普通员工" << std::endl;
			std::cout << "2.经理" << std::endl;
			std::cout << "3.老板" << std::endl;
			std::cin >> deptId;

			Worker* newWorker = NULL;
			switch (deptId)
			{
			case 1:
				newWorker = new Employee(id, name, 1);
				break;
			case 2:
				newWorker = new Manager(id, name, 2);
				break;
			case 3:
				newWorker = new Boss(id, name, 3);
				break;
			default:
				break;
			}
			newSpace[this->m_EmpNum + i] = newWorker;
		}

		delete[] this->m_EmpArray;
		this->m_EmpArray = newSpace;
		this->m_EmpNum = newSize;
		this->m_FileIsEmpty = false;

		std::cout << "成功添加" << addNum << "人" << std::endl;
		this->save();
	}
	else
	{
		std::cout << "输入有误,请重新输入!" << std::endl;
	}

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

7. 文件交互——写文件

功能描述:对文件进行读写

在上一个添加功能中,我们只是将所有的数据添加到了内存中,一旦程序结束就无法保存了

因此文件管理类中需要一个与文件进行交互的功能,对于文件进行读写操作

7.1 设定文件路径

首先我们将文件路径,在 workerManager.h 中添加宏常量,并且包含头文件 fstream

#include <fstream>
#define  FILENAME "empFile.txt"

7.2 成员函数声明

workerManager.h 中类里添加成员函数 void save()

//保存文件
void save();

7.3 保存文件功能实现

void WorkerManager::save()
{
	ofstream ofs;
	ofs.open(FILENAME, ios::out);

	for (int i = 0; i < this->m_EmpNum; i++)
	{
		ofs << this->m_EmpArray[i]->m_Id << " " 
			<< this->m_EmpArray[i]->m_Name << " " 
			<< this->m_EmpArray[i]->m_DeptId << endl;
	}

	ofs.close();
}

7.4 保存文件功能测试

在添加职工功能中添加成功后添加保存文件函数

8. 文件交互——读文件

功能描述:将文件中的内容读取到程序中

虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中数据读取到程序中

而我们的程序功能中还有清空文件的需求

因此构造函数初始化数据的情况分为三种

  1. 第一次使用,文件未创建
  2. 文件存在,但是数据被用户清空
  3. 文件存在,并且保存职工的所有数据

8.1 文件未创建

workerManager.h 中添加新的成员属性 m_FileIsEmpty 标志文件是否为空

	//标志文件是否为空
	bool m_FileIsEmpty;

修改 WorkerManager.cpp 中构造函数代码

WorkerManager::WorkerManager()
{
	//文件不存在
	std::ifstream ifs(FILENAME, std::ios::in);
	if (!ifs.is_open())
	{
		std::cout << "文件不存在" << std::endl;
		this->m_EmpNum = 0;
		this->m_EmpArray = NULL;
		this->m_FileIsEmpty = true;
		ifs.close();
		return;
	}
}

删除文件后,测试文件不存在时初始化数据功能

8.2 文件存在且数据为空

workerManager.cpp 中的构造函数追加代码:

	//文件存在,但没有内容
	char buf;
	ifs >> buf;
	//只读文件里的第一个位置,看看是否是空的
	if (ifs.eof())
	{
		std::cout << "文件为空" << std::endl;
		this->m_EmpNum = 0;
		this->m_EmpArray = NULL;
		this->m_FileIsEmpty = true;
		ifs.close();
		return;
	}

8.3 文件存在且保存职工数据

8.3.1 获取记录的职工人数

workerManager.h 中添加成员函数 int get_EmpNum();

	//统计人数
	int get_EmpNum();

workerManager.cpp 中实现

int WorkerManager::get_EmpNum()
{
	std::ifstream ifs(FILENAME, std::ios::in);

	int id;
	std::string name;
	int deptId;

	int count = 0;
	//这种方法会使文件内容为空的情况下仍然返回1,造成缓冲区溢出
	/*
	char buf[1024] = { 0 };
	while (ifs.getline(buf, sizeof(buf)))
	{
		num++;
	}
	*/

	while (ifs >> id && ifs >> name && ifs >> deptId)
	{
		count++;
	}
	ifs.close();

	return count;
}

workerManager.cpp 构造函数中继续追加代码:

	int num =  this->get_EmpNum();
	cout << "职工个数为:" << num << endl;  //测试代码
	this->m_EmpNum = num;  //更新成员属性 

8.3.2 初始化数组

根据职工的数据以及职工数据,初始化 workerManager 中的 Worker ** m_EmpArray 指针

workerManager.h 中添加成员函数 void init_Emp();

	//初始化员工
	void init_Emp();

workerManager.cpp 中实现

void WorkerManager::init_Emp()
{
	std::ifstream ifs(FILENAME, std::ios::in);

	int id;
	std::string name;
	int deptId;

	int index = 0;
	while (ifs >> id && ifs >> name && ifs >> deptId)
	{
		Worker* worker = NULL;
		if (deptId == 1)
		{
			worker = new Employee(id, name, deptId);
		}
		else if (deptId == 2)
		{
			worker = new Manager(id, name, deptId);
		}
		else
		{
			worker = new Boss(id, name, deptId);
		}
		this->m_EmpArray[index] = worker;
		index++;
	}
	ifs.close();
}

workerManager.cpp 构造函数中追加代码

	//根据职工数创建数组
	this->m_EmpArray = new Worker *[this->m_EmpNum];
	//初始化职工
	init_Emp();

	//测试代码
	for (int i = 0; i < m_EmpNum; i++)
	{
		cout << "职工号: " << this->m_EmpArray[i]->m_Id
			<< " 职工姓名: " << this->m_EmpArray[i]->m_Name
			<< " 部门编号: " << this->m_EmpArray[i]->m_DeptId << endl;
	}

9. 显示职工

功能描述:显示当前所有职工信息

9.1 显示职工函数声明

workerManager.h 中添加成员函数 void Show_Emp();

	//显示职工
	void show_Emp();

9.2 显示职工函数实现

workerManager.cpp 中实现成员函数 void Show_Emp();

//显示职工
void WorkerManager::show_Emp()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
	}
	else
	{
		for (int i = 0; i < m_EmpNum; i++)
		{
			//利用多态调用接口
			this->m_EmpArray[i]->showInfo();
		}
	}

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

10. 删除职工

10.1 删除职工函数声明

workerManager.h 中添加成员函数 void del_Emp();

	//修改职工
	void del_Emp();

10.2 职工是否存在函数声明

很多功能都需要用到根据职工是否存在来进行操作如:删除职工、修改职工、查找职工

因此添加该公告函数,以便后续调用

workerManager.h 中添加成员函数 int isExist(int id);

	//按照职工编号判断职工是否存在,若存在返回职工在数组中位置,不存在返回-1
	int isExist(int id);

10.3 职工是否存在函数实现

workerManager.cpp 中实现成员函数 int isExist(int id);

int WorkerManager::isExist(int id)
{
	int count = -1;
	for (int i = 0; i < this->m_EmpNum; i++)
	{
		if (this->m_EmpArray[i]->m_Id == id)
		{
			count = i;
			break;
		}
	}
	return count;
}

10.4 删除职工函数实现

workerManager.cpp中实现成员函数 void Del_Emp();

void WorkerManager::del_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
	}
	else
	{
		int id = -1;
		std::cout << "请输入你要删除的职工编号: ";
		std::cin >> id;
		int result = isExist(id);

		if (result != -1)
		{
			for (int i = result; i < this->m_EmpNum - 1; i++)
			{
				this->m_EmpArray[i] = this->m_EmpArray[i + 1];
			}
			this->m_EmpNum--;
			this->save();
			std::cout << "删除成功" << std::endl;
		}
		else
		{
			std::cout << "没有找到职工编号为[" << id << "]的员工" << std::endl;
		}

	}

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

11. 修改职工

功能描述:能够按照职工的编号对职工信息进行修改并保存

11.1 修改职工函数声明

workerManager.h 中添加成员函数 void mod_Emp();

	//修改职工
	void mod_Emp();

11.2 修改职工函数实现

workerManager.cpp 中实现成员函数 void_mod_Emp();

void WorkerManager::mod_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
		return;
	}

	int id = -1;
	std::cout << "请输入你要修改的职工编号: ";
	std::cin >> id;
	int result = isExist(id);

	if (result != -1)
	{
		this->m_EmpArray[result]->showInfo();
		
		int id;
		std::string name;
		int deptId;

		std::cout << "请输入修改的职工编号: ";
		std::cin >> id;

		std::cout << "请输入修改的职工姓名: ";
		std::cin >> name;

		std::cout << "请选择该职工的岗位" << std::endl;
		std::cout << "1.普通员工" << std::endl;
		std::cout << "2.经理" << std::endl;
		std::cout << "3.老板" << std::endl;
		std::cin >> deptId;

		Worker* modWorker = NULL;
		switch (deptId)
		{
		case 1:
			modWorker = new Employee(id, name, 1);
			break;
		case 2:
			modWorker = new Manager(id, name, 2);
			break;
		case 3:
			modWorker = new Boss(id, name, 3);
			break;
		default:
			break;
		}
		this->m_EmpArray[result] = modWorker;
		this->save();
		std::cout << "修改成功,修改后的信息如下" << std::endl;
		this->m_EmpArray[result]->showInfo();
	}
	else
	{
		std::cout << "没有找到职工编号为[" << id << "]的员工" << std::endl;
	}

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

为什么不能直接覆盖?

没有真正改变子类对象,假如数组中是这样的

//直接操纵数组中存放的值
this->m_EmpArray[result].m_Id;
this->m_EmpArray[result].m_Name;
this->m_EmpArray[result].m_deptId;

类型没有变化,那么你就拥有了这个类型的所有函数。试想一下,假如一位普通员工升职成为经理了,但是它的类型仍然是Employee,而Manager中所有的权限他都没有,所以直接覆盖值是不对的

image-20230802214107033

12. 查找职工

功能描述:提供两种查找职工方式,一种按照职工编号,一种按照职工姓名

12.1 查找职工函数声明

workerManager.h 中添加成员函数 void find_Emp();

	//查找职工
	void find_Emp();

12.2 查找职工函数实现

workerManager.cpp 中实现成员函数 void find_Emp();

void WorkerManager::find_Emp()
{
	std::cout << "请输入查找的方式:" << std::endl;
	std::cout << "1.按员工编号查找" << std::endl;
	std::cout << "2.按员工姓名查找" << std::endl;
	int choise = 0;
	std::cin >> choise;

	if (choise == 1)
	{
		int id;
		std::cout << "请输入你要查找的员工编号: ";
		std::cin >> id;
		int result = isExist(id);

		if (result != -1)
		{
			std::cout << "查找成功,员工信息如下:" << std::endl;
			this->m_EmpArray[result]->showInfo();
		}
		else
		{
			std::cout << "没有找到职工编号为[" << id << "]的员工" << std::endl;
		}
	}
	else if (choise == 2)
	{
		std::string name;
		std::cout << "请输入你要查找的员工姓名: ";
		std::cin >> name;

		bool flag = false;
		for (int i = 0; i < this->m_EmpNum; i++)
		{
			if (this->m_EmpArray[i]->m_Name == name)
			{
				std::cout << "查找成功,员工信息如下:" << std::endl;
				this->m_EmpArray[i]->showInfo();
				flag = true;
			}
		}
		if (flag == false)
		{
			std::cout << "没有找到职工姓名为[" << name << "]的员工" << std::endl;
		}
	}
	else
	{
		std::cout << "输入有误,请重新输入" << std::endl;
	}

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

13. 职工排序

功能描述:按照职工编号进行排序,排序的顺序由用户指定

13.1 排序函数声明

workerManager.h 中添加成员函数 void sort_Emp();

	//排序职工
	void sort_Emp();

13.2 排序函数实现

workerManager.cpp 中实现成员函数 void sort_Emp();

void WorkerManager::sort_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
		system("pause");
		system("cls");
	}
	else
	{
		std::cout << "请输入排序的方式:" << std::endl;
		std::cout << "1.按员工编号升序" << std::endl;
		std::cout << "2.按员工编号降序" << std::endl;
		
		int choise = 0;
		std::cin >> choise;
		
		//升序
		for (int i = 0; i < this->m_EmpNum; i++)
		{
			int Min_Or_Max = i;
			for (int j = i + 1; j < this->m_EmpNum; j++)
			{
				if (choise == 1)
				{
					//前一个大于后一个,就移动min指针
					if (this->m_EmpArray[Min_Or_Max]->m_Id > this->m_EmpArray[j]->m_Id)
					{
						Min_Or_Max = j;
					}
					//前一个小于后一个,继续往后比较
				}
				else if (choise == 2)
				{
					//前一个小于后一个,就移动max指针
					if (this->m_EmpArray[Min_Or_Max]->m_Id < this->m_EmpArray[j]->m_Id)
					{
						Min_Or_Max = j;
					}
					//前一个大于后一个,继续往后比较
				}
			}
			//一轮比较后,如果标记位置变了,交换位置
			if (Min_Or_Max != i)
			{
				Worker* tempWorker = this->m_EmpArray[i];
				this->m_EmpArray[i] = this->m_EmpArray[Min_Or_Max];
				this->m_EmpArray[Min_Or_Max] = tempWorker;
			}
		}
		this->save();
		std::cout << "排序完成,排序后的结果如下:" << std::endl;
		this->show_Emp();
	}
}

该排序算法选用 选择排序 难度不大,如果没有算法基础可以去看算法可视化动画,没有基础的人看完一般在1个小时内能够写出来大致的思路

14. 清空文件

功能描述:将文件中记录数据清空

14.1 清空函数声明

workerManager.h 中声明函数 void clean_File();

	//清空文件
	void clean_File();

14.2 清空函数实现

workerManager.cpp 中实现成员函数 void clean_File();

void WorkerManager::clean_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
	}
	else
	{
		std::cout << "请确认是否需要清空?" << std::endl;
		std::cout << "1.清空" << std::endl;
		std::cout << "2.返回" << std::endl;

		int choise = 0;
		std::cin >> choise;

		if (choise == 1)
		{
			std::ofstream ofs(FILENAME, std::ios::trunc);
			ofs.close();
			if (this->m_EmpArray != NULL)
			{
				for (int i = 0; i < this->m_EmpNum; i++)
				{
					delete this->m_EmpArray[i];
					this->m_EmpArray[i] = NULL;

				}
				delete[] this->m_EmpArray;
				this->m_EmpArray = NULL;
				this->m_EmpNum = 0;
				this->m_FileIsEmpty = true;
			}
			std::cout << "清空成功" << std::endl;
		}
	}

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

源代码及文件结构

├─头文件
│      boss.h
│      employee.h
│      worker.h
│      workerManager.h
│
├─源文件
│      boss.cpp
│      employee.cpp
│      EmploySys.cpp
│      manager.cpp
│      workerManager.cpp

项目关系图:

image-20230803183739601

1. 员工类

1.1 员工抽象类 Worker — 基类

worker.h

#pragma once
#include <iostream>

class Worker
{
public:
	int m_Id;
	std::string m_Name;
	int m_DeptId;

	virtual void showInfo() = 0;
	virtual std::string getDeptName() = 0;
};

1.2 普通员工类 Employee — 派生类

Employee.h

#pragma once
#include <iostream>
#include "worker.h"

class Employee :public Worker
{
public:
	Employee(int id, std::string name, int deptId);

	void showInfo();
	std::string getDeptName();
};

Employee.cpp

#include "employee.h"

Employee::Employee(int id, std::string name, int deptId)
{
	this->m_Id = id;
	this->m_Name = name;
	this->m_DeptId = deptId;
}

void Employee::showInfo()
{
	std::cout
		<< "职工编号: " << this->m_Id
		<< " \t职工姓名: " << this->m_Name
		<< " \t岗位: " << this->getDeptName()
		<< " \t岗位职责: 完成经理交给的任务" << std::endl;
}

std::string Employee::getDeptName()
{
	return std::string("普通员工");
}

1.3 经理类 Manager — 派生类

Manager.h

#pragma once
#include <iostream>
#include "worker.h"

class Manager :public Worker
{
public:
	Manager(int id, std::string name, int deptId);

	void showInfo();
	std::string getDeptName();
};

Manager.cpp

#include "manager.h"

Manager::Manager(int id, std::string name, int deptId)
{
	this->m_Id = id;
	this->m_Name = name;
	this->m_DeptId = deptId;
}

void Manager::showInfo()
{
	std::cout
		<< "职工编号: " << this->m_Id
		<< " \t职工姓名: " << this->m_Name
		<< " \t岗位: " << this->getDeptName()
		<< " \t岗位职责: 完成老板交给的任务,并下发任务给员工" << std::endl;
}

std::string Manager::getDeptName()
{
	return std::string("经理");
}

1.4 老板类 Boss — 派生类

Boss.h

#pragma once
#include <iostream>
#include "worker.h"

class Boss :public Worker
{
public:
	Boss(int id, std::string name, int deptId);

	void showInfo();
	std::string getDeptName();
};

Boss.cpp

#include "boss.h"

Boss::Boss(int id, std::string name, int deptId)
{
	this->m_Id = id;
	this->m_Name = name;
	this->m_DeptId = deptId;
}

void Boss::showInfo()
{
	std::cout
		<< "职工编号: " << this->m_Id
		<< " \t职工姓名: " << this->m_Name
		<< " \t岗位: " << this->getDeptName()
		<< " \t岗位职责: 管理公司所有事务" << std::endl;
}

std::string Boss::getDeptName()
{
	return std::string("老板");
}

2. 员工管理类

该类用于声明和实现主界面的所有操作

workerManager.h

#pragma once
#include <iostream>
#include <fstream>
#include "worker.h"
#include "employee.h"
#include "manager.h"
#include "boss.h"

#define FILENAME "empFile.txt"

class WorkerManager
{
public:
	int m_EmpNum;
	Worker** m_EmpArray;
	bool m_FileIsEmpty;

	WorkerManager();

	void showMenu();
	void exitSystem();
	void add_Emp();
	void save();
	int get_EmpNum();
	void init_Emp();
	void show_Emp();
	int isExist(int id);
	void del_Emp();
	void mod_Emp();
	void find_Emp();
	void sort_Emp();
	void clean_Emp();

	~WorkerManager();
};

workerManager.cpp

#include "workerManager.h"

WorkerManager::WorkerManager()
{
	//文件不存在
	std::ifstream ifs(FILENAME, std::ios::in);
	if (!ifs.is_open())
	{
		//std::cout << "文件不存在" << std::endl;
		this->m_EmpNum = 0;
		this->m_EmpArray = NULL;
		this->m_FileIsEmpty = true;
		ifs.close();
		return;
	}

	//文件存在,但没有内容
	char buf;
	ifs >> buf;
	//只读文件里的第一个位置,看看是否是空的
	if (ifs.eof())
	{
		//std::cout << "文件为空" << std::endl;
		this->m_EmpNum = 0;
		this->m_EmpArray = NULL;
		this->m_FileIsEmpty = true;
		ifs.close();
		return;
	}

	//文件存在,并且记录数据
	int num = this->get_EmpNum();
	this->m_EmpNum = num;
	this->m_EmpArray = new Worker * [this->m_EmpNum];
	this->init_Emp();
}

void WorkerManager::showMenu()
{
	std::cout << "********************************************" << std::endl;
	std::cout << "*********  欢迎使用职工管理系统! **********" << std::endl;
	std::cout << "*************  0.退出管理程序  *************" << std::endl;
	std::cout << "*************  1.增加职工信息  *************" << std::endl;
	std::cout << "*************  2.显示职工信息  *************" << std::endl;
	std::cout << "*************  3.删除离职职工  *************" << std::endl;
	std::cout << "*************  4.修改职工信息  *************" << std::endl;
	std::cout << "*************  5.查找职工信息  *************" << std::endl;
	std::cout << "*************  6.按照编号排序  *************" << std::endl;
	std::cout << "*************  7.清空所有文档  *************" << std::endl;
	std::cout << "********************************************" << std::endl;
	std::cout << std::endl;
}

void WorkerManager::exitSystem()
{
	std::cout << "欢迎下次使用" << std::endl;
	exit(0);
}

void WorkerManager::add_Emp()
{
	std::cout << "请输入添加职工的数量: " << std::endl;
	int addNum = 0;
	std::cin >> addNum;

	if (addNum > 0)
	{
		int newSize = this->m_EmpNum + addNum;
		Worker** newSpace = new Worker * [newSize];

		//假如文件内不为空,申请数组将文件中的内容读到内存中操作
		if (this->m_EmpArray != NULL)
		{
			//把原有的数组都移动到新开辟的内存中
			for (int i = 0; i < this->m_EmpNum; i++)
			{
				newSpace[i] = this->m_EmpArray[i];
			}
		}

		//假如文件为空或不为空,则直接开辟后添加
		for (int i = 0; i < addNum; i++)
		{
			int id;
			std::string name;
			int deptId;

			std::cout << "请输入第[" << i + 1 << "]个职工编号: ";
			std::cin >> id;

			std::cout << "请输入第[" << i + 1 << "]个职工姓名: ";
			std::cin >> name;

			std::cout << "请选择该职工的岗位" << std::endl;
			std::cout << "1.普通员工" << std::endl;
			std::cout << "2.经理" << std::endl;
			std::cout << "3.老板" << std::endl;
			std::cin >> deptId;

			Worker* newWorker = NULL;
			switch (deptId)
			{
			case 1:
				newWorker = new Employee(id, name, 1);
				break;
			case 2:
				newWorker = new Manager(id, name, 2);
				break;
			case 3:
				newWorker = new Boss(id, name, 3);
				break;
			default:
				break;
			}
			newSpace[this->m_EmpNum + i] = newWorker;
		}

		delete[] this->m_EmpArray;
		this->m_EmpArray = newSpace;
		this->m_EmpNum = newSize;
		this->m_FileIsEmpty = false;

		std::cout << "成功添加" << addNum << "人" << std::endl;
		this->save();
	}
	else
	{
		std::cout << "输入有误,请重新输入!" << std::endl;
	}

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

void WorkerManager::save()
{
	std::ofstream ofs(FILENAME, std::ios::out);

	for (int i = 0; i < this->m_EmpNum; i++)
	{
		ofs
			<< this->m_EmpArray[i]->m_Id << " "
			<< this->m_EmpArray[i]->m_Name << " "
			<< this->m_EmpArray[i]->m_DeptId << std::endl;
	}

	ofs.close();
}

int WorkerManager::get_EmpNum()
{
	std::ifstream ifs(FILENAME, std::ios::in);

	int id;
	std::string name;
	int deptId;

	int count = 0;
	//这种方法会使文件内容为空的情况下仍然返回1,造成缓冲区溢出
	/*
	char buf[1024] = { 0 };
	while (ifs.getline(buf, sizeof(buf)))
	{
		num++;
	}
	*/

	while (ifs >> id && ifs >> name && ifs >> deptId)
	{
		count++;
	}
	ifs.close();

	return count;
}

void WorkerManager::init_Emp()
{
	std::ifstream ifs(FILENAME, std::ios::in);

	int id;
	std::string name;
	int deptId;

	int index = 0;
	while (ifs >> id && ifs >> name && ifs >> deptId)
	{
		Worker* worker = NULL;
		if (deptId == 1)
		{
			worker = new Employee(id, name, deptId);
		}
		else if (deptId == 2)
		{
			worker = new Manager(id, name, deptId);
		}
		else
		{
			worker = new Boss(id, name, deptId);
		}
		this->m_EmpArray[index] = worker;
		index++;
	}
	ifs.close();
}

void WorkerManager::show_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
	}
	else
	{
		for (int i = 0; i < m_EmpNum; i++)
		{
			this->m_EmpArray[i]->showInfo();
		}
	}

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

int WorkerManager::isExist(int id)
{
	int count = -1;
	for (int i = 0; i < this->m_EmpNum; i++)
	{
		if (this->m_EmpArray[i]->m_Id == id)
		{
			count = i;
			break;
		}
	}
	return count;
}

void WorkerManager::del_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
	}
	else
	{
		int id = -1;
		std::cout << "请输入你要删除的职工编号: ";
		std::cin >> id;
		int result = isExist(id);

		if (result != -1)
		{
			for (int i = result; i < this->m_EmpNum - 1; i++)
			{
				this->m_EmpArray[i] = this->m_EmpArray[i + 1];
			}
			this->m_EmpNum--;
			this->save();
			std::cout << "删除成功" << std::endl;
		}
		else
		{
			std::cout << "没有找到职工编号为[" << result << "]的员工" << std::endl;
		}
	}

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

void WorkerManager::mod_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
	}
	else
	{
		int id = -1;
		std::cout << "请输入你要修改的职工编号: ";
		std::cin >> id;
		int result = isExist(id);

		if (result != -1)
		{
			this->m_EmpArray[result]->showInfo();

			int id;
			std::string name;
			int deptId;

			std::cout << "请输入修改的职工编号: ";
			std::cin >> id;

			std::cout << "请输入修改的职工姓名: ";
			std::cin >> name;

			std::cout << "请选择该职工的岗位" << std::endl;
			std::cout << "1.普通员工" << std::endl;
			std::cout << "2.经理" << std::endl;
			std::cout << "3.老板" << std::endl;
			std::cin >> deptId;

			Worker* modWorker = NULL;
			switch (deptId)
			{
			case 1:
				modWorker = new Employee(id, name, 1);
				break;
			case 2:
				modWorker = new Manager(id, name, 2);
				break;
			case 3:
				modWorker = new Boss(id, name, 3);
				break;
			default:
				break;
			}
			this->m_EmpArray[result] = modWorker;
			this->save();
			std::cout << "修改成功,修改后的信息如下" << std::endl;
			this->m_EmpArray[result]->showInfo();
		}
		else
		{
			std::cout << "没有找到职工编号为[" << id << "]的员工" << std::endl;
		}
	}

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

void WorkerManager::find_Emp()
{
	std::cout << "请输入查找的方式:" << std::endl;
	std::cout << "1.按员工编号查找" << std::endl;
	std::cout << "2.按员工姓名查找" << std::endl;
	int choise = 0;
	std::cin >> choise;

	if (choise == 1)
	{
		int id;
		std::cout << "请输入你要查找的员工编号: ";
		std::cin >> id;
		int result = isExist(id);

		if (result != -1)
		{
			std::cout << "查找成功,员工信息如下:" << std::endl;
			this->m_EmpArray[result]->showInfo();
		}
		else
		{
			std::cout << "没有找到职工编号为[" << id << "]的员工" << std::endl;
		}
	}
	else if (choise == 2)
	{
		std::string name;
		std::cout << "请输入你要查找的员工姓名: ";
		std::cin >> name;

		bool flag = false;
		for (int i = 0; i < this->m_EmpNum; i++)
		{
			if (this->m_EmpArray[i]->m_Name == name)
			{
				std::cout << "查找成功,员工信息如下:" << std::endl;
				this->m_EmpArray[i]->showInfo();
				flag = true;
			}
		}
		if (flag == false)
		{
			std::cout << "没有找到职工姓名为[" << name << "]的员工" << std::endl;
		}
	}
	else
	{
		std::cout << "输入有误,请重新输入" << std::endl;
	}

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

void WorkerManager::sort_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
		system("pause");
		system("cls");
	}
	else
	{
		std::cout << "请输入排序的方式:" << std::endl;
		std::cout << "1.按员工编号升序" << std::endl;
		std::cout << "2.按员工编号降序" << std::endl;

		int choise = 0;
		std::cin >> choise;

		//升序
		for (int i = 0; i < this->m_EmpNum; i++)
		{
			int Min_Or_Max = i;
			for (int j = i + 1; j < this->m_EmpNum; j++)
			{
				if (choise == 1)
				{
					//前一个大于后一个,就移动min指针
					if (this->m_EmpArray[Min_Or_Max]->m_Id > this->m_EmpArray[j]->m_Id)
					{
						Min_Or_Max = j;
					}
					//前一个小于后一个,继续往后比较
				}
				else if (choise == 2)
				{
					//前一个小于后一个,就移动max指针
					if (this->m_EmpArray[Min_Or_Max]->m_Id < this->m_EmpArray[j]->m_Id)
					{
						Min_Or_Max = j;
					}
					//前一个大于后一个,继续往后比较
				}
			}
			//一轮比较后,如果标记位置变了,交换位置
			if (Min_Or_Max != i)
			{
				Worker* tempWorker = this->m_EmpArray[i];
				this->m_EmpArray[i] = this->m_EmpArray[Min_Or_Max];
				this->m_EmpArray[Min_Or_Max] = tempWorker;
			}
		}
		this->save();
		std::cout << "排序完成,排序后的结果如下:" << std::endl;
		this->show_Emp();
	}
}

void WorkerManager::clean_Emp()
{
	if (this->m_FileIsEmpty)
	{
		std::cout << "文件不存在或记录为空" << std::endl;
	}
	else
	{
		std::cout << "请确认是否需要清空?" << std::endl;
		std::cout << "1.清空" << std::endl;
		std::cout << "2.返回" << std::endl;

		int choise = 0;
		std::cin >> choise;

		if (choise == 1)
		{
			std::ofstream ofs(FILENAME, std::ios::trunc);
			ofs.close();
			if (this->m_EmpArray != NULL)
			{
				for (int i = 0; i < this->m_EmpNum; i++)
				{
					delete this->m_EmpArray[i];
					this->m_EmpArray[i] = NULL;

				}
				delete[] this->m_EmpArray;
				this->m_EmpArray = NULL;
				this->m_EmpNum = 0;
				this->m_FileIsEmpty = true;
			}
			std::cout << "清空成功" << std::endl;
		}
	}

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

WorkerManager::~WorkerManager()
{
	if (this->m_EmpArray != NULL)
	{
		for (int i = 0; i < this->m_EmpNum; i++)
		{
			delete this->m_EmpArray[i];
		}
		delete[] this->m_EmpArray;
		this->m_EmpArray = NULL;
	}
}

3. Main函数主体

负责调用我们写好的函数

main.cpp

#include <iostream>
#include "workerManager.h"
#include "worker.h"
#include "employee.h"
#include "manager.h"
#include "boss.h"

int main()
{
	WorkerManager wm;

	int choise = 0;
	while (true)
	{
		wm.showMenu();

		std::cout << "请输入你的选择: " << std::endl;
		std::cin >> choise;
		
		switch (choise)
		{
		case 0: //退出系统
			wm.exitSystem();
			break;
		case 1: //添加职工
			wm.add_Emp();
			break;
		case 2: //显示职工
			wm.show_Emp();
			break;
		case 3: //删除职工
			wm.del_Emp();
			break;
		case 4: //修改职工
			wm.mod_Emp();
			break;
		case 5: //查找职工
			wm.find_Emp();
			break;
		case 6: //排序职工
			wm.sort_Emp();
			break;
		case 7: //清空文件
			wm.clean_Emp();
			break;
		default:
			system("cls");
			break;
		}
	}
	
	return 0;
}

标签:实战,std,cout,管理系统,int,EmpArray,void,C++,id
From: https://www.cnblogs.com/sarexpine/p/17604478.html

相关文章

  • 125.C++中的size_t
    125.C++中的size_t1.size_t●size_t是一些C/C++标准在stddef.h中定义的,size_t类型表示C中任何对象所能达到的最大长度,它是无符号整数●它是为了方便系统之间的移植而定义的,不同的系统上,定义size_t可能不一样。size_t在32位系统上定义为unsignedint,也就是32位无符号整型。在64......
  • C++ STL
    1.初始头文件c++标准库不包括.h,#include;c旧库需要包括.h,#include<stdio.h>;c新库在旧库前面加c,不需要包含.h,#include。旧头文件不被封装在std命名空间中。网站资源www.cplusplus.comcppreference.comgcc.gnu.org书籍2.STL体系结构部件六大部件:容器、分配器、......
  • C++ | extern "C" 的用法
    extern"C"是C++中的一种用法(无法在C语言中使用),其作用是修饰一段代码,将其用C语言的方式进行编译。那么,使用C语言方式进行编译与使用C++方式进行编译又有什么区别呢?在C++中,支持函数重载:voidfunc();voidfunc(inta,intb);voidfunc(doublea,floatb);但在C语言中如果......
  • 【智慧校园】智慧班牌管理系统
    【智慧校园】智慧班牌管理系统源码智慧班牌智慧班牌是一款校园多媒体交互终端与信息展示终端,集学生管理、班级管理、校园管理于一身,融合学校教务管理、教师管理、学籍管理、考勤、信息发布、班级文明建设、校园风采、家校互通等一系列应用,为校园管理现代化、信息化提供有效解决工具......
  • 【完结15章】React18+TS 通用后台管理系统解决方案落地实战
    课程下载——【完结15章】React18+TS通用后台管理系统解决方案落地实战 提取码:qwu4 给大家分享一套课程——React18+TS通用后台管理系统解决方案落地实战,已完结15章,附源码+笔记。TypeScript是微软开发的一个开源的编程语言,通过在JavaScript的基础上添加静态类型定义构建而成......
  • C++基础
    Talkischeap.Showmethecode.C++分为C++语言和C++标准库 版本演化可分为C++98(1.0),C++11(2.0),C++14话不多说,上代码头文件命名方式,例如complex.h首先要写防卫式声明,以前写的时候只是知道要写,现在知道才叫什么。1#ifndef_MYCOMPLEX_2#define_MYCOMPLEX_34......
  • Linux平台C++读写Word文档(DuckX库)
    1、安装cmake如果没有cmake或者cmake版本太旧,都需要进行重新安装此次推荐直接安装编译好的软件包进入官网:https://cmake.org/download/下载后直接在拷贝到系统里进行解压添加环境变量vim/etc/profile添加下面这条命令,路径换成自己安装的路径exportPATH=$PATH:/root......
  • c++
    1,2章输出printf(    输入scanf(一,变量通用形式<类型名><变量名>变量名=标识符(不能用数字开头,不能用关键字/保留字)前缀const【不变的】即锁定变量值(不允许改变)若变量要作为赋值则变量初始时要赋值(初始化) eg:inta; =》inta=0;二,浮点数类型名:int整点   do......
  • 分布式流处理组件-生产实战:Broker副本与优化
    ......
  • Netty 原理解析与实战开发(二)
    Netty原理解析与开发实战八、ChannelHandler8.1ChannelHandler介绍我们对数据的处理都是在ChannelHandler中完成的,Netty提供了众多ChannelHandler的实现类来帮助我们实现一些网络编程中通用功能,比如最常用的心跳检测、数据编解码等。Netty中的ChannelHandler分为两类,一类处......