C++项目实战之职工管理系统
职工管理系统
1. 管理系统需求
职工管理系统可以用来管理公司内所有员工的信息,利用C++来实现一个基于多态的职工管理系统
公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责
-
普通员工职责:完成经理交给的任务
-
经理职责:完成老板交给的任务,并下发任务给员工
-
老板职责:管理公司所有事务
管理系统中需要实现的功能如下:
- 退出管理程序:退出当前管理系统
- 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
- 显示职工信息:显示公司内部所有职工的信息
- 删除离职职工:按照编号删除指定的职工
- 修改职工信息:按照编号修改职工个人信息
- 查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
- 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
- 清空所有文档:清空文件中记录的所有职工信息 (清空前需要再次确认,防止误删)
2. 创建管理类
管理类负责的内容如下:
- 与用户的沟通菜单界面
- 对职工增删改查的操作
- 与文件的读写交互
2.1 创建文件
在头文件和源文件的文件夹下分别创建 workerManager.h
和 workerManager.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;
}
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 选项中,调用退出程序的接口
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.h
和 employee.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.h
和 manager.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.h
和 boss.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;
}
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. 文件交互——读文件
功能描述:将文件中的内容读取到程序中
虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中数据读取到程序中
而我们的程序功能中还有清空文件的需求
因此构造函数初始化数据的情况分为三种
- 第一次使用,文件未创建
- 文件存在,但是数据被用户清空
- 文件存在,并且保存职工的所有数据
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中所有的权限他都没有,所以直接覆盖值是不对的
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
项目关系图:
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;
}