C++职工管理系统

目录

一.基本介绍

二.职工管理系统的要求 

三.菜单和退出管理程序

四.增加职工信息

(1)创建"worker.h"头文件 

(2)创建"employee.h"头文件 

(3)创建"employee.cpp"源文件

 (4)创建"manager.h"头文件(与上面的员工内容很相似)

(5)创建"manager.cpp"源文件(同上) 

(6)创建"boss.h"头文件(同上)

(7)创建"boss.cpp"源文件(同上)

五.显示职工信息

六.文件交互操作 

(1)设定文件路径 

 (2)实现保存文件功能

 (3)文件的读取

 七.删除离职职工

 八.修改职工信息

九. 查找职工信息

十. 按照编号排序

十一.清空所有文档

十二.释放堆区空间

总结


一.基本介绍

本文没有涉及到C++中的STL库,只是使用了C++中的基础知识,是入门级别的编程

其中涉及到:继承,纯虚函数(不会的同志可以先去了解一下)

上面有C++职工管理系统的全部代码,可以自行下载

二.职工管理系统的要求 

公司中职工分为三类:普通员工,经理,老板

显示信息时,需要显示职工编号,职工姓名,职工岗位,以及职责

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

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

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

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

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

三.菜单和退出管理程序

 这两个的写法都很简单,我就写在一起了(首先创建一个"职工管理系统.cpp"来放主函数

首先先创建一个头文件("workeManager.h")去放我们写的接口

class workManager
{
public:
	//展示菜单
	void Show_Menu();

	//退出系统
	void ExitSystem();
};

然后再创建一个源文件("workManager.cpp")去实现我们写的接口(注意引用头文件)

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

void workManager::ExitSystem()
{
	cout << "退出系统成功!!" << endl;
	cout << "欢迎下次使用" << endl;
	system("pause");   //请按任意键继续
	system("cls");     //清屏
	exit(-1);          //退出系统
}

最后通过刚开始创建的"职工管理系统.cpp"去调用菜单接口 (注意引用头文件,后面不再提醒)

int main()
{
	while (1)
	{
		workManager wm;

		wm.Show_Menu();		//调用菜单

		cout << "请输入要选择的程序:";
		int n = 0;
		cin >> n;

		switch (n)   //通过switch去调用接口
		{
		case 1:     //增加职工信息
			break;
		case 2:     //显示职工信息
			break;
		case 3:     //删除离职职工
			break;
		case 4:     //修改职工信息
			break;
		case 5:     //查找职工信息
			break;
		case 6:     //按照编号排序
			break;
		case 7:     //清楚所有文档
			break;
		case 0:     //退出系统
			wm.ExitSystem();  //调用退出接口
			break;
		}
	}
	return 0;
}

四.增加职工信息

  • 因为每类员工都有姓名,职工编号,所在部门编号,所以再增加一个"worker.h"头文件,去抽象出一个职工类,作为父类继承给子类员工
  • 职工有三类员工,经理,老板。   创建头文件源文件:                                             员工:"employee.cpp"和"employee.h"     经理:"manager.cpp"和"manager.h"                老板:"boss.cpp"和"boss.h"    这些头文件写接口,源文件写实现                                (这样写可能很麻烦,但是,可以使我们的逻辑清晰,并且回头看这些代码时很清晰
(1)创建"worker.h"头文件 
class Worker
{
public:
	//显示个人信息
	virtual void showInfo() = 0;  //纯虚函数

	//获取岗位名称
	virtual string getDeptName() = 0;  //纯虚函数

	string m_Name;  //姓名
	int m_Id;       //职工编号
	int m_DeptId;  //职工所在部门编号
};
(2)创建"employee.h"头文件 
class Employee :public Worker  //继承
{
public:
	//构造函数
	Employee(int id, string name, int did);

	//显示个人信息
	virtual void showInfo();

	//获取岗位名称
	virtual string getDeptName();
};
(3)创建"employee.cpp"源文件
//构造函数
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是水平制表符
		<< "\t岗位:" << this->getDeptName()
		<< "\t岗位职责:" << "完成经理交给的任务" << endl;
}

//获取岗位名称
string Employee::getDeptName()
{
	return string("员工");
}
 (4)创建"manager.h"头文件(与上面的员工内容很相似)
class Manager :public Worker
{
public:
	//构造函数
	Manager(int id, string name, int did);

	//显示个人信息
	virtual void showInfo();

	//获取岗位名称
	virtual string getDeptName();
};
(5)创建"manager.cpp"源文件(同上) 
//构造函数
Manager::Manager(int id, string name, int did)
{
	this->m_Id = id;
	this->m_DeptId = did;
	this->m_Name = name;
}

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

//获取岗位名称
string Manager::getDeptName()
{
	return string("经理");
}
(6)创建"boss.h"头文件(同上)
class Boss :public Worker
{
public:
	//构造函数
	Boss(int id, string name, int did);

	//显示个人信息
	virtual void showInfo();

	//获取岗位名称
	virtual string getDeptName();
};
(7)创建"boss.cpp"源文件(同上)
//构造函数
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("老板");
}

写到这里我们可以测试一下,看程序能不能正常运行(在"职工管理系统.cpp"里测试) 

把原来main函数里的东西注释掉,写下面的代码进行测试

int main()
{
	Worker* worker = NULL;
	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;
    return 0;
}

我的测试结果:(说明程序没有错误,测试完就可以删掉或注释掉了)


上面已经实现了员工,经理,老板的类了,下面实现在控制面板手动输入员工

在"workManager.h"头文件中的类中添加五个个接口

    //构造函数
	workManager();
	
    //增加职工
	void Add_Emp();  

	//记录文件中职工个数
	int m_EmpNum;     //后续要写文件操作的内容,来获取文件中的人数,以至于能更好的开辟空间

	//员工数组指针
	Worker** m_EmpArray; //这里使用两个*,因为:我们在录入员工时,使用new在堆区开放空间,也是一个指针,存放一级指针,使用二级指针

	//判断文件是否为空
	bool m_fileIsEmpty;

 在"workManager.cpp"中去实现

//增加职工
void workManager::Add_Emp()
{
	cout << "请输入加入的职工个数:";
	int n = 0;
	cin >> n;
	
	if (n > 0)
	{
		//更新人数
		int NewSize = this->m_EmpNum + n;

		//开辟空间
		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 < n; i++)
		{
			int id;
			string name;
			int did;

			cout << "请输入第" << i + 1 << "个员工的编号:";
			cin >> id;

			cout << "请输入第" << i + 1 << "个员工的姓名:";
			cin >> name;

			cout << "请选择员工的岗位:" << endl;
			cout << "1.员工" << endl;
			cout << "2.经理" << endl;
			cout << "3.老板" << endl;
			cin >> did;

			Worker* worker = NULL;
			switch (did)
			{
			case 1:  //员工
			{
				worker = new Employee(id, name, did);
				break;
			}
			case 2:  //经理
			{
				worker = new Manager(id, name, did);
				break;
			}
			case 3:  //老板
			{
				worker = new Boss(id, name, did);
				break;
			}
			}

			NewSpace[this->m_EmpNum + i] = worker;
		}

		//释放原来的空间
		delete[] this->m_EmpArray;
		this->m_EmpArray = NULL;

		//更新空间内容
		this->m_EmpArray = NewSpace;

		//更新文件不为空
		this->m_fileIsEmpty = false;

		//更新数组大小
		cout << "成功添加" << n << "个职工" << endl;

        //保存到文件中
		this->save();//这个函数下面将会说明
	}
	else
	{
		cout << "输入有误" << endl;
	}
	system("pause");
	system("cls");
}

 配合下面的显示职工信息的操作,我们可以测试一下我们写的代码(把Add_Emp()写道case2中

五.显示职工信息

显示职工信息就比较简单了,可以调用我们之前写的Worker类中的showInfo()接口

在workManager.cpp中去使用workManager的构造函数去初始化一些变量(后期还会再更改)

//构造函数
workManager::workManager()
{
	//初始化人数
	this->m_EmpNum = 0;

	//初始化数组指针
	this->m_EmpArray = NULL;

	//初始化为空
	this->m_fileIsEmpty = true;
}

 显示职工信息的操作:

在"workManager.h"头文件中添加接口

	//显示职工信息
	void Show_Emp();

 在"workManager.cpp"中实现接口(在员工类中有直接写showInfo()的实现,可以直接调用)

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

实现到这,就可以在主函数中去测试了:(我这里是没有问题的,可以显示出来员工)

六.文件交互操作 

上面,我们只是把信息存到了内存中,当程序结束后,内存释放,信息也就没了

所以需要一个与文件交互的功能,对文件进行读写操作

(1)设定文件路径 

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

#include<fstream>
#define FILENAME "test.txt"
 (2)实现保存文件功能

在"workManager.h"中添加接口

	//将数据保存到文件
	void save();

在"workManager.cpp"中去实现接口

//保存文件
void workManager::save()
{
	ofstream ofs;
	ofs.open(FILENAME, ios::out);  //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();  //关闭文件
}

注意: save()接口是将数据保存到文件中,所以应该在添加职工中的Add_Emp()接口中调用

            在Add_Emp()中已经写到,下面就 不再写了

 我们去测试一下(先在程序中录入数据,打开文件的地址就可以看到多出来一个txt文件):

 (3)文件的读取

我们先考虑一下情况

  • txt文件不存在
  • txt文件存在,但是数据为空
  • txt文件存在,数据不为空

一共就这三种情况,需要进行判断,我们将在workManager类构造函数中进行更改

被注释掉的代码是测试代码,可以自行删除去测试

下面的代码中的一些接口我会慢慢说明

//构造函数
workManager::workManager()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);  //ios::in为读文件而打开文件

	//文件不存在的情况
	if (!ifs.is_open())
	{
		//cout << "文件不存在!" << endl;
		this->m_fileIsEmpty = true;  //初始化文件为空
		this->m_EmpNum = 0;		//初始化人数
		this->m_EmpArray = NULL;  //初始化指针
		ifs.close();      //关闭文件
		return;
	}

	//文件存在,数据为空
	char c;
	ifs >> c;
	if (ifs.eof())
	{
		//cout << "文件为空!" << endl;
		this->m_fileIsEmpty = true;  //初始化文件为空
		this->m_EmpNum = 0;		//初始化人数
		this->m_EmpArray = NULL;  //初始化指针
		ifs.close();
		return;
	}

	//文件存在,并且有数据
	int num = this->m_getEmpNum();
	//cout << "职工人数为:" << num << endl;
	this->m_EmpNum = num;


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

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

int m_getEmpNum();接口     获取txt文件中员工的个数

注意:将接口写到"workManager.h"中

//职工个数
int workManager::m_getEmpNum()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in); //打开文件 读取

	int id;
	string name;
	int did = 0;

	int num = 0;
	while (ifs >> id && ifs >> name && ifs >> did)  //一行一行的遍历
	{
		num++;
	}

	ifs.close();//关闭文件
	return num;
}

 void  Init_Emp();接口    是将文件中的数据录入到程序中(能在程序中显示)

注意:将接口写到"workManager.h"中

//初始化职工(将文件中的数据录入到程序中)
void workManager::Init_Emp()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);

	int id;
	string name;
	int did;

	int n = 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 Manager(id, name, did);
		}
		else
		{
			worker = new Boss(id, name, did);
		}
		this->m_EmpArray[n] = worker;
		n++;
	}
}

 文件操作在这里就结束了,可以进行多次不同的测试,看程序是否能运行成功

 七.删除离职职工

在"wokeManager.h"中写接口

	//删除职工
	void Del_Emp();

在"workManager.cpp"中实现接口

//删除职工
void workManager::Del_Emp()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空" << endl;
	}
	else
	{
		int m = 0;
		cout << "请输入要删除的职工号:";
		cin >> m;
		int ret = IsExist(m);   //这个接口是判断员工是否存在
		if (ret == -1)
		{
			cout << "删除失败,职工不存在!" << endl;
		}
		else
		{
			for (int i = ret; i < this->m_EmpNum - 1; i++)
			{
				this->m_EmpArray[i] = this->m_EmpArray[i + 1];
			}
			//更新人数
			this->m_EmpNum--;

			//保存到文件
			this->save();

			cout << "删除员工成功" << endl;
		}
	}
	system("pause");
	system("cls");
}

    int IsExist(int id);的实现        判断职工是否存在 

//判断职工是否存在
int workManager::IsExist(int id)
{
	for (int i = 0; i < this->m_EmpNum; i++)
	{
		if (this->m_EmpArray[i]->m_Id == id)
		{
			return i;
		}
	}
	return -1;
}

接着就是测试,如果没有成功,在认真分析代码,再进行调试

 八.修改职工信息

修改职工信息:通过职工编号找到职工,然后进行修改

注意:将接口写到"workManager.h"中

//修改职工信息
void workManager::Mod_Emp()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空" << endl;
	}
	else
	{
		int n = 0;
		cout << "请输入要修改的职工编号:";
		cin >> n;

		int ret = IsExist(n); //判断职工是否存在
		if (ret == -1)
		{
			cout << "修改失败,职工不存在!" << endl;
		}
		else
		{
			delete this->m_EmpArray[ret];

			cout << "查找到:" << n << "号职工,请输入新的职工信息" << endl;
			int id;
			string name;
			int did;

			cout << "请输入新的职工号:";
			cin >> id;
			cout << "请输入新名字:";
			cin >> name;
			cout << "请输入岗位" << endl;
			cout << "1.员工" << endl;
			cout << "2.经理" << endl;
			cout << "3.老板" << endl;
			cin >> did;

			Worker* worker = NULL;
			switch (did)
			{
			case 1:
                worker = new Employee(id, name, did);
				break;
			case 2:
				worker = new Manager(id, name, did);
				break;
			case 3:
				worker = new Boss(id, name, did);
				break;
			}

			this->m_EmpArray[ret] = worker;  //将新信息保存
		}
	}

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

测试一下 

九. 查找职工信息

查找职工信息:这里分为两种查法  (1)按照职工编号查找  (2)按照职工姓名查找

注意:将接口写到"workManager.h"中

//查找职工
void workManager::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 = 0;
			cout << "请输入要查找的职工号:";
			cin >> id;
			int ret = this->IsExist(id);
			if (ret == -1)
			{
				cout << "查找失败,查无此人" << endl;
			}
			else
			{
				cout << "查找成功,具体信息如下:" << endl;
				this->m_EmpArray[ret]->showInfo();
			}
		}
		else if (select == 2)  //按照姓名查找
		{
			bool flag = false;
			cout << "请输入要查找人的姓名:" << endl;
			string name;
			cin >> name;
			for (int i = 0; i < this->m_EmpNum; i++)
			{
				if (this->m_EmpArray[i]->m_Name == name)
				{
					cout << "查找成功,具体信息如下:" << endl;
					this->m_EmpArray[i]->showInfo();
					flag = true;
					break;
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人" << endl;
			}
		}
		else
		{
			cout << "输入有误" << endl;
		}
	}
	system("pause");
	system("cls");
}

 测试一下

十. 按照编号排序

在这里使用一个非常简单的排序方法(选择排序)

注意:将接口写到"workManager.h"中

//按照职工号排序
void workManager::Sort_Emp()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空" << endl;
	}
	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 (minOrMax != i)
			{
				int tmp = this->m_EmpArray[i]->m_Id;
				this->m_EmpArray[i]->m_Id = this->m_EmpArray[minOrMax]->m_Id;
				this->m_EmpArray[minOrMax]->m_Id = tmp;
			}
		}
		this->save();
		cout << "排序成功" << endl;
	}
	system("pause");
	system("cls");
}

测试一下 

十一.清空所有文档

清空所有文档:将txt文件中的所有数据删除(防止错误操作,增加一层确认删除操作)

注意:将接口写到"workManager.h"中

//清空文件
void workManager::Clean_File()
{
	cout << "确认清空?" << endl;
	cout << "1.确认" << endl;
	cout << "2.返回" << endl;
	int select = 0;
	cin >> select;

	if (select == 1)
	{
		//打开模式ios::trunc
		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_EmpNum = 0;
		delete[] this->m_EmpArray;
		this->m_EmpArray = NULL;
		this->m_fileIsEmpty = true;
		cout << "清空成功" << endl;
	}
	system("pause");
	system("cls");
}

测试代码

到这里还没结束:我们是在堆区开放的空间,最后需要我们手动释放 

十二.释放堆区空间

释放堆区空间:在workManager类的析构函数中去释放空间

注意:将接口写到"workManager.h"中 

	//析构函数
	~workManager();

实现: 

//析构函数
workManager::~workManager()
{
	if (this->m_EmpArray != NULL)
	{
		delete[] this->m_EmpArray;
		this->m_EmpArray = NULL;
	}
}

总结

职工管理系统没有使用很难的算法,只是逻辑比较复杂,只要逻辑清晰,还是很好写出来的

本文也使用了C++中的一些基本的语法,可以更好的帮助我们学习C++

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值