一、管理系统需求
1.1 公司职工分类
- 普通职工:完成经理交给的任务
- 经理:完成老板交给的任务,并下任务给员工
- 老板:管理公司所有的事务
1.2 管理系统中需要实现的功能
- 退出管理程序:退出当前管理系统
- 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
- 显示职工信息:显示公司内部所有职工的信息
- 删除离职职工:按照编号删除指定的职工
- 修改职工信息:按照编号修改职工的个人信息
- 查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
- 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
- 清空所有文档:清空文件中记录的所有职工信息(需要二次确认)
二、创建管理类
- 管理类负责的内容如下:
- 与用户的沟通菜单页面
- 对职工的增删改查操作
- 与文件的读写交互
2.1 main函数
#include <iostream>
#include "workerManager.h"
int main() {
workerManager wm;
int choice = 0;//记录用户的选择
while (true) {
wm.showMenu();
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;
}
}
return 0;
}
2.2 workerManager.h
#pragma once
#include <iostream>
using namespace std;
class workerManager{
public:
workerManager();
~workerManager();
};
2.3 workManager.cpp
#include "workerManager.h"
workerManager::workerManager() {}
workerManager::~workerManager() {}
三、菜单功能
- 创建
showMenu()
函数3.1 workerManager.h
void showMenu();
3.2 workerManager.cpp
void workerManager::showMenu() { 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; }
四、退出功能
- 创建
exitSystem()
函数4.1 workerManager.h
void exitSystem();
4.2 workerManager.cpp
void workerManager::exitSystem() { cout << "欢迎下次使用!" << endl; system("pause"); exit(0); }
五、创建职工类
- 创建一个抽象职工类,具体职工类型继承抽象类
5.1 建立抽象类文件 Worker.h
```Cpp #pragma once
#include#include using namespace std;
// 创建Worker抽象类
class Worker {
public:
virtual void showInfo() = 0;
virtual string getDeptName() = 0;
int m_Id;
string m_Name;
int m_workerDeptId; }; ``` ##### 5.2 创建普通员工类 ###### 5.2.1 头文件 ```Cpp #pragma once #include <iostream> #include <string> using namespace std; #include "Worker.h"
class Employee : public Worker {
public:
Employee(int id, string name, int deptId);
void showInfo() override;
string getDeptName() override;
};
###### 5.2.2 Cpp源文件
```Cpp
#include "Employee.h"
Employee::Employee(int id, std::string name, int deptId) {
m_Id = id;
m_Name = name;
m_workerDeptId = deptId;
}
void Employee::showInfo() {
cout << "编号:" << this->m_Id
<< "\t姓名:" << this->m_Name
<< "\t岗位:" << this->getDeptName()
<< "\t职责:完成经理交给的任务" << endl;
}
string Employee::getDeptName() {
return string("员工");
}
5.3 创建经理类
5.3.1 头文件
#pragma once
#include <iostream>
#include <string>
using namespace std;
#include "Worker.h"
class Manager : public Worker {
public:
Manager(int id, string name, int deptId);
void showInfo() override;
string getDeptName() override;
};
5.3.2 Cpp源文件
#include "Manager.h"
Manager::Manager(int id, std::string name, int deptId) {
m_Id = id;
m_Name = name;
m_workerDeptId = deptId;
}
void Manager::showInfo() {
cout << "编号:" << this->m_Id
<< "\t姓名:" << this->m_Name
<< "\t岗位:" << this->getDeptName()
<< "\t职责:完成老板交给的任务,并下任务给员工" << endl;
}
string Manager::getDeptName() {
return string("经理");
}
5.4 创建老板类
5.4.1 头文件
#pragma once
#include <iostream>
#include <string>
using namespace std;
#include "Worker.h"
class Boss : public Worker {
public:
Boss(int id, string name, int deptId);
void showInfo() override;
string getDeptName() override;
};
5.4.2 Cpp源文件
#include "Boss.h"
Boss::Boss(int id, std::string name, int deptId) {
m_Id = id;
m_Name = name;
m_workerDeptId = deptId;
}
void Boss::showInfo() {
cout << "编号:" << this->m_Id
<< "\t姓名:" << this->m_Name
<< "\t岗位:" << this->getDeptName()
<< "\t职责:管理公司所有的事务" << endl;
}
string Boss::getDeptName() {
return string("老板");
}
六、添加职工
6.1 功能分析
- 功能描述:批量添加职工,并且保存到文件中
- 如果想把所有种类的员工都放在一个数组中,可以将所有员工的指针维护到一个数组里;
- 如果想在程序中维护这个不定长度的数组,可以将数组创建在堆区,并利用
Worker**
的指针维护6.2 功能实现
```Cpp void workerManager::exitSystem() { cout « “欢迎下次使用!” « endl; system(“pause”); exit(0); }
void workerManager::addWorker() { int addNum;
cout << "请输入要添加的员工的数量" << endl;
cin >> addNum;
if (addNum > 0) {
// 新员工的人数
int newSize = this->workerNum + addNum;
// 为新加的员工开辟一块新空间
// Worker ** 是一个二级指针,指向一个指向Worker的指针
// new Worker *[newSize] 中的 Worker* 是表示数组中的每个元素都是一个Worker*的指针
Worker **newSpace = new Worker *[newSize];
// 将原空间中的元素放在新空间中
if (workerArray != NULL) {
for (int i = 0; i < workerNum; i++) {
newSpace[i] = workerArray[i];
}
}
// 输入新职工
for (int i = 0; i < addNum; i++) {
// 员工编号
int id;
// 员工姓名
string name;
// 员工部门
int did;
cout << " 请输入第 " << i + 1
<< " 个新员工的员工编号: " << endl;
// 判断员工id是否存在
while (true) {
cin >> id;
int ret = this->IsExist(id);
if (ret != -1) {
cout << "该编号已经被占用,请重新输入:" << endl;
}
else {
break;
}
}
cout << " 请输入第 " << i + 1
<< " 个新员工的姓名: " << endl;
cin >> name;
cout << " 请输入第 " << i + 1
<< " 个新员工的部门编号: " << endl;
cout << "1. 普通职员" << endl;
cout << "2. 经理" << endl;
cout << "3. 老板" << endl;
cin >> did;
// 创建一个抽象父类指针
Worker *worker;
// 使用多态创建不同类型的员工
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;
}
newSpace[workerNum + i] = worker;
}
// 释放原来的内存
delete[] this->workerArray;
// 将指针指向新内存
this->workerArray = newSpace;
// 更新员工数量
this->workerNum = newSize;
// 保存文件到指定路径
save();
// 更新文件为空标志位
this->m_FileIsEmpty = false;
// 提示信息
cout << "添加 " << addNum << " 个新员工成功" << endl;
}
else {
cout << "输入有误" << endl;
}
system("pause");
system("cls"); } ```
七、文件交互 - 写文件
- 将文件保存在指定位置
void workerManager::save() { ofstream ofs; // 写方式打开文件 ofs.open(FILENAME, ios::out); if (!ofs.is_open()) { cout << "打开文件失败" << endl; return; } // 写数据 for (int i = 0; i < this->workerNum; i++) { ofs << this->workerArray[i]->m_Id << " " << this->workerArray[i]->m_Name << " " << this->workerArray[i]->m_workerDeptId << endl; } // 关闭文件 ofs.close(); cout << "员工文件更新在:" << FILENAME << endl; }
八、文件交互 - 读文件
8.1 功能分析
- 功能描述:将文件中的内容读取到程序中
- 构造函数初始化分为三种情况:
- 第一次使用,文件未创建
- 文件存在,但是数据被用户清空
- 文件存在,并且保存职工的所有数据
8.2 功能实现
- 读文件的功能都实现在
workerManager
的构造函数中8.1 文件未创建
// 1、文件不存在 if (!ifs.is_open()) { cout << "文件不存在" << endl; // 员工人数置空 this->workerNum = 0; // 员工数组置空 this->workerArray = NULL; // 初始化文件为空标志位 this->m_FileIsEmpty = true; ifs.close(); return; }
8.2 文件为空
```Cpp
// 2、文件存在但为空
char ch;
ifs » ch;
// ifs.eof()返回一个布尔值,若为真则为文件尾
if (ifs.eof()) {
cout « “文件为空” « endl;
// 员工人数置空
this->workerNum = 0;
// 员工数组置空
this->workerArray = NULL;
// 初始化文件为空标志位
this->m_FileIsEmpty = true;
ifs.close();
return; } ``` ###### 8.3 文件存在且不为空 1. 需要创建一个函数`getNum`获得文件中的员工个数
```Cpp
// 获取文件中员工的数量
int workerManager::getNum() {
int num = 0;
int id;
string name;
int dId;
ifstream ifs;
ifs.open(FILENAME, ios::in);
if (!ifs.is_open()) {
cout << "文件打开异常" << endl;
return -1;
}
// 使用流文件读取,空格为一个分隔符
while (ifs >> id && ifs >> name && ifs >> dId) {
num++;
}
return num;
}
``` 1. 将文件中的人员读取到维护的`workArray`数组中
```Cpp
// 从文件初始化员工列表
void workerManager::initWorker() {
ifstream ifs;
ifs.open(FILENAME, ios::in);
if (!ifs.is_open()) {
cout << "文件打开异常" << endl;
return;
}
Worker *worker = NULL;
int id;
string name;
int dId;
int index = 0;
// 读取文件
while (ifs >> id && ifs >> name && ifs >> dId) {
switch (dId) {
case 1:
worker = new Employee(id, name, dId);
break; // 千万别忘了break!!!
case 2:
worker = new Manager(id, name, dId);
break;
case 3:
worker = new Boss(id, name, dId);
break;
}
this->workerArray[index++] = worker;
}
// 关闭文件
ifs.close();
}
``` 1. 整合功能
```Cpp
// 3、文件存在且不为空
else {
cout << "现在的员工人数为:" << this->getNum() << endl;
this->workerNum = this->getNum();
this->m_FileIsEmpty = false;
// 为员工列表开辟空间
this->workerArray = new Worker *[this->workerNum];
// 初始化员工列表
initWorker();
for (int i = 0; i < this->workerNum; i++) {
cout << this->workerArray[i]->m_Name << endl;
}
}
``` ###### 8.4 初始化完毕 ```Cpp workerManager::workerManager() {
ifstream ifs;
ifs.open(FILENAME, ios::in);
// 1、文件不存在
if (!ifs.is_open()) {
cout << "文件不存在" << endl;
// 员工人数置空
this->workerNum = 0;
// 员工数组置空
this->workerArray = NULL;
// 初始化文件为空标志位
this->m_FileIsEmpty = true;
ifs.close();
return;
}
// 2、文件存在但为空
char ch;
ifs >> ch;
// ifs.eof()返回一个布尔值,若为真则为文件尾
if (ifs.eof()) {
cout << "文件为空" << endl;
// 员工人数置空
this->workerNum = 0;
// 员工数组置空
this->workerArray = NULL;
// 初始化文件为空标志位
this->m_FileIsEmpty = true;
ifs.close();
return;
}
// 3、文件存在且不为空
else {
cout << "现在的员工人数为:" << this->getNum() << endl;
this->workerNum = this->getNum();
this->m_FileIsEmpty = false;
// 为员工列表开辟空间
this->workerArray = new Worker *[this->workerNum];
// 初始化员工列表
initWorker();
for (int i = 0; i < this->workerNum; i++) {
cout << this->workerArray[i]->m_Name << endl;
}
} } ``` #### 九、显示职工 ```Cpp // 显示员工信息 void workerManager::showWorkers() {
if (this->m_FileIsEmpty) {
cout << "员工列表为空" << endl;
system("pause");
system("cls");
return;
}
else {
for (int i = 0; i < this->workerNum; i++) {
this->workerArray[i]->showInfo();
}
}
system("pause");
system("cls"); } ``` #### 十、删除职工 ##### 10.1 删除前先判断员工是否存在 ```Cpp // 判断员工是否存在 int workerManager::IsExist(int id) {
int index = -1;
for (int i = 0; i < this->workerNum; i++) {
if (workerArray[i]->m_Id == id) {
index = i;
break;
}
}
return index; } ``` ##### 10.2 删除员工,需要二次确认 ```Cpp // 删除员工 void workerManager::Del_Emp() {
if (this->m_FileIsEmpty) {
cout << "文件为空" << endl;
system("pause");
return;
}
int id;
cout << "请输入要删除的员工Id:" << endl;
cin >> id;
int confirm = 0;
cout << "确认删除?(此操作不可撤销)" << endl;
cout << "1. 确认" << endl;
cout << "2. 取消" << endl;
cin >> confirm;
if (confirm == 1) {
int ret = IsExist(id);
if (ret != -1) {
for (int i = ret; i < this->workerNum; i++) {
this->workerArray[i] = this->workerArray[i + 1];
}
// 更新人数
this->workerNum--;
// 保存到文件
this->save();
// 输出提示信息
cout << "删除成功" << endl;
}
else {
cout << "查无此人" << endl;
system("pause");
system("cls");
return;
}
}
else {
cout << "操作取消" << endl;
}
system("pause");
system("cls"); } ```
十一、修改职工
- 修改职工前直接把原先的职工内存释放,再根据员工部门重新创建
// 修改员工信息 void workerManager::Mod_Emp() { if (this->m_FileIsEmpty) { cout << "文件为空" << endl; return; } int id; cout << "请输入要修改的员工Id:" << endl; cin >> id; int ret = IsExist(id); if (ret != -1) { delete this->workerArray[ret]; int newID; string newName; int newDId; cout << "请输入此员工修改后的id:" << endl; cin >> newID; cout << "请输入此员工修改后的姓名:" << endl; cin >> newName; cout << "请输入此员工修改后的部门编号:" << endl; cin >> newDId; Worker *worker = NULL; switch (newDId) { case 1: worker = new Employee(newID, newName, newDId); break; // 千万别忘了break!!! case 2: worker = new Manager(newID, newName, newDId); break; case 3: worker = new Boss(newID, newName, newDId); break; } this->workerArray[ret] = worker; } // 保存文件 this->save(); }
十二、查找职工
- 功能:根据id或者姓名查找员工
- 根据姓名查找需要找到所有同名的员工
// 使用id或者姓名查找员工 void workerManager::Search_Emp() { if (this->m_FileIsEmpty) { cout << "文件为空" << endl; system("pause"); system("cls"); return; } int SChoice = 0; cout << "请输入你要查找的方式:" << endl; cout << "1. 按编号查找" << endl; cout << "2. 按姓名查找" << endl; cin >> SChoice; if (SChoice == 1) { int id; cout << "请输入要查找的员工Id:" << endl; cin >> id; int ret = IsExist(id); if (ret != -1) { this->workerArray[ret]->showInfo(); } else { cout << "查无此人" << endl; system("pause"); system("cls"); return; } } // 按姓名查找需要查出所有同名的人 else if (SChoice == 2) { string name; cout << "请输入要查找的员工姓名:" << endl; cin >> name; bool flag = false; for (int i = 0; i < this->workerNum; i++) { if (this->workerArray[i]->m_Name == name) { flag = true; this->workerArray[i]->showInfo(); } } if (flag == false) { cout << "查无此人" << endl; return; } } system("pause"); system("cls"); }
十三、排序
- 功能:根据员工编号进行升序或者降序排列
// 给员工排序 void workerManager::Sort_Emp() { if (this->m_FileIsEmpty) { cout << "文件为空" << endl; system("pause"); system("cls"); return; } cout << "请选择排序方式:" << endl; cout << "1. 升序" << endl; cout << "2. 降序" << endl; int select; cin >> select; for (int i = 0; i < this->workerNum; i++) { int originMin = i; for (int j = i + 1; j < this->workerNum; j++) { if (select == 1) { if (this->workerArray[originMin]->m_Id > this->workerArray[j]->m_Id) { originMin = j; } } else if (select == 2) { if (this->workerArray[originMin]->m_Id < this->workerArray[j]->m_Id) { originMin = j; } } else { cout << "您输入的排序方式有误" << endl; return; } } if (originMin != i) { Worker *temp = workerArray[i]; workerArray[i] = workerArray[originMin]; workerArray[originMin] = temp; } } // 保存文件 cout << "排序成功" << endl; this->save(); this->showWorkers(); }
十四、清空文件
14.1 清空文件操作
- 功能:删除所有的员工信息
// 清空员工信息 void workerManager::Clear_Emp() { if (this->m_FileIsEmpty) { cout << "文件为空" << endl; system("pause"); system("cls"); return; } int comfirm = 0; cout << "确认删除所有员工信息吗?(此操作不可撤回)" << endl; cout << "1. 确认" << endl; cout << "2. 取消" << endl; cin >> comfirm; if (comfirm == 1) { ofstream ofs; // trunc 重写覆盖 ofs.open(FILENAME, ios::trunc); ofs.close(); if (this->workerArray != NULL) { for (int i = 0; i < this->workerNum; i++) { if (workerArray[i] != NULL) { delete workerArray[i]; } } } delete[] this->workerArray; this->workerNum = 0; this->m_FileIsEmpty = true; cout << "成功清除所有员工细信息" << endl; } else { cout << "操作取消" << endl; } system("pause"); system("cls"); }
14.2 workManager的析构函数
workerManager::~workerManager() { // 释放堆区内存 if (this->workerArray != NULL) { for (int i = 0; i < this->workerNum; i++) { if (workerArray[i] != NULL) { delete workerArray[i]; } } delete[] this->workerArray; } }
十五、主程序
```Cpp #include “workerManager.h” #include
using namespace std;
int main() { workerManager wm; int choice = 0; // 记录用户的选择 while (true) { wm.showMenu(); cout « “请输入您的选择:” « endl; cin » choice; switch (choice) { case 0: // 退出管理系统 wm.exitSystem(); break; case 1: // 增加职工信息 wm.addWorker(); break; case 2: // 显示职工信息 wm.showWorkers(); break; case 3: // 删除职工信息 wm.Del_Emp(); break; case 4: // 修改职工信息 wm.Mod_Emp(); break; case 5: // 查找职工信息 wm.Search_Emp(); break; case 6: // 按照编号排序 wm.Sort_Emp(); break; case 7: // 清空所有文档 wm.Clear_Emp(); break; default: system(“cls”); break; } } return 0; } ```