2021-11-12 C++职工管理系统分步代码实现和解析

职工管理系统可以用来管理公司内所有员工的信息
本教程主要利用C++来实现一个基于多态的职工管理系统
公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责普通员工职责:完成经理交给的任务
经理职责:完成老板交给的任务,并下发任务给员工老板职责:管理公司所有事务

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

1、管理系统需求

2、创建项目

简要说一些,头文件workerManager.h中做函数的声明,源文件workerManager.cpp做函数的具体实现,main函数在另外一个源文件中,做具体运行的操作。

3、创建管理类

管理类负责的内容如下:
与用户的沟通菜单界面
对职工增删改查的操作·
与文件的读写交互

4、菜单功能

4.1 添加成员函数 show_menu();

在管理类workerManager.h中添加成员函教 展示菜单 void Show_menu();

4.2 菜单功能实现

太简单了,直接去看代码

4.3测试菜单功能

5、退出功能

在main函数当中进行操作即可。

5.1 提供功能接口

5.2 实现退出功能

5.3 测试功能

6、创建职工类

6.1 创建职工抽象类,父类声明 class worker

职工的分类为:普通员工、经理、老板
将三种职工抽象到一个类(worker)中,利用多态管理不同职工种类职工的属性为:职工编号、职工姓名、职工所在部门编号
职工的行为为:岗位职责信息描述,获取岗位名称

//职工抽象类
class worker
{
public:
	//显示个人信息
	virtual void showinfo() = 0;
	//获取岗位无信息
	virtual string getdeptname() = 0;

	//职工编号
	int m_id;
	//职工姓名
	string m_name;
	//部门编号
	int m_deptid;
};

6.2 创建普通员工类 , 子类声明 class employee

//普通员工文件
class employee : public worker
{
public:
	//构造函数
	employee(int id,string name, int did);
	//显示个人信息
	void showinfo() ;
	//获取岗位无信息
	virtual string getdeptname() ;

};

6.3 普通员工类的函数修改实现

//构造函数
employee::employee(int id, string name, int did)
{
	this->m_id = id;   //初始化
	this->m_name = name; 
	this->m_deptid = did;
}



//显示个人信息
void employee::showinfo()
{
	cout << "职工编号" << this->m_id
		<< "\t职工姓名" << this->m_name
		<< "\t岗位" << this->getdeptname()
		<< "\t岗位职责:完成经理交给的任务" << endl;
}


//获取岗位无信息
string employee::getdeptname()
{
	return string("员工");
}

6.4 创建经理类,子类声明 class manger

//经理类
class manger :public worker
{
public:
	//构造函数
	manger(int id, string name, int did);
	//显示个人信息
	virtual void showinfo();
	//获取岗位无信息
	virtual string getdeptname();
};

6.5 经理类的函数修改实现

//构造函数
manger::manger(int id, string name, int did)
{
	this->m_id = id;   //初始化
	this->m_name = name;
	this->m_deptid = did;
}
//显示个人信息
void manger::showinfo()
{
	cout << "职工编号" << this->m_id
		<< "\t职工姓名" << this->m_name
		<< "\t岗位" << this->getdeptname()
		<< "\t岗位职责:完成董事长交给的任务,并且下发任务给普通的员工" << endl;
}
//获取岗位无信息
string manger::getdeptname()
{
	return string("经理");
}

6.6 创建老板类,子类声明 class boss

//boss类
class boss :public worker
{
public:
	//构造函数
	boss(int id, string name, int did);
	//显示个人信息
	virtual void showinfo();
	//获取岗位无信息
	virtual string getdeptname();

}; 

6.7 经理类的函数修改实现

//构造函数
boss::boss(int id, string name, int did)
{
	this->m_id = id;   //初始化
	this->m_name = name;
	this->m_deptid = did;
}
//显示个人信息
void boss::showinfo()
{
	cout << "职工编号" << this->m_id
		<< "\t职工姓名" << this->m_name
		<< "\t岗位" << this->getdeptname()
		<< "\t岗位职责:管理公司所有的事务" << endl;
}
//获取岗位无信息
string boss::getdeptname()
{
	return string("总裁");
}

6.8 测试多态

7、添加职工

7.1 功能分析

分析:
用户在批量创建时,可能会创建不同种类的职工
如果想将所有不同种类的员工都放入到一个数组中,可以将所有员工的指针维护到一个数组里如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用Worker的指针维护**
2021-11-12 C++职工管理系统分步代码实现和解析_第1张图片

7.2 记录员工人数的函数声明 m_empnum;

int  m_empnum;

7.3 员工数组的指针 worker ** m_emparray();

worker ** m_emparray();

7.4 添加职工的函数声明 add_emp();

void add_mp();

7.3 功能实现

//添加职工
void workermanger::add_emp()
{
	cout << "请输入添加职工数量" << endl;

	int addnum = 0;//保存用户的输入的数量
	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; //职工编号
			string name; //职工姓名
			int dselect; //部门选择

			cout << "请输入第" << i + 1 << "个新职工编号" << endl;
			cin >> id;


			cout << "请输入第" << i + 1 << "个新职工姓名" << endl;
			cin >> name;

			cout << "请选择该职工岗位" << endl;
			cout << "1 普通职工" << endl;
			cout << "2 经理" << endl;
			cout << "3 老板" << endl;
			cin >> dselect;

			worker* worker = NULL;   //防止野指针
			switch (dselect)
			{
			case 1:
				worker = new employee(id, name, 1);
				break;
			case 2:
				worker = new manger(id, name, 2);
				break;
			case 3:
				worker = new boss(id, name, 3);
				break;
			default:
				break;
			}

			//将创建的职工指针 保存到数组中
			newspace[this->m_empnum + i] = worker;
		}
		//释放原有的空间
		delete[] this->m_emparray;  //[] 是因为他是数组

		//更改新空间的指向
		this->m_emparray = newspace;

		//更新新的职工人数
		this->m_empnum = newsize;

		//更新职工不为空的标志
		this->m_fileisempty = false;
		//提示添加成功
		cout << "成功添加" << addnum << "名新职工" << endl;

		//保存数据到文件中
		this->save();
	}
	else
	{
		cout << "输入有误" << endl;

	}
	//按下任意键,清屏回到上级目录
	system("pause");
	system("cls");
}

8、文件交互-写文件

功能描述:对文件进行读写
在上一个添加功能中,我们只是将所有的数据添加到了内存中,一旦程序结束就无法保存了因此文件管理类中需要一个与文件进行交互的功能,对于文件进行读写操作

8.1设定文件路径

#include 
#include FOLENAME "empfile.txt"

8.2成员函数声明 save();

void save();

8.3保存文件功能实现

也就是写入文件,生成文件的过程。

//保存文件
void Workermanger::save()
{
	ofstream ofs;  //创建输出流对象
	ofs.open(FILENAME, ios::out);  //用输出的方式打开文件 ————写文件

	//将每个人数据写入到文件中
	for (int i = 0; i < this->m_empnum; i++)  //将数组指针m_empnum对应的员工的信息指针指到对应的员工信息上
	{
		ofs << this->m_emparray[i]->m_id << ""
			<< this->m_emparray[i]->m_name << ""
			<< this->m_emparray[i]->m_deptid << endl;
	}
	//关闭文件
	ofs.close();
}

8.4保存文件功能测试

9、文件交互-读文件:

功能描述:将文件中的内容读取到程序中
虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中数据读取到程序中而我们的程序功能中还有清空文件的需求
因此构造函数初始化教据的情况分为三种
1.第一次使用,文件未创建
2.文件存在,但是数据被用户清空
3.文件存在,并且保存职工的所有教据

9.1 添加成员属性标志文件是否为空 bool m_fileisempty;

bool m_fileisempty;

9.2 文件不存在

//1 文件不存在
	ifstream ifs;  //读入流
	ifs.open(filename, ios::in); //读文件

	if (!ifs.is_open())
	{
		cout <<"文件不存在" << endl;
		//初始化属性
		this->m_empnum; //初始化记录人数
		this->m_emparray = NULL;  //初始化记录指针
		this->m_fileisempty = true; //初始化文件是否为空
		ifs.close(); 
		return;  //1 return 不带返回值,应用于void,相当于break; 2 return带上返回值,不能应用与void
	}

9.3 文件存在且数据为空

读入文件的一个字符,随便一个字符,然后判断他是不是空的字符,如果是空的字符,说明文件本来就是空的。

//2 文件存在 数据为空
	char ch;
	ifs >> ch;  //读走一个字符
	if (ifs.eof()) //判断是不是结尾
	{
		// 文件为空
		cout << "文件为空" << endl;
		//初始化属性
		this->m_empnum; //初始化记录人数
		this->m_emparray = NULL;  //初始化记录指针
		this->m_fileisempty = true; //初始化文件是否为空
		ifs.close();
		return;  //1 return 不带返回值,应用于void,相当于break; 2 return带上返回值,不能应用与void
	}

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

//3 文件存在,并且记录数据
	int num = this->get_empnum();
	cout << "职工人数为:" << num << endl;
	this->m_empnum = num;
	
	//开辟空间
	this->m_emparray = new worker * [this->m_empnum];  //数组指针
	//将文件中的数据,存到数组中
	this->init_emp();

9.4.1 获取记录的职工人数的成员函数

int get_empnum();

9.4.2 代码实现

//统计文件中人数
int workermanger::get_empnum()
{
	ifstream ifs;
	ifs.open(filename, ios::in);  //打开文件 读
	
	int id;
	string name;
	int did;
	
	int num = 0;
	//cin读取到空格时候会自动结束,所以ifs>>id遇到空格结束,然后继续读取ifs>>name遇到空格结束,然后在读取ifs>>did,这样一行就读取完了
	//流提取符>>会自动跳过输入流里面的空格
	while (ifs >> id && ifs >> name && ifs >> did)
	{
		//统计人数变量
		num++;
	}
	return num;
}

9.4.3 初始化数组的成员函数

void init_emp();

9.4.4 代码实现

输入流读取文件中的内容。并且利用worker的父类多态,new一个指针对象,根据编号来确定指针对象指向哪类员工,指向哪类?哪类就创建对应的对象指向父类,并且进行相应的改写。

//初始化员工
void workermanger::init_emp()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);

	int id;
	string name;
	int did;

	int index = 0;
	while (ifs >> id && ifs >> name && ifs >> did)
	{
		worker* worker = NULL;

		if (did == 1) //普通职工
		{
			worker = new employee(id, name, did);
		}
		else if (did == 2) //经理
		{
			worker = new manger(id, name, did);
		}
		else //老板
		{
			worker = new boss(id, name, did);
		}

		this->m_emparray[index] = worker;
		index++;
	}
	//关闭文件
	ifs.close();
}

10、显示职工

显示当前所有的职工信息

10.1 显示职工函数声明 void show_emp();

void show_emp();

10.2 显示职工函数实现

//显示职工
void workermanger::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.3 测试显示职工

11、删除职工

11.1 删除职工函数声明 void del_emp();

void del_emp();

11.2 职工是否存在函数声明

很多功能都需要用到根据职工是否存在来进行操作如∶删除职工、修改职工、查找职工
因此添加该公告函数,以便后续调用
在workerManager.h中添加成员函数

int IsExist(int id);

11.3 要删除的职工是否存在函数实现

// 判断职工是否存在,如果存在返回职工所在数组的位置,不存在返回-1
int workermanger::isexist(int id)
{
	int index = -1;
	for (int i = 0; i < this->m_empnum; i++)
	{
		if (this->m_emparray[i]->m_id == id)
		{
			//找到职工
			index = i;
			break;
		}
	}
	return index;
}

11.4 删除职工函数实现

==在数组中,删除的意思就是数据的前移!==所以覆盖就完事了。。。

//删除职工
void workermanger::del_emp()
{
	if (this->m_fileisempty) //判断文件是不是空的
	{
		cout << "文件不存在或者记录为空" << endl;
	}
	else
	{
		//按照职工编号删除
		cout << "请输入想要删除的职工编号" << endl;
		int id = 0;
		cin >> id;

		int index = this->isexist(id); //返回职工所在位置

		if (index != -1) //说明职工存在,并且要删掉index位置上的职工
		{
			for (int i = index; i < this->m_empnum - 1; i++)
			{
				//数据前移
				this->m_emparray[i] = this->m_emparray[i + 1];
			}
			this->m_empnum--;//更新数组中记录的人员个数
			//数据同步更新到文件中
			this->save();
			cout << "删除成功!!!" << endl;
		}
		else
		{
			cout << "删除失败,未找到该职工" << endl;
		}
	}
	system("pause");
	system("cls");
}

11.5 测试删除职工

在main函数中进行测试即可,别忘记中括号括起来,因为代码较多。。。。

		{
			int ret = wm.isexist(1);
			if (ret != -1)
			{
				cout << "职工存在" << endl;
			}
			else
			{
				cout << "职工不存在" << endl;
			}
			break;
		}

12、修改职工

12.1 修改职工的成员函数声明 void mod_emp();

void mod_emp();

12.2 代码实现

//修改职工信息
void workermanger::mod_emp()
{
	if (this->m_fileisempty)
	{
		cout << "文件不存在或者记录为空" << endl;
	}
	else
	{
		cout << "请输入修改职工编号:" << endl;
		int id;
		cin >> id;

		int ret = this->isexist(id);
		if (ret != -1)
		{
			//查找到编号的职工
			delete this->m_emparray[ret];  //删除原有位置处的职工信息

			int newid = 0;
			string newname = "";
			int dselect = 0;

			cout << "查找到:" <<id<<"号职中,请输入新的职工号" <<endl;  //输入新的职工的信息
			cin >> newid;

			cout << "请输入新姓名" << endl;
			cin >> newname;

			cout<<  "请输入岗位" << endl;
			cout << "1 普通职工" << endl;
			cout << "2 经理" << endl;
			cout << "3 老板" << endl;
			cin >> dselect;

			worker* worker = NULL;
			switch (dselect)
			{
			case 1:
				worker = new employee(newid, newname, dselect);
				break;
			case 2:
				worker = new manger(newid, newname, dselect);
				break;
			case 3:
				worker = new boss(newid, newname, dselect);
				break;
			default:
				break;
			}

			//将创建的职工指针 保存到数组中
			this->m_emparray[ret] = worker;
			cout << "修改成功!!" << endl;
			//保存到文件中
			this->save();
		}
		else
		{
			cout<< "查无此人" << endl;
		}
	}
	system("pause");
	system("cls");
}

13、查找职工

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

13.1查找职工函数声明 find_emp();

void find_emp();

13.2查找职工函数实现

//查找职工
void workermanger::find_emp()
{
	if (this->m_fileisempty)
	{
		cout << "文件不存在或者记录为空" << endl;
	}
	else
	{
		cout << "请输入查找的方式" << endl;
		cout << "1 按照职工编号查找" << endl;
		cout << "2 按照职工姓名查找" << endl;

		int select = 0;
		cin >> select;

		if (select == 1)
		{
			//按照编号查
			int id;
			cout << "请输入查找的职工编号" << endl;
			cin >> id;

			int ret = isexist(id);
			if (ret != -1)
			{
				//找到职工
				cout << "查找成功!!该职工信息如下" << endl;
				this->m_emparray[ret]->showinfo();
			}
		}
		else if (select == 2)
		{
			//按照姓名查
			string name;
			cout << "请输入查找的姓名" << endl;
			cin >> name;

			//加入一个判断是否查到的标志
			bool flag = false; //默认没有找到

			for (int i = 0; i < m_empnum; i++)
			{
				if (this->m_emparray[i]->m_name == name)
				{
					cout << "查找成功,职工编号为:" << this->m_emparray[i]->m_id
						<< "职工系信息如下" << endl;
					flag = true;

					
					//调用显示信息的接口
					this->m_emparray[i]->showinfo();
				}
			}
			if (flag = false)
			{
				cout << "查找失败,查无此人" << endl;
			}
		}
		else
		{
			cout << "输入选项有误!" << endl;
		}
	}
	system("pause");
	system("cls");
}

13.3测试查找职工

14、排序

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

14.1 排序函数声明

void sort_emp();

14.2 排序函数实现

运用选择算法排序功能进行排序,比如升序排序,就是for循环设第一个下标为最小值,然后再进行一个内循环,找到最小值和第一个下标替换;然后第二个下标再去找最小值,把第二个下标也替换成最小值,长此以往即可。

//按照职工编号排序
void workermanger::sort_emp()
{
	if (this->m_fileisempty)
	{
		cout << "文件不存在或者记录为空" << endl;
		system("pause");
		system("cls");
	}
	else
	{
		cout << "请选择排序方式" << endl;
		cout << "1 按照职工号进行升序" << endl;
		cout << "2 按照职工号进行降序" << endl;

		int select = 0;
		cin >> select;
		for (int i = 0; i <this->m_empnum; i++)
		{
			int minormax = i;  //声明最小值  或者 最大值下标
			for (int j = i + 1; j < this->m_empnum; j++)
			{
				if (select == 1)   //升序  
				{
					if (this->m_emparray[minormax]->m_id > this->m_emparray[j]->m_id)
					{
						minormax = j;
					}
				}
				else //降序
				{
					if (this->m_emparray[minormax]->m_id > this->m_emparray[j]->m_id)
					{
						minormax = j;
					}
				}
			}

			if (i != minormax)
			{
				worker* temp = this->m_emparray[i];
				this->m_emparray[i] = this->m_emparray[minormax];
				this->m_emparray[minormax] = temp;
			}
		}

	}
	cout << "排序完成!排序的结果为" << endl;
	this->save();
	this->show_emp();
}

14.3 测试排序功能

15、清空文件

将文件中记录的数据清空

15.1 清空函数声明 void clean_file();

void clean_file();

15.2 清空函数实现

把该清空的都清空!把设置都设成默认的。。。。。。。

//清空文件
void workermanger::clean_file()
{
	cout << "确定清空?" << endl;
	cout << "1 确定" << endl;
	cout << "2 返回" << endl;

	int select = 0;
	cin >> select;
	if (select == 1)
	{
		//清空文件
		ofstream ofs(filename, 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;
		}

		cout << "清空成功!" << endl;
	}
	system("pause");
	system("cls");
}

15.3 测试清空文件

你可能感兴趣的:(C++,c++,开发语言,后端)