C++項目實戰之職工管理系統

来源:https://www.cnblogs.com/sarexpine/archive/2023/08/03/17604478.html
-Advertisement-
Play Games

# 職工管理系統 ## 1. 管理系統需求 職工管理系統可以用來管理公司內所有員工的信息,利用C++來實現一個基於多態的職工管理系統 公司中職工分為三類:普通員工、經理、老闆,顯示信息時,需要顯示職工編號、職工姓名、職工崗位、以及職責 + 普通員工職責:完成經理交給的任務 + 經理職責:完成老闆交給 ...


職工管理系統

1. 管理系統需求

職工管理系統可以用來管理公司內所有員工的信息,利用C++來實現一個基於多態的職工管理系統

公司中職工分為三類:普通員工、經理、老闆,顯示信息時,需要顯示職工編號、職工姓名、職工崗位、以及職責

  • 普通員工職責:完成經理交給的任務

  • 經理職責:完成老闆交給的任務,並下發任務給員工

  • 老闆職責:管理公司所有事務

管理系統中需要實現的功能如下:

  • 退出管理程式:退出當前管理系統
  • 增加職工信息:實現批量添加職工功能,將信息錄入到文件中,職工信息為:職工編號、姓名、部門編號
  • 顯示職工信息:顯示公司內部所有職工的信息
  • 刪除離職職工:按照編號刪除指定的職工
  • 修改職工信息:按照編號修改職工個人信息
  • 查找職工信息:按照職工的編號或者職工的姓名進行查找相關的人員信息
  • 按照編號排序:按照職工編號,進行排序,排序規則由用戶指定
  • 清空所有文檔:清空文件中記錄的所有職工信息 (清空前需要再次確認,防止誤刪)

2. 創建管理類

管理類負責的內容如下:

  • 與用戶的溝通菜單界面
  • 對職工增刪改查的操作
  • 與文件的讀寫交互

2.1 創建文件

在頭文件和源文件的文件夾下分別創建 workerManager.hworkerManager.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;
}
image-20230731154542863

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 選項中,調用退出程式的介面

image-20230731155904366

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.hemployee.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.hmanager.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.hboss.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;
}

image-20230731165904709

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. 文件交互——讀文件

功能描述:將文件中的內容讀取到程式中

雖然我們實現了添加職工後保存到文件的操作,但是每次開始運行程式,並沒有將文件中數據讀取到程式中

而我們的程式功能中還有清空文件的需求

因此構造函數初始化數據的情況分為三種

  1. 第一次使用,文件未創建
  2. 文件存在,但是數據被用戶清空
  3. 文件存在,並且保存職工的所有數據

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中所有的許可權他都沒有,所以直接覆蓋值是不對的

image-20230802214107033

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

項目關係圖:

image-20230803183739601

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;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、分支相關操作 1.創建本地分支 使用以下命令創建一個本地分支 git branch <本地分支名> 使用以下命令創建一個本地分支且新建分支從特定分支拉取代碼 git branch <本地分支名> origin/<遠程分支名 or 本地分支名> 2.創建本地分支並切換 使用以下命令創建一個本地分支 ...
  • Nuxt.js是一個基於Vue.js的通用應用框架,主要關註的是應用的UI渲染,利用Vue.js開發服務端渲染的應用所需要的各種配置。 ...
  • 問題描述:初始化渲染後 tabs的下劃線沒有居中對其,出現異位。 問題分析: 網上很多大佬分析過出現原因了 記錄下解決的過程: 在各個論壇搜集到解決方案都暫時無效 有使用v-if重新渲染的 有給類賦值偏移值的 有強行轉換px的 因為各種原因這些方法在自己身上沒有奏效所以記錄下自己解決方案 偏移問題會 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 介紹 canvas:使用腳本 (通常為 JavaScript) 來繪製圖形的 HTML 元素。 本人遍歷了以下兩份文檔,學習完就相當於有了筆和紙,至於最後能畫出什麼,則需要在 canvas 應用方面進一步學習。 MDN 的 Canvas ...
  • 2020 年我有幸加入騰訊 tdmq 初創團隊,當時 tdmq 還正在上雲公測階段,我第一次從一個使用工具的人轉變成了開發工具的人, 這個過程使我沉澱了很多消息隊列知識與設計藝術。 後來在業務中台的實踐中,也頻繁地使用到了 MQ,比如最常見的消息推送,異常信息的重試等等, 過程中也對消息隊列有了更加 ...
  • ##### 延遲和死信隊列的配置 - 延遲隊列有效期一分鐘,後進入死信隊列,如果異常就進入異常隊列 ``` @Configuration @Data public class RabbitMQConfig { /** * 交換機 */ private String orderEventExchang ...
  • [TOC] ### 一、@RequestMapping註解的功能 從註解名稱上我們可以看到,@RequestMapping註解的作用就是將請求和處理請求的控制器方法關聯起來,建立映射關係。 SpringMVC 接收到指定的請求,就會來找到在映射關係中對應的控制器方法來處理這個請求。 ### 二、@R ...
  • 問題代碼: 1 // 目標:使用Properties讀取屬性文件中的內容。 2 // 1、創建properties對象 3 Properties properties = new Properties(); 4 5 6 // 2、使用properties對象載入屬性文件中的鍵值對數據。 7 prop ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...