C++核心编程(六)—— 案例:职工管理系统(中)

C++系列内容的学习目录 → \rightarrow C++学习系列内容汇总。

  • 1. 管理系统需求
  • 2. 创建项目
  • 3. 创建管理类
  • 4. 菜单功能
  • 5. 退出功能
  • 6. 创建职工类
  • 7. 添加职工
  • 8. 文件交互 —— 写文件
  • 9. 文件交互 —— 读文件
  • 10. 显示职工
    • 10.1 显示职工函数声明
    • 10.2 显示职工函数实现
    • 10.3 测试显示职工
  • 11. 删除职工
    • 11.1 删除职工函数声明
    • 11.2 职工是否存在函数声明
    • 11.3 职工是否存在函数实现
    • 11.4 删除职工函数实现
    • 11.5 测试删除职工
  • 12. 修改职工
    • 12.1 修改职工函数声明
    • 12.2 修改职工函数实现
    • 12.3 测试修改职工
  • 13. 查找职工
    • 13.1 查找职工函数声明
    • 13.2 查找职工函数实现
    • 13.3 测试查找职工
  • 14. 排序
    • 14.1 排序函数声明
    • 14.2 排序函数实现
    • 14.3 测试排序功能
  • 15. 清空文件
    • 15.1 清空函数声明
    • 15.2 清空函数实现
    • 15.3 测试清空文件
  • 16. 附录:完整代码

  本案例由于内容较多,故分为三个篇章。
    1-9部分的内容见C++核心编程(六)—— 案例:职工管理系统(上)
    10-15部分的内容见C++核心编程(六)—— 案例:职工管理系统(中)
    16部分的内容见C++核心编程(六)—— 案例:职工管理系统(下)

1. 管理系统需求

2. 创建项目

3. 创建管理类

4. 菜单功能

5. 退出功能

6. 创建职工类

7. 添加职工

8. 文件交互 —— 写文件

9. 文件交互 —— 读文件

  1-9部分的内容见C++核心编程(六)—— 案例:职工管理系统(上)。

10. 显示职工

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

10.1 显示职工函数声明

  在workerManager.h中添加成员函数 void Show_Emp();,代码如下所示。

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

10.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.3 测试显示职工

  在switch case语句中case 2:里调用显示职工的接口,代码如下所示。

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

  测试时分别测试文件为空和文件不为空两种情况,测试效果图如下所示。

  • 测试1:文件不存在或者为空情况
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第1张图片  
  • 测试2:文件存在且有记录情况
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第2张图片

  测试完毕,至此,显示所有职工信息功能实现!

11. 删除职工

  功能描述: 按照职工的编号进行删除职工操作。

11.1 删除职工函数声明

  在workerManager.h中添加成员函数void Del_Emp();,代码如下所示。

    void Del_Emp;  //删除职工

11.2 职工是否存在函数声明

  很多功能都需要用到根据职工是否存在来进行操作如:删除职工、修改职工、查找职工。因此添加该功能函数,以便后续调用。在workerManager.h中添加成员函数int IsExist(int id);,代码如下所示。

	int IsExist(int id);  //判断职工是否存在,如果存在,返回职工所在数组,如果不存在,返回-1

11.3 职工是否存在函数实现

  在workerManager.cpp中实现成员函数int IsExist(int id);,代码如下所示。

//判断职工是否存在,如果存在,返回职工所在数组,如果不存在,返回-1
int WorkerManager::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 删除职工函数实现

  在workerManager.h中添加成员函数int IsExist(int id);,代码如下所示。

	void Del_Emp();  //删除职工

  在workerManager.cpp中实现成员函数void Del_Emp();,代码如下所示。

//删除职工
void WorkerManager::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 测试删除职工

  在switch case语句中case 3:里调用删除职工的接口,代码如下所示。

		case 3:  //3. 删除离职职工
			wm.Del_Emp();
			break;

  测试时分别测试文件为空和文件不为空两种情况,测试效果图如下所示。

  • 测试1: 删除不存在职工情况
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第3张图片   

  • 测试2:删除存在的职工情况
      
       首先,在已有职工的基础上,再添加一个职工,显示职工信息,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第4张图片   
      接着,删除1号职工,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第5张图片  
      然后,再次显示已有的职工信息,发现1号职工信息没有了,确保已经删除,如下图所示。
      C++核心编程(六)—— 案例:职工管理系统(中)_第6张图片  
      最后,查看文件empFile中的信息,再次核实1号职工已被完全删除并同步到文件中,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第7张图片

  至此,删除职工功能实现完毕!

12. 修改职工

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

12.1 修改职工函数声明

  在workerManager.h中添加成员函数 void Mod_Emp();,代码如下所示。

	void Mod_Emp();  //修改职工

12.2 修改职工函数实现

  在workerManager.cpp中实现成员函数 void Mod_Emp();,代码如下所示。

//修改职工
void WorkerManager::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 newdeptSelect = 0;

			cout << "查到编号为 " << id << " 号的职工,请输入新的职工编号:" << endl;
			cin >> newId;

			cout << "请输入新的姓名:" << endl;
			cin >> newName;

			cout << "请输入新的岗位:" << endl;
			cout << "1. 员工" << endl;
			cout << "2. 经理" << endl;
			cout << "3. 老板" << endl;
			cin >> newdeptSelect;

			Worker * worker = NULL;
			switch (newdeptSelect)
			{
			case 1:
				worker = new Employee(newId, newName, newdeptSelect);
				break;
			case 2:
				worker = new Manager(newId, newName, newdeptSelect);
				break;
			case 3:
				worker = new Boss(newId, newName, newdeptSelect);
				break;
			default:
				break;
			}

			//更新数据到数组中
			this->m_EmpArray[ret] = worker;
			cout << "修改成功!" << endl;

			//保存到文件中
			this->save();
		}
		else
		{
			cout << "修改失败,查无此人!" << endl;
		}
	}
	system("pause");
	system("cls");
}

12.3 测试修改职工

  在switch case语句中case 4:里调用修改职工的接口,代码如下所示。

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

  测试时分别测试需要修改的职工不存在和存在两种情况,测试效果图如下所示。

  • 测试1:需要修改的职工不存在的情况
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第8张图片   
  • 测试2:需要修改的职工存在的情况
      
       首先,显示已有的职工信息,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第9张图片  
      接着,修改职工李四的编号为1,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第10张图片   
       然后,再次显示职工信息,发现李四的编号变为1号,确保已经修改成功,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第11张图片  
      最后,查看文件empFile中的信息,再次核实职工李四的编号信息已被修改并同步到文件中,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第12张图片
      至此,修改职工功能已实现!

13. 查找职工

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

13.1 查找职工函数声明

  在workerManager.h中添加成员函数 void Find_Emp();,代码如下所示。

	void Find_Emp();  //查找职工

13.2 查找职工函数实现

  在workerManager.cpp中实现成员函数 void Find_Emp();,代码如下所示。

//查找职工
void WorkerManager::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
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		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 << "查找成功!该职工信息如下:" << endl;
					this->m_EmpArray[i]->showInfo();  //调用显示信息的接口

					flag = true;
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else
		{
			cout << "输入的选项有误!" << endl;
		}
	}
	system("pause");
	system("cls");
}

13.3 测试查找职工

  在switch case语句中case 5:里调用查找职工的接口,代码如下所示。

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

  测试时分别测试按照职工编号查找和按照职工姓名查找两种查找方式下的查找职工不存在和存在四种情况,测试效果图如下所示。

  • 测试1:按照职工编号查找——查找不存在职工
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第13张图片   
  • 测试2:按照职工编号查找——查找存在职工
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第14张图片   
  • 测试3:按照职工姓名查找——查找不存在职工
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第15张图片   
  • 测试4:按照职工姓名查找——查找存在职工(如果出现重名,也一并显示,在文件中可以添加重名职工)
      
      没有重名的情况,如下所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第16张图片   
      有重名的情况,例如添加两个张三的职工,然后按照姓名查找张三,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第17张图片

  至此,查找职工功能实现完毕!

14. 排序

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

14.1 排序函数声明

  在workerManager.h中添加成员函数 void Sort_Emp();,代码如下所示。

	void Sort_Emp();  //排序职工

14.2 排序函数实现

  在workerManager.cpp中实现成员函数 void Sort_Emp();,代码如下所示。

//排序职工
void WorkerManager::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 < m_EmpNum; i++)
		{
			int MinOrMax = i;  //声明最小值或最大值下标
			for (int j = i + 1; j < 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 测试排序功能

  在switch case语句中case 6:里调用排序职工的接口,代码如下所示。

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

  测试时分别测试文件不存在和文件存在两种情况,测试效果图如下所示。

  • 测试:文件不存在的情况
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第18张图片

  测试文件存在的情况时,首先我们添加一些职工,序号是无序的,例如下图所示。

C++核心编程(六)—— 案例:职工管理系统(中)_第19张图片

  • 测试:升序排序
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第20张图片  
      文件同步更新,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第21张图片  

  • 测试:降序排序
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第22张图片  
      文件empFile.txt同步更新,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第23张图片

  至此,按照职工编号排序的功能实现完毕!

15. 清空文件

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

15.1 清空函数声明

  在workerManager.h中添加成员函数 void Clean_File();,代码如下所示。

	void Clean_File();  //清空文件

15.2 清空函数实现

  在实现清空函数之前,为把每一个用户创建的数据清除干净,需对析构函数进行改进。

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

  在workerManager.cpp中实现员函数 void Clean_File();,代码如下所示。

//清空文件
void WorkerManager::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 测试清空文件

  在switch case语句中case 7:里调用清空文件的接口,代码如下所示。

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

  测试时分别测试确认清空时的是和否两种情况,测试效果下图所示。

  • 测试:确认清空?否
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第24张图片  
  • 测试:确认清空?是
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第25张图片  
      再次查看职工信息,记录已为空,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第26张图片  
      打开文件empFile.txt,里面数据已确保清空,该功能需要慎用!
      
    C++核心编程(六)—— 案例:职工管理系统(中)_第27张图片

  随着清空文件功能的实现,本案例制作完毕 ^ _ ^

16. 附录:完整代码

  16部分的内容见C++核心编程(六)—— 案例:职工管理系统(下)。

你可能感兴趣的:(C++,c++,编程语言)