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



  本案例由于内容较多,故分为三个篇章。

    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++核心编程(六)—— 案例:职工管理系统(中)_C  开发  
  • 测试2:文件存在且有记录情况
      
    C++核心编程(六)—— 案例:职工管理系统(中)_编程开发_02

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

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

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

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++核心编程(六)—— 案例:职工管理系统(中)_编程开发_08   
  • 测试2:需要修改的职工存在的情况
      
       首先,显示已有的职工信息,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_C  开发_06  
      接着,修改职工李四的编号为1,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_编程开发_10   
       然后,再次显示职工信息,发现李四的编号变为1号,确保已经修改成功,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_C  开发_11  
      最后,查看文件empFile中的信息,再次核实职工李四的编号信息已被修改并同步到文件中,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_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++核心编程(六)—— 案例:职工管理系统(中)_C  开发_13   
  • 测试2:按照职工编号查找——查找存在职工
      
    C++核心编程(六)—— 案例:职工管理系统(中)_编程开发_14   
  • 测试3:按照职工姓名查找——查找不存在职工
      
    C++核心编程(六)—— 案例:职工管理系统(中)_编程开发_15   
  • 测试4:按照职工姓名查找——查找存在职工(如果出现重名,也一并显示,在文件中可以添加重名职工)
      
      没有重名的情况,如下所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_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++核心编程(六)—— 案例:职工管理系统(中)_C  开发_19

  • 测试:升序排序
      
    C++核心编程(六)—— 案例:职工管理系统(中)_C  开发_20  
      文件同步更新,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_C  开发_21  
  • 测试:降序排序
      
    C++核心编程(六)—— 案例:职工管理系统(中)_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++核心编程(六)—— 案例:职工管理系统(中)_C  开发_25  
      再次查看职工信息,记录已为空,如下图所示。
      
    C++核心编程(六)—— 案例:职工管理系统(中)_编程开发_26  
      打开文件empFile.txt,里面数据已确保清空,该功能需要慎用!
      
    C++核心编程(六)—— 案例:职工管理系统(中)_编程开发_27

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

16. 附录:完整代码

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