C++職工管理系統
職工管理系統
一、 需求
職工管理系統可以用來管理公司所有員工的資訊
本次利用C++來實現一個基於多態的職工管理系統
公司中職工分為三類:普通職工、經理、老闆。顯示資訊時,需要顯示職工編號、職工姓名、職工崗位以及職責
普通員工職責:完成經理布置的任務
經理職責:完成老闆布置的任務,並下發給員工
老闆職責:管理公司所有事務
管理功能中需要實現的功能
- 退出管理程式:退出當前管理系統
- 增加職工資訊:實現批量添加職工資訊,將資訊錄入到文件中,職工資訊為:職工編號、姓名、部門編號
- 顯示職工資訊:顯示公司內部所有職工的資訊
- 刪除離職職工:按照編號刪除指定的職工
- 修改職工資訊:按照編號修改職工個人資訊
- 查找職工資訊:按照職工的編號或者姓名進行查找相關的人員資訊
- 按照編號排序:按照職工編號,進行排序,排序規則由用戶指定
- 清空所有文檔:清空文件中記錄的所有職工資訊(清空前需要再次確認,防止誤觸)
二、 創建管理類
管理類賦值的內容如下
- 與用戶的溝通菜單介面
- 對職工增刪改查的操作
- 與文件的讀寫交互
1、創建文件
在頭文件和源文件的文件夾下面分別創建 workerManger.h 和 workerManger.cpp 文件
2、 頭文件實現
在 workerManager.h 中設計管理類
#pragma once // 防止頭文件重複包含
#include <iostream> // 包含輸入輸出流頭文件
using namespace std; // 使用標準命名空間
class WorkerManager
{
public:
// 構造函數
WorkerManager();
// 析構函數
~WorkerManager();
};
3、 源文件實現
在 workerManager.cpp 中將構造函數和析構函數空實現補全
#include "workerManager.h"
WorkerManager::WorkerManager() {}
WorkerManager::~WorkerManager() {}
三、 菜單功能
功能描述:與用戶的溝通介面
1、 添加成員函數
在管理類 workerManager.h 中添加成員函數 void Show_Menu();
class WorkerManager
{
public:
// 構造函數
WorkerManager();
// 展示菜單
void Show_Menu();
// 析構函數
~WorkerManager();
};
2、 功能實現
在管理類 workerManager.cpp 中實現 Show_Menu() 函數
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;
cout << endl;
}
3、 測試菜單功能
在 職工管理系統.cpp 中測試菜單功能
#include <iostream>
using namespace std;
#include "workerManager.h"
int main()
{
// 實例化管理對象
WorkerManager wm;
// 調用成員函數
wm.Show_Menu();
system("pause");
return 0;
}
四、 退出功能
1、 提供功能介面
在 main() 函數中提供分支選擇,提供每個功能介面
int main()
{
WorkerManager wm;
int choice;
while (true)
{
// 展示菜單
wm.Show_Menu();
cout << "請輸入您的選擇:" << endl;
cin >> choice;
switch (choice)
{
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;
}
}
system("pause");
return 0;
}
2、 實現退出功能
在 workerManager.h 中提供退出系統的成員函數 void exitSystem();
在 workerManager.cpp 中提供具體的功能實現
void WorkerManager::exitSystem()
{
cout << "歡迎下次使用" << endl;
system("pause");
exit(0); // 退出程式
}
五、 創建職工類
1、 創建職工抽象類
職工分為:普通員工、經理、老闆
將三種職工抽象到一個類(worker)中,利用多態管理不同職工種類
職工屬性分為:職工編號、職工姓名、職工所在部門
職工的行為:崗位職責資訊描述、獲取崗位名稱
在頭文件下,創建文件 worker.h 文件並且添加程式碼
#pragma once
#include <iostream>
using namespace std;
// 員工抽象類
class Worker
{
public:
virtual void showInfo() = 0; // 顯示職工資訊
virtual string getDeptName() = 0; // 返回崗位名稱
int m_Id; // 職工編號
string m_Name; // 職工姓名
int m_DeptId; // 部門編號
};
2、 創建普通員工類
在頭文件下,創建 employee.h 頭文件,並且添加程式碼
#pragma once
#include "worker.h"
#include <iostream>
using namespace std;
class Employee : public Worker
{
public:
Employee(int id, string name, int did);
virtual void showInfo(); // 顯示職工資訊
string getDeptName(); // 返回崗位名稱
};
在源文件中,創建 employee.cpp,並且添加程式碼
#include "employee.h"
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("員工");
}
簡單測試
在 職工管理系統.cpp 中添加測試程式碼
Worker* worker = new Employee(1, "張三", 1);
worker->showInfo();
3、 創建經理類
經理類繼承職工抽象類,並重寫父類中純虛函數和普通員工類類似
在頭文件和源文件的文件夾下分別創建 manager.h 和 manager.cpp 文件
manager.h 中程式碼如下
#pragma once
#include <iostream>
using namespace std;
#include "worker.h"
class Manager : public Worker
{
public:
Manager(int id, string name, int did);
virtual void showInfo();
virtual string getDeptName();
};
manager.cpp 中程式碼如下
#include "manager.h"
Manager::Manager(int id, string name, int did)
{
this->m_Id = id;
this->m_Name = name;
this->m_DeptId = did;
}
void Manager::showInfo()
{
cout << "職工編號:" << this->m_Id
<< "\t職工姓名:" << this->m_Name
<< "\t職工崗位:" << this->getDeptName()
<< "\t崗位職責:完成老闆布置的任務,並下發給員工" << endl;
}
string Manager::getDeptName()
{
return string("經理");
}
4、 創建老闆類
老闆類繼承職工抽象類,並重寫父類中純虛函數和普通員工類類似
在頭文件和源文件的文件夾下分別創建 boss.h 和 boss.cpp 文件
在 boss.h 中添加程式碼
#pragma once
#include <iostream>
using namespace std;
#include "worker.h"
class Boss : public Worker
{
public:
Boss(int id, string name, int did);
virtual void showInfo();
virtual string getDeptName();
};
在 boss.cpp 中添加程式碼
#include "boss.h"
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("老闆");
}
5、 程式碼測試
#include <iostream>
using namespace std;
#include "workerManager.h"
#include "worker.h"
#include "employee.h"
#include "manager.h"
#include "boss.h"
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, "Ja", 3);
worker->showInfo();
delete worker;
system("pause");
return 0;
}
六、 添加職工類
功能描述:批量添加職工,並且保存到文件中
1、 功能分析
用戶在批量添加時,可能會創建不同種類的員工
如果想將所有不同種類的員工放入到一個數組中,可以將所有員工的指針維護到一個數組裡面
如果想在程式中維護這個不定長的數組,可以將數組創建到堆區,並利用 Worker** 的指針維護
2、 功能實現
在 WorkerManager.h 頭文件中添加成員屬性和成員函數
// 記錄文件中的人數
int m_EmpNum;
// 員工數組的指針
Worker** m_EmpArr = NULL;
// 注意要導入 worker 頭文件
// 添加職工
void Add_Emp();
workerManager.cpp 實現該函數
#include "employee.h"
#include "manager.h"
#include "boss.h"
// 初始化成員屬性
WorkerManager::WorkerManager(){
// 初始化屬性
this->m_EmpNum = 0;
this->m_EmpArr = NULL;
}
void WorkerManager::Add_Emp()
{
int num; // 保存用戶輸入數量
cout << "請輸入添加職工的人數:" << endl;
cin >> num;
if (num > 0)
{
// 添加人數
// 計算添加空間大小
int newSize = this->m_EmpNum + num; // 新空間大小 = 原來的人數 + 添加人數
// 開闢空間
Worker** newSpace = new Worker* [newSize];
// 將原來空間下數據,拷貝到新空間下
if (this->m_EmpArr)
{
for (int i = 0; i < this->m_EmpNum; i++)
{
newSpace[i] = this->m_EmpArr[i];
}
}
// 添加數據
for (int i = 0; i < num; i++)
{
int id;
string name;
int dSelect; // 部門選擇
cout << "請輸入第" << i + 1 << "個新員工的編號" << endl;
cin >> id;
cout << "請輸入該新員工的姓名" << 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, dSelect);
break;
case 2:
worker = new Manager(id, name, dSelect);
break;
case 3:
worker = new Boss(id, name, dSelect);
break;
default:
cout << "請按照要求輸入!" << endl;
break;
}
// 將創建的職工指針保存到職工數組中
newSpace[this->m_EmpNum + i] = worker;
}
// 釋放原有的空間
delete[] this->m_EmpArr;
// 更改新空間的指向
this->m_EmpArr = newSpace;
// 更新職工人數
this->m_EmpNum = newSize;
this->save();
cout << "成功添加" << num << "名職工" << endl;
}
else
{
// 返回
cout << "輸入錯誤!" << endl;
}
}
delete[] array; 釋放數組空間
七、 文件交互
1、 寫文件
功能描述:對文件進行寫入
在上一個添加功能中,我們只是將所有的數據添加到了記憶體中,一旦程式結束就無法保存了。因此,文件管理類中需要一個與文件進行交互的功能,對於文件進行讀寫操作
1.1 設定文件路徑
首先,我們將文件路徑,在 workerManager.h 中添加宏常量,並且包含 <fstream> 文件
#include <fstream>
#define FILENAME "empFile.txt"
1.2 成員函數聲明
在 workerManager.h 里添加成員函數
// 保存
void save();
1.3 保存功能實現
void WorkerManager::save()
{
ofstream ofs(FILENAME, ios::out);
// 將每個數據寫入到文件中
for (int i = 0; i < this->m_EmpNum; i++)
{
ofs << this->m_EmpArr[i]->m_Id << " "
<< this->m_EmpArr[i]->m_Name << " "
<< this->m_EmpArr[i]->m_DeptId << endl;
}
ofs.close();
}
2、 讀文件
功能描述:將文件中的內容讀取到程式中
雖然我們實現了添加職工後保存文件的操作,但是每次開始運行程式,並沒有將文件中數據讀取到程式中
而我們的程式功能中海油清空文件的需求
因此,構造函數初始化數據的情況分為三種
- 第一次使用,文件未創建
- 文件存在,但是數據被用戶清空
- 文件存在,並且保存職工所有數據
2.1 文件未創建
在 workerManager.h 中添加新的成員屬性 m_FilesEmpty 標誌文件是否為空
// 判斷文件是否為空
bool m_FilesEmpty;
修改 workerManager.cpp 中構造函數程式碼
WorkerManager::WorkerManager(){
// 初始化屬性
// 如果文件不存在
ifstream ifs(FILENAME, ios::in); // 讀文件
if (!ifs.is_open())
{
this->m_EmpNum = 0;
this->m_EmpArr = NULL;
this->m_FilesEmpty = true;
ifs.close();
return;
}
}
2.2 文件存在
2.2.1 文件數據為空
在 workerManager.cpp 中的構造函數追加程式碼
// 文件存在數據為空
char ch;
ifs >> ch;
if (ifs.eof())
{
this->m_EmpNum = 0;
this->m_EmpArr = NULL;
this->m_FilesEmpty = true;
ifs.close();
return;
}
ifstream ifs(FILENAME, ios::in); // 讀文件 char ch; ifs >> ch; isEmpty = ifs.eof(); // 判斷文件是否為空的方法
2.2.2 文件數據存在
2.2.2.1 獲取記錄的職工人數
在 workerManager.h 中添加成員函數 int get_EmpNum();
// 統計員工人數
int get_EmpNum();
在 workerManager.cpp 實現
int WorkerManager::get_EmpNum()
{
ifstream ifs(FILENAME, ios::in);
int id;
string name;
int did;
int num = 0;
while (ifs >> id && ifs >> name && ifs >> did)
{
// 統計人數
num++;
}
return num;
}
2.2.2.2 初始化員工
在 workerManager.h 中添加成員函數void init_Emp();
// 初始化員工
void init_Emp();
在 workerManager.cpp 中實現
void WorkerManager::init_Emp()
{
// 初始化員工
ifstream ifs(FILENAME, ios::in);
int index = 0;
int id;
string name;
int did;
while (ifs >> id && ifs >> name && ifs >> 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_EmpArr[index] = worker;
index++;
}
ifs.close(); // 關閉文件
}
在構造函數追加
// 文件存在且有數據
this->m_EmpNum = this->get_EmpNum();
// 開闢空間
this->m_EmpArr = new Worker * [this->m_EmpNum];
// 將文件中的數據,存到數組中
this->init_Emp();
八、 顯示員工
功能描述:顯示當前所有員工資訊
在 workerManager.h 中添加成員函數void Show_Emp();
// 顯示職工資訊
void Show_Emp();
在 workerManager.cpp 中實現成員函數
void WorkerManager::Show_Emp()
{
// 顯示職工
// 判斷文件是否為空
if (this->m_FilesEmpty)
{
cout << "文件不存在或數據為空" << endl;
}
else
{
for (int i = 0; i < m_EmpNum; i++)
{
// 利用多態調用程式介面
this->m_EmpArr[i]->showInfo();
}
}
// 按任意鍵清屏
system("pause");
system("cls");
}
九、 刪除職工
功能描述:按照職工的編號進行刪除職工操作
1、 刪除職工函數聲明
在 workerManager.h 中添加成員函數void Del_Emp();
// 刪除職工函數
void Del_Emp();
2、 職工是否存在函數聲明
很多功能都需要用到根據職工是否存在來進行操作,如:刪除職工、修改職工、查找職工
因此,添加該函數,以便後續使用
在 workerManager.h 中添加成員函數int IsExist(int id);
// 判斷職工是否存在,存在返回索引,不存在返回 -1
int IsExist(int id); // id查找
int IsExist(string name); // name查找
3、 職工是否存在函數實現
在 workerManager.h 中添加函數
int WorkerManager::IsExist(int id)
{
// 判斷職工是否存在,存在返回索引,不存在返回 -1
for (int i = 0; i < this->m_EmpNum; i++)
{
if (this->m_EmpArr[i]->m_Id == id)
{
return i;
}
}
return -1; // 沒找到返回-1
}
int WorkerManager::IsExist(string name)
{
for (int i = 0; i < this->m_EmpNum; i++)
{
if (this->m_EmpArr[i]->m_Name == name)
{
return i;
}
}
return -1;
}
4、 刪除職工函數實現
在 workerManager.cpp 中添加函數
void WorkerManager::Del_Emp()
{
// 刪除職工函數
if (this->m_FilesEmpty)
{
cout << "文件不存在或數據為空" << endl;
return;
}
else
{
// 按照職工編號刪除職工
int id;
cout << "請輸入要刪除的職工編號:" << endl;
cin >> id;
int num = this->IsExist(id);
if (num == -1) // 說明職工不存在
{
cout << "該職工不存在!";
return;
}
else
{
for (int i = num; i < m_EmpNum - 1 - num; i++)
{
this->m_EmpArr[i] = this->m_EmpArr[i + 1];
}
this->m_EmpNum--; // 更新人員個數
this->save();
cout << "刪除成功" << endl;
system("pause");
system("cls");
}
}
}
十、 修改職工
功能描述:能夠按照職工的編號對職工資訊進行修改並保存
1、 函數聲明
在 workerManager.h 中添加成員函數void Mod_Emp();
// 修改職工
void Mod_Emp();
2、 函數實現
在 workerManager.cpp 中實現成員函數
void WorkerManager::Mod_Emp()
{
if (this->m_FilesEmpty)
{
cout << "文件不存在或數據清空" << endl;
}
else
{
int id;
cout << "請輸入修改職工的編號:" << endl;
cin >> id;
int index = this->IsExist(id);
if (index == -1)
{
cout << "該職工不存在" << endl;
}
else
{
// 職工存在
delete this->m_EmpArr[index];
int newId;
string newName;
int dSelect;
cout << "請輸入修改內容:" << endl;
cout << "請輸入員工的編號" << 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 Manager(newId, newName, dSelect);
break;
case 3:
worker = new Boss(newId, newName, dSelect);
break;
default:
cout << "請按照要求輸入!" << endl;
break;
}
this->m_EmpArr[index] = worker; // 重新存儲
cout << "修改成功" << endl;
this->save();
}
}
system("pause");
system("cls");
}
十一、 查找職工
功能描述:提供兩種查找職工的方式,一種按照職工編號,一種按照職工姓名
1、 查找職工函數聲明
在 workerManager.h 中添加成員函數聲明void Find_Emp();
// 查找職工
void Find_Emp();
2、 查找職工函數實現
void WorkerManager::Find_Emp()
{
if (this->m_FilesEmpty)
{
cout << "文件為空或不存在" << endl;
}
else
{
cout << "請輸入查找方式:" << endl
<< "1、 按照職工編號查找" << "\n"
<< "2、 按照職工姓名查找" << endl;
int choice;
cin >> choice;
switch (choice)
{
case 1:
{
int id;
cout << "請輸入職工編號:" << endl;
cin >> id;
int index = this->IsExist(id);
if (index == -1)
{
cout << "該職工不存在" << endl;
}
else
{
m_EmpArr[index]->showInfo();
}
}
break;
case 2:
{
cout << "請輸入職工姓名:" << endl;
string name;
cin >> name;
int index = this->IsExist(name);
if (index == -1)
{
cout << "該職工不存在" << endl;
}
else
{
m_EmpArr[index]->showInfo();
}
}
break;
default:
cout << "請按照要求輸入" << endl;
break;
}
}
system("pause");
system("cls");
}
十二、 排序
功能描述:按照職工編號進行排序,排序的順序由用戶指定
1、 函數聲明
在 workerManager.h 中添加成員函數void Sort_Emp();
// 排序
void Sort_Emp();
2、 函數實現
在 workerManager.cpp 中添加函數
void WorkerManager::Sort_Emp()
{
if (this->m_FilesEmpty)
{
cout << "文件不存在或文件為空" << endl;
system("pause");
system("cls");
return;
}
else
{
cout << "請輸入排序方式:" << endl
<< "1、 升序排序" << endl
<< "2、 降序排序" << endl;
int choice;
cin >> choice;
for (int i = 0; i < this->m_EmpNum; i++)
{
int minOrmax = i;
for (int j = i + 1; j < this->m_EmpNum; j++)
{
if (choice == 1) // 升序
{
if (this->m_EmpArr[minOrmax]->m_Id > this->m_EmpArr[j]->m_Id)
{
minOrmax = j;
}
}
else
{
if (this->m_EmpArr[minOrmax]->m_Id < this->m_EmpArr[j]->m_Id)
{
minOrmax = j;
}
}
}
Worker* temp = m_EmpArr[minOrmax];
m_EmpArr[minOrmax] = m_EmpArr[i];
m_EmpArr[i] = temp;
}
cout << "排序成功" << endl;
this->Show_Emp(); // 展示資訊
}
}
選擇排序
for (int i = 0; i < this->m_EmpNum; i++) { int minOrmax = i; for (int j = i + 1; j < this->m_EmpNum; j++) { if (choice == 1) // 升序 { if (this->m_EmpArr[minOrmax]->m_Id > this->m_EmpArr[j]->m_Id) { minOrmax = j; } } else { if (this->m_EmpArr[minOrmax]->m_Id < this->m_EmpArr[j]->m_Id) { minOrmax = j; } } } Worker* temp = m_EmpArr[minOrmax]; m_EmpArr[minOrmax] = m_EmpArr[i]; m_EmpArr[i] = temp; }
十三、 清空文件
功能描述:將文件中記錄數據清空
1、 清空函數聲明
在 workerManager.h 中添加成員函數void Clean_File();
// 清空文件
void Clean_File();
2、 函數實現
在 workerManager.cpp 中實現函數
void WorkerManager::Clean_File()
{
cout << "確認清空嗎?" << endl
<< "1、 確認" << endl
<< "2、 取消" << endl;
int choice;
cin >> choice;
switch (choice)
{
case 1:
{
cout << "清除成功" << endl;
// 打開模式:ios::trunc,如果存在刪除文件並重新創建
ofstream ofs(FILENAME, ios::trunc);
ofs.close();
if (this->m_EmpArr) // 刪除堆區數據
{
for (int i = 0; i < m_EmpNum; i++)
{
if (this->m_EmpArr[i])
{
delete this->m_EmpArr[i];
}
}
// 刪除指針
this->m_EmpNum = 0;
delete[] this->m_EmpArr;
this->m_EmpArr = NULL;
this->m_FilesEmpty = true;
}
break;
}
case 2:
cout << "正在取消" << endl;
break;
default:
cout << "請按要求輸入" << endl;
break;
}
system("pause");
system("cls");
}