黑马C++视频的第二个案例:职工管理系统
黑马C++视频的第二个案例:职工管理系统
-
视频链接:https://www.bilibili.com/video/BV1et411b73Z?spm_id_from=333.999.0.0
-
在学习完C++的面向对象部分:封装,继承以及多态还有文件流后的第一个案例,可以作为简单的练习
一.要求分析
-
员工分为三类:普通职工,经理和老板。他们都有员工ID,姓名和职责类型共同属性,以及显示员工信息的共同函数。所以可以将员工类作为抽象类,普通职工类,经理类和老板类作为员工的子类利用多态以实现不同功能。
-
利用一个员工管理类来实现具体的功能函数,且员工类中包含员工人数信息,利用一个指针数组来维护员工信息,再用一个bool变量来判断要求读入的文件是否为空。
-
接下来就是具体功能函数的实现。
二.代码分析
1.利用数组维护员工信息
Worker** workerArr = new Worker*[worker_num];
类似一个workerArr数组,数组中存放的是worker的指针变量,指向堆中具体开辟出的worker空间,所以此处的 workerArr是二级指针。
2.员工管理类的初始化
//构造函数,构造函数时还需判断文件是否存在
WorkerManager::WorkerManager()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
char ch;
//文件不存在情况下初始化
if (!ifs.is_open())
{
this->fileIsEmpty = true;
this->workerArr = NULL;
this->worker_num = 0;
//cout << "文件不存在" << endl;(测试用)
ifs.close();
return;
}
//文件存在但是为空情况下初始化
ifs >> ch;
if (ifs.eof())
{
this->fileIsEmpty = true;
this->workerArr = NULL;
this->worker_num = 0;
//cout << "文件为空" << endl;(测试用)
ifs.close();
return;
}
//文件存在且不为空的情况下初始化
this->fileIsEmpty = false;
this->worker_num = getWorkerNum();
this->workerArr = new Worker * [this->worker_num];
initialize();
//测试代码
//for (int i = 0; i < worker_num; i++)
//{
// cout << workerArr[i]->m_ID << "\t"
// << workerArr[i]->m_name << "\t"
// << workerArr[i]->getDeptName() << endl;
//}
}
void WorkerManager::initialize()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
string name;
int deptID;
int index = 0;
while (ifs >> id && ifs >> name && ifs >> deptID)
{
Worker* worker;
switch (deptID)
{
case 0:
worker = new Employee(id, name);
this->workerArr[index] = worker;
break;
case 1:
worker = new Management(id, name);
this->workerArr[index] = worker;
break;
case 2:
worker = new Boss(id, name);
this->workerArr[index] = worker;
break;
}
index++;
}
}
员工管理类的初始化有些麻烦,分为三种情况:文件不存在,文件存在但是为空和文件存在且不为空。需要通过文件输入流ifstream的对象进行判断,分为三种情况构造对象。利用fileIsEmpty变量判断文件情况。
3.添加员工函数中的部分代码
int newNum = this->worker_num + num;
Worker** newSpace = new Worker * [newNum];
//将原来的指针数组转移至新的数组
if (workerArr != NULL)
{
for (int i = 0; i < worker_num; i++)
{
newSpace[i] = workerArr[i];
}
}
在添加前先计算添加员工后的员工人数,再通过新的员工人数构建新的指针数组,将原来的指针数组复制到新的数组中。
delete[] workerArr;
workerArr = newSpace;
worker_num = newNum;
save();
if (fileIsEmpty == true)
{
fileIsEmpty = false;
}
添加员工完之后别忘了删除原来的指针数组,释放空间。
4.析构函数
WorkerManager::~WorkerManager()
{
for (int i = 0; i < worker_num; i++)
{
delete[] workerArr[i];
workerArr[i] = NULL;
cout << "删除成功" << endl;
}
}
三.代码展示
员工管理类代码:
#include"WorkerManager.h"
//构造函数,构造函数时还需判断文件是否存在
WorkerManager::WorkerManager()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
char ch;
//文件不存在情况下初始化
if (!ifs.is_open())
{
this->fileIsEmpty = true;
this->workerArr = NULL;
this->worker_num = 0;
//cout << "文件不存在" << endl;(测试用)
ifs.close();
return;
}
//文件存在但是为空情况下初始化
ifs >> ch;
if (ifs.eof())
{
this->fileIsEmpty = true;
this->workerArr = NULL;
this->worker_num = 0;
//cout << "文件为空" << endl;(测试用)
ifs.close();
return;
}
//文件存在且不为空的情况下初始化
this->fileIsEmpty = false;
this->worker_num = getWorkerNum();
this->workerArr = new Worker * [this->worker_num];
initialize();
//测试代码
//for (int i = 0; i < worker_num; i++)
//{
// cout << workerArr[i]->m_ID << "\t"
// << workerArr[i]->m_name << "\t"
// << workerArr[i]->getDeptName() << endl;
//}
}
//析构函数
WorkerManager::~WorkerManager()
{
for (int i = 0; i < worker_num; i++)
{
delete[] workerArr[i];
workerArr[i] = NULL;
cout << "删除成功" << endl;
}
}
//界面展示
void WorkerManager::showSelection()
{
cout << "--------------------------------------------------------" << endl;
cout << "--------------------员工管理系统------------------------" << endl;
cout << "--------------------1、增加职工信息---------------------" << endl;
cout << "--------------------2、显示职工信息---------------------" << endl;
cout << "--------------------3、删除职工信息---------------------" << endl;
cout << "--------------------4、修改职工信息---------------------" << endl;
cout << "--------------------5、查找职工信息---------------------" << endl;
cout << "--------------------6、按照编号排序---------------------" << endl;
cout << "--------------------7、清空所有文档---------------------" << endl;
cout << "--------------------8、退出管理程序---------------------" << endl;
cout << "--------------------------------------------------------" << endl;
}
//第一个方法:添加员工,写入文件
void WorkerManager::addWorker()
{
cout << "请选择要添加的员工人数" << endl;
int num;
cin >> num;
int newNum = this->worker_num + num;
Worker** newSpace = new Worker * [newNum];
//将原来的指针数组转移至新的数组
if (workerArr != NULL)
{
for (int i = 0; i < worker_num; i++)
{
newSpace[i] = workerArr[i];
}
}
//添加新的员工
for (int i = 0; i < num; i++)
{
cout << endl;
cout << "下面添加第" << i + 1 << "位员工" << endl;
int id;
cout << "请输入员工的ID" << endl;
cin >> id;
string name;
cout << "请输入员工的姓名" << endl;
cin >> name;
int selection;
cout << "请输入数字选择员工的职位:" << endl;
cout << "1:普通员工" << endl;
cout << "2:经理" << endl;
cout << "3:总裁" << endl;
cin >> selection;
Worker* worker;
switch (selection)
{
case 1:
worker = new Employee(id, name);
newSpace[worker_num + i] = worker;
break;
case 2:
worker = new Management(id, name);
newSpace[worker_num + i] = worker;
break;
case 3:
worker = new Boss(id, name);
newSpace[worker_num + i] = worker;
break;
default:
cout << "选择有误" << endl;
break;
}
}
delete[] workerArr;
workerArr = newSpace;
worker_num = newNum;
save();
if (fileIsEmpty == true)
{
fileIsEmpty = false;
}
system("pause");
system("cls");
}
//第二个方法:显示当前列表中的员工信息
void WorkerManager::display()
{
if (fileIsEmpty == true)
{
cout << "文件不存在或为空" << endl;
}
else
{
for (int i = 0; i < worker_num; i++)
{
workerArr[i]->showInfo();
}
}
system("pause");
system("cls");
}
//第三个方法:删除员工
void WorkerManager::deleteWorker()
{
if (fileIsEmpty == true)
{
cout << "文件不存在或为空" << endl;
}
else
{
cout << "请输入你想删除的员工编号" << endl;
int deleteNum;
cin >> deleteNum;
if (isExist(deleteNum) == -1)
{
cout << "查无此人" << endl;
}
else
{
int pointer = isExist(deleteNum);
for (; pointer < worker_num - 1; pointer++)
{
workerArr[pointer] = workerArr[pointer + 1];
}
workerArr[worker_num - 1] = NULL;
worker_num--;
cout << "删除成功" << endl;
}
save();
}
system("pause");
system("cls");
}
//第四个方法:修改员工信息
void WorkerManager::modMessage()
{
if (fileIsEmpty == true)
{
cout << "文件不存在或为空" << endl;
}
else
{
int selection;
cout << "请输入要修改的员工编号" << endl;
cin >> selection;
int pointer = isExist(selection);
if (pointer == -1)
{
cout << "查无此人" << endl;
}
else
{
cout << "找到该员工,下面输入修改后的信息" << endl;
int tempID;
string tempName;
int tempDeptID;
cout << "请输入员工编号" << endl;
cin >> tempID;
cout << "请输入员工姓名" << endl;
cin >> tempName;
cout << "请选择员工职位" << endl;
cout << "1.普通员工" << endl;
cout << "2.经理" << endl;
cout << "3.总裁" << endl;
int tempSelection;
cin >> tempSelection;
Worker* worker;
switch (tempSelection)
{
case 1:
worker = new Employee(tempID, tempName);
workerArr[pointer] = worker;
break;
case 2:
worker = new Management(tempID, tempName);
workerArr[pointer] = worker;
break;
case 3:
worker = new Boss(tempID, tempName);
workerArr[pointer] = worker;
break;
default:
cout << "选择有误" << endl;
break;
}
cout << "修改成功" << endl;
}
save();
}
system("pause");
system("cls");
}
//第五个方法:通过员工编号或姓名查找员工
void WorkerManager::seekWorker()
{
if (fileIsEmpty == true)
{
cout << "文件不存在或为空" << endl;
}
else
{
cout << "请选择你的查找方式" << endl;
cout << "1.通过员工编号查找" << endl;
cout << "2.通过员工姓名查找" << endl;
int selection = 0;
cin >> selection;
switch (selection)
{
case 1:
{
cout << "请选择你要查找的员工编号" << endl;
int searchID;
cin >> searchID;
int pointer = isExist(searchID);
if (pointer == -1)
{
cout << "查无此人" << endl;
system("pause");
system("cls");
return;
}
else
{
cout << "查找员工的信息如下" << endl;
workerArr[pointer]->showInfo();
system("pause");
system("cls");
return;
}
}
case 2:
{
cout << "输入要查找的员工姓名" << endl;
string searchName;
cin >> searchName;
bool isExist = false;
for (int i = 0; i < worker_num; i++)
{
if (workerArr[i]->m_name == searchName)
{
workerArr[i]->showInfo();
isExist = true;
}
}
if (isExist == false)
{
cout << "查无此人" << endl;
system("pause");
system("cls");
return;
}
system("pause");
system("cls");
return;
}
default:
cout << "输入有误" << endl;
break;
}
}
system("pause");
system("cls");
}
//第六个方法:将文件中的员工通过员工编号排序
void WorkerManager::sortByID()
{
if (fileIsEmpty == true)
{
cout << "文件不存在或为空" << endl;
}
else
{
cout << "请选择你的排序方式" << endl;
cout << "1.通过编号升序排列" << endl;
cout << "2.通过编号降序排列" << endl;
int selection = 0;
cin >> selection;
if (selection == 1)
{
for (int i = 0; i < worker_num; i++)
{
for (int j = i + 1; j < worker_num; j++)
{
if (workerArr[i]->m_ID > workerArr[j]->m_ID)
{
Worker* tempWorker;
tempWorker = workerArr[i];
workerArr[i] = workerArr[j];
workerArr[j] = tempWorker;
}
}
}
cout << "排序成功" << endl;
save();
}
else if (selection == 2)
{
for (int i = 0; i < worker_num; i++)
{
for (int j = i + 1; j < worker_num; j++)
{
if (workerArr[i]->m_ID < workerArr[j]->m_ID)
{
Worker* tempWorker;
tempWorker = workerArr[i];
workerArr[i] = workerArr[j];
workerArr[j] = tempWorker;
}
}
}
cout << "排序成功" << endl;
save();
}
else
{
cout << "输入有误" << endl;
}
}
system("pause");
system("cls");
}
//第七个方法:清空文件
void WorkerManager::emptyFile()
{
if (fileIsEmpty == true)
{
cout << "文件不存在或为空" << endl;
}
else
{
cout << "是否确认清空文件?" << endl;
cout << "输入:Y/N" << endl;
char selection;
cin >> selection;
if (selection == 'Y' || selection == 'y')
{
ofstream ofs;
ofs.open(FILENAME, ios::trunc);
ofs.close();
if (workerArr != NULL)
{
for (int i = 0; i < worker_num; i++)
{
delete workerArr[i];
workerArr[i] = NULL;
}
}
delete[] workerArr;
workerArr = NULL;
fileIsEmpty = true;
cout << "清空成功" << endl;
}
else if (selection == 'N' || selection == 'n')
{
cout << "不执行清空操作" << endl;
}
else
{
cout << "输入有误" << endl;
}
system("pause");
system("cls");
}
}
//第八个方法:退出程序
void WorkerManager::exitProcedure()
{
cout << "欢迎下次使用" << endl;
exit(0);
}
//子方法:保存当前worker数组信息到文件当中
void WorkerManager::save()
{
ofstream ofs;
ofs.open(FILENAME, ios::out);
for (int i = 0; i < worker_num; i++)
{
ofs << workerArr[i]->m_ID << " "
<< workerArr[i]->m_name << " "
<< workerArr[i]->dept_ID << endl;
}
ofs.close();
}
//子方法:帮助初始化
void WorkerManager::initialize()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
string name;
int deptID;
int index = 0;
while (ifs >> id && ifs >> name && ifs >> deptID)
{
Worker* worker;
switch (deptID)
{
case 0:
worker = new Employee(id, name);
this->workerArr[index] = worker;
break;
case 1:
worker = new Management(id, name);
this->workerArr[index] = worker;
break;
case 2:
worker = new Boss(id, name);
this->workerArr[index] = worker;
break;
}
index++;
}
}
//子方法:得到文件中的员工数
int WorkerManager::getWorkerNum()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
string name;
int deptID;
this->worker_num = 0;
while (ifs >> id && ifs >> name && ifs >> deptID)
{
this->worker_num++;
}
return this->worker_num;
}
//子方法:判断所输入的员工编号,查找此人是否存在
int WorkerManager::isExist(int searchID)
{
for (int i = 0; i < worker_num; i++)
{
if (workerArr[i]->m_ID == searchID)
{
return i;
}
}
return -1;
}
抽象类员工类代码:
class Worker
{
public:
int m_ID;//员工ID
int dept_ID;//员工的职位编号
string m_name;//员工姓名
virtual void showInfo() = 0;//显示员工信息
virtual string getDeptName() = 0;//得到员工职位名字
};
主函数代码:
#include<iostream>
#include"WorkerManager.h"
using namespace std;
int main()
{
WorkerManager wm;
while (true)
{
wm.showSelection();
cout << "请输入你的操作" << endl;
int selection;
cin >> selection;
switch (selection)
{
case 1://增加职工信息
wm.addWorker();
break;
case 2://显示职工信息
wm.display();
break;
case 3://删除职工信息
wm.deleteWorker();
break;
case 4://修改职工信息
wm.modMessage();
break;
case 5://查找职工信息
wm.seekWorker();
break;
case 6://按照编号排序
wm.sortByID();
break;
case 7://清空所有文档
wm.emptyFile();
break;
case 8://退出管理程序
wm.exitProcedure();
break;
default:
{
cout << "输入有误" << endl;
exit(0);
}
break;
}
}
system("pause");
return 0;
}
三种员工类代码就不逐一展示。