需求
总体思路:
除主函数外,再创建两个cpp文件:
1.职工类:
1.图示
抽象类(父类):worker
子类:employee,manager,boss
2.思路
运用到了多态的知识:父类指针指向子类对象,如:
worker* wk=new employee(int id,string name,int did);
因为后续要用数组维护职工信息,而数组只能存放相同数据类型的变量。如果想用一个数组存放三种职工的信息,显然不可行。不过用一个数组就可以存放所有的父类指针,再用父类指针指向三种子类对象,就间接实现了用一个数组存放职工信息。
3.代码部分
抽象类(父类):
class Worker
{
public:
virtual void showInfo()=0;
virtual string GetDID()=0;
int m_id;
string m_name;
int m_did;
};
子类.h(定义部分,以员工为例)
class Employee :public Worker
{
public:
Employee(int id,string name,int did);
void showInfo();
string GetDID();
};
子类.cpp(函数实现)
Employee::Employee(int id, string name, int did)
{
m_id = id;
m_name = name;
m_did = did;
}
void Employee::showInfo()
{
cout << "职工编号:" << this->m_id << " "
<< "职工姓名:" << this->m_name << " "
<< "职工岗位:" << this->GetDID() << endl;
}
string Employee::GetDID()
{
return "员工";
}
2.管理类:
1.图示
2.菜单界面
菜单部分单独写一个展示菜单的函数:void show_menu(); //使用cout输出即可
主函数部分:让用户输入选择,再使用switch语句,执行对应操作(具体操作先空着,函数先不做实现)
int select=0;
while (1)
{
wm.show_menu();
cout << "请输入您的选择:" << endl;
cin >> select;
switch (select)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 0:
break;
default:
system("cls");
break;
}
3.创建管理类
class workManager
{
public:
//构造函数
workManager();
//析构函数
~workManager();
//显示菜单
void show_menu();
//0.退出系统
void exit_sys();
//1.添加职工
void add_emp();
//2.显示职工
void show_emp();
//3.删除离职员工
void del_emp();
//4.修改职工信息
void modify_emp();
//5.查找职工
void find_emp();
//6.按照职工编号重新排序
void sort_emp();
//7.清空职工
void clear_emp();
int EmpNum; //职工人数
Worker** EmpArr; //职工数组指针
};
4. 0-退出系统
void workManager::exit_sys()
{
cout << "欢迎下次使用!" << endl;
system("pause");
exit(0);
}
5. 1-添加职工
总体思路:
①让用户输入要添加的人数,计算新的总人数
②根据新人数,开辟新空间
③将原有数据,放到新空间
④添加新的职工信息
⑤修改原指针指向
void workManager::add_emp()
{
cout << "请输入您要添加的职工人数:" << endl;
int addNum;
cin >> addNum;
if (addNum > 0)
{
//开辟新空间
int allNum = this->EmpNum + addNum;
Worker** newArr = new Worker * [allNum];
//把旧空间数据搁进来
if (this->EmpArr!=NULL)
{
for (int i=0;i<this->EmpNum;i++)
{
newArr[i] = this->EmpArr[i];
}
}
//添加新成员
for (int i=0;i<addNum;i++)
{
int id;
string name;
int did;
cout << "请输入第" << i + 1 << "个职工的编号:" << endl;
cin >> id;
cout << "请输入第" << i + 1 << "个职工的姓名:" << endl;
cin >> name;
cout << "请选择第" << i + 1 << "个职工的岗位:" << endl;
cout << "1--员工 2--经理 3--老板" << endl;
cin >> did;
Worker* wk = NULL;
switch (did)
{
case 1:wk = new Employee(id, name, did);
break;
case 2:wk = new Manager(id, name, did);
break;
case 3:wk = new Boss(id, name, did);
break;
default:break;
}
newArr[this->EmpNum+i] = wk;
}
this->EmpNum = allNum;
delete[]this->EmpArr;
EmpArr = newArr;
cout << "成功添加" << addNum << "人" << endl;
Save();
FlafEmpty = false;
}
else
{
cout << "输入有误" << endl;
}
system("pause");
system("cls");
}
6. 写文件
将职工信息保存到文件中,每次对职工数组进行操作(增加、删除、清除、修改)后,都要调用此函数,保存到文件中
用到写文件的操作:
ofstream ofs;
ofs.open("Emptxt", ios::out);
for (int i=0;i<this->EmpNum;i++)
{
ofs << this->EmpArr[i]->m_id << " "
<< this->EmpArr[i]->m_name << " "
<< this->EmpArr[i]->m_did << endl;
}
ofs.close();
7.读文件
读文件的操作可以直接放到管理类的构造函数中(用于初始化属性):
每次打开程序,就可以把文件中的数据读到职工数组中。
构造函数代码:
workManager::workManager()
{
ifstream ifs;
ifs.open("Emptxt", ios::in);
//1.打不开(文件不存在)
if (!ifs.is_open())
{
cout << "文件不存在" << endl;
this->FlafEmpty = true;
this->EmpNum = 0;
this->EmpArr = NULL;
ifs.close();
return;
}
//2.打开为空
int ch;
ifs >> ch;
if (ifs.eof())
{
cout << "文件为空" << endl;
FlafEmpty = true;
this->EmpNum = 0;
this->EmpArr = NULL;
ifs.close();
return;
}
//3.文件中有内容,把文件中的内容读进数组
this->EmpNum = GetSize();
this->EmpArr = new Worker * [EmpNum];
this->FlafEmpty = false;
this->InitEmp();
}
打开程序时存在三种情况:
①第一次打开程序,没有文件
ifs.is_open()
②虽然有文件,但是文件中没有内容
int ch;
ifs >> ch;
if (ifs.eof())
③文件中有内容,将文件中的内容存放到职工数组中,初始化职工数组,人数等
计算文件中的人数:
ifstream ifs;
ifs.open("Emptxt", ios::in);
int id;
string name;
int did;
int num=0;
while (ifs >> id && ifs >> name && ifs >> did)
{
num++;
}
return num;
ifs.close();
初始化职工数组:
ifstream ifs;
ifs.open("Emptxt", ios::in);
int id;
string name;
int did;
int i = 0;
while (ifs >> id && ifs >> name && ifs >> did)
{
Worker* wk = NULL;
switch (did)
{
case 1:wk = new Employee(id, name, did);
break;
case 2:wk = new Manager(id, name, did);
break;
case 3:wk = new Boss(id, name, did);
break;
default:break;
}
EmpArr[i] = wk;
i++;
}
ifs.close();
8. 2-显示职工
用for循环,调用职工的show_info函数即可显示
cout << "当前职工系统共有" << this->EmpNum << "人" << endl;
if (this->EmpNum>0)
{
for (int i=0;i<this->EmpNum;i++)
{
EmpArr[i]->showInfo();
}
}
system("pause");
system("cls");
9. 3-删除职工
数组中删除一个元素的思路是:找到该元素的位置,从这个位置开始,让后面的元素覆盖自己前面的元素
让用户输入职工姓名,用for循环查找该名员工在职工数组里的下标
int workManager::GetIndex(string name)
{
int index = -1;
for (int i=0;i<this->EmpNum;i++)
{
if (this->EmpArr[i]->m_name==name)
{
index = 1;
}
}
return index;
}
删除函数:
cout << "请输入你要删除的员工姓名:" << endl;
string name;
cin >> name;
int index = this->GetIndex(name);
if (index == -1)
{
cout << "没有找到该职工" << endl;
}
else
{
cout << "找到该员工,确认要删除吗?" << endl;
cout << "1--YES 2--NO" << endl;
int select=0;
cin >> select;
if (select == 1)
{
for(int i=index;i<this->EmpNum;i++)
{
this->EmpArr[i] = this->EmpArr[i + 1];
}
this->EmpNum--;
cout << "已为您删除该员工" << endl;
this->Save();
}
if (select == 2)
{
return;
}
}
10. 4-修改职工信息
让用户输入信息后,调用职工对应的构造函数赋值(和添加职工的方式相同),再保存到数组对应位置中
Worker* wk = NULL;
switch (did)
{
case 1:wk = new Employee(id, name, did);
break;
case 2:wk = new Manager(id, name, did);
break;
case 3:wk = new Boss(id, name, did);
break;
default:break;
}
this->EmpArr[index] = wk;
this->Save();
11. 5-查找职工
使用删除职工里的查找对应职工索引的函数,找到职工索引,使用showInfo函数展示该名职工的信息
12. 6-根据职工编号排序
用的是冒泡排序的知识,循环嵌套的方法排序
if (this->EmpNum != 0)
{
for (int i = 0; i < this->EmpNum - 1; i++)
{
for (int j = 0; j < this->EmpNum - 1 - i; j++)
{
if (EmpArr[j]->m_id > EmpArr[j + 1]->m_id)
{
Worker* temp = EmpArr[j];
EmpArr[j] = EmpArr[j + 1];
EmpArr[j + 1] = temp;
}
}
}
this->Save();
cout << "已为您重新排序" << endl;
cout << "排序后职工信息如下:" << endl;
this->show_emp();
}
13. 7-清空职工信息
文件和数组都要清空
①清空文件
ios::trunc //打开文件,如果文件中有数据,就清空数据,重建一份文件
ofstream ofs;
ofs.open("Emptxt", ios::trunc);
ofs.close();
②清空数组(记得顺便把职工人数置0)
if (this->EmpArr!=NULL)
{
for (int i=0;i<this->EmpNum;i++)
{
if (this->EmpArr[i]!=NULL)
{
delete this->EmpArr[i];
this->EmpArr[i] = NULL;
}
}
delete[]this->EmpArr;
this->EmpArr = NULL;
this->EmpNum = 0;
this->FlafEmpty = true;
}
代码部分:
主函数
#include <iostream>
#include <string>
#include"sys.h"
#include "worker.h"
using namespace std;
int main()
{
workManager wm;
int select=0;
while (1)
{
wm.show_menu();
cout << "请输入您的选择:" << endl;
cin >> select;
switch (select)
{
case 1:
wm.add_emp(); break;
case 2:
wm.show_emp(); break;
case 3:
wm.del_emp(); break;
case 4:
wm.modify_emp(); break;
case 5:
wm.find_emp(); break;
case 6:
wm.sort_emp(); break;
case 7:
wm.clear_emp(); break;
case 0:
wm.exit_sys();
break;
default:
system("cls");
break;
}
}
system("pause");
return 0;
}
管理类.cpp
#include"sys.h"
//构造函数
workManager::workManager()
{
ifstream ifs;
ifs.open("Emptxt", ios::in);
//1.打不开(文件不存在)
if (!ifs.is_open())
{
cout << "文件不存在" << endl;
this->FlafEmpty = true;
this->EmpNum = 0;
this->EmpArr = NULL;
ifs.close();
return;
}
//2.打开为空
int ch;
ifs >> ch;
if (ifs.eof())
{
cout << "文件为空" << endl;
FlafEmpty = true;
this->EmpNum = 0;
this->EmpArr = NULL;
ifs.close();
return;
}
//3.文件中有内容,把文件中的内容读进数组
this->EmpNum = GetSize();
this->EmpArr = new Worker * [EmpNum];
this->FlafEmpty = false;
this->InitEmp();
}
//析构函数
workManager::~workManager()
{
if (this->EmpArr!=NULL)
{
for (int i = 0; i < this->EmpNum; i++)
{
delete this->EmpArr[i];
}
delete[]this->EmpArr;
this->EmpArr = NULL;
this->EmpNum = 0;
}
}
//显示菜单
void workManager::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;
}
void workManager::exit_sys()
{
cout << "欢迎下次使用!" << endl;
system("pause");
exit(0);
}
void workManager::Save()
{
ofstream ofs;
ofs.open("Emptxt", ios::out);
for (int i=0;i<this->EmpNum;i++)
{
ofs << this->EmpArr[i]->m_id << " "
<< this->EmpArr[i]->m_name << " "
<< this->EmpArr[i]->m_did << endl;
}
ofs.close();
}
int workManager::GetSize()
{
ifstream ifs;
ifs.open("Emptxt", ios::in);
int id;
string name;
int did;
int num=0;
while (ifs >> id && ifs >> name && ifs >> did)
{
num++;
}
return num;
ifs.close();
}
void workManager::InitEmp()
{
ifstream ifs;
ifs.open("Emptxt", ios::in);
int id;
string name;
int did;
int i = 0;
while (ifs >> id && ifs >> name && ifs >> did)
{
Worker* wk = NULL;
switch (did)
{
case 1:wk = new Employee(id, name, did);
break;
case 2:wk = new Manager(id, name, did);
break;
case 3:wk = new Boss(id, name, did);
break;
default:break;
}
EmpArr[i] = wk;
i++;
}
ifs.close();
}
void workManager::show_emp()
{
cout << "当前职工系统共有" << this->EmpNum << "人" << endl;
if (this->EmpNum>0)
{
for (int i=0;i<this->EmpNum;i++)
{
EmpArr[i]->showInfo();
}
}
system("pause");
system("cls");
}
void workManager::add_emp()
{
cout << "请输入您要添加的职工人数:" << endl;
int addNum;
cin >> addNum;
if (addNum > 0)
{
//开辟新空间
int allNum = this->EmpNum + addNum;
Worker** newArr = new Worker * [allNum];
//把旧空间数据搁进来
if (this->EmpArr!=NULL)
{
for (int i=0;i<this->EmpNum;i++)
{
newArr[i] = this->EmpArr[i];
}
}
//添加新成员
for (int i=0;i<addNum;i++)
{
int id;
string name;
int did;
cout << "请输入第" << i + 1 << "个职工的编号:" << endl;
cin >> id;
cout << "请输入第" << i + 1 << "个职工的姓名:" << endl;
cin >> name;
cout << "请选择第" << i + 1 << "个职工的岗位:" << endl;
cout << "1--员工 2--经理 3--老板" << endl;
cin >> did;
Worker* wk = NULL;
switch (did)
{
case 1:wk = new Employee(id, name, did);
break;
case 2:wk = new Manager(id, name, did);
break;
case 3:wk = new Boss(id, name, did);
break;
default:break;
}
newArr[this->EmpNum+i] = wk;
}
this->EmpNum = allNum;
delete[]this->EmpArr;
EmpArr = newArr;
cout << "成功添加" << addNum << "人" << endl;
Save();
FlafEmpty = false;
}
else
{
cout << "输入有误" << endl;
}
system("pause");
system("cls");
}
int workManager::GetIndex(string name)
{
int index = -1;
for (int i=0;i<this->EmpNum;i++)
{
if (this->EmpArr[i]->m_name==name)
{
index = 1;
}
}
return index;
}
void workManager::del_emp()
{
cout << "请输入你要删除的员工姓名:" << endl;
string name;
cin >> name;
int index = this->GetIndex(name);
if (index == -1)
{
cout << "没有找到该职工" << endl;
}
else
{
cout << "找到该员工,确认要删除吗?" << endl;
cout << "1--YES 2--NO" << endl;
int select=0;
cin >> select;
if (select == 1)
{
for(int i=index;i<this->EmpNum;i++)
{
this->EmpArr[i] = this->EmpArr[i + 1];
}
this->EmpNum--;
cout << "已为您删除该员工" << endl;
this->Save();
}
if (select == 2)
{
return;
}
}
system("pause");
system("cls");
}
void workManager::modify_emp()
{
cout << "请输入你要修改的职工姓名:" << endl;
string name;
cin >> name;
int index = this->GetIndex(name);
if (index == -1)
{
cout << "没有找到该职工" << endl;
}
else
{
int id;
string name;
int did;
cout << "已为您找到该员工,请输入修改后的职工编号:" << endl;
cin >> id;
cout << "请输入修改后职工的姓名:" << endl;
cin >> name;
cout << "请选择修改后职工的岗位:" << endl;
cout << "1--员工 2--经理 3--老板" << endl;
cin >> did;
Worker* wk = NULL;
switch (did)
{
case 1:wk = new Employee(id, name, did);
break;
case 2:wk = new Manager(id, name, did);
break;
case 3:wk = new Boss(id, name, did);
break;
default:break;
}
this->EmpArr[index] = wk;
this->Save();
}
system("pause");
system("cls");
}
void workManager::find_emp()
{
cout << "请输入你要查找的职工姓名:" << endl;
string name;
cin >> name;
int index = this->GetIndex(name);
if (index == -1)
{
cout << "没有找到该职工" << endl;
}
else
{
cout << "已为您找到该员工! 他的信息如下" << endl;
this->EmpArr[index]->showInfo();
}
system("pause");
system("cls");
}
void workManager::clear_emp()
{
cout << "确认要清空职工信息吗?" << endl;
cout << "1--YES 2--NO" << endl;
int select;
cin >> select;
if (select==1)
{
//文件和数组都需要清空
ofstream ofs;
ofs.open("Emptxt", ios::trunc);
ofs.close();
if (this->EmpArr!=NULL)
{
for (int i=0;i<this->EmpNum;i++)
{
if (this->EmpArr[i]!=NULL)
{
delete this->EmpArr[i];
this->EmpArr[i] = NULL;
}
}
delete[]this->EmpArr;
this->EmpArr = NULL;
this->EmpNum = 0;
this->FlafEmpty = true;
}
}
system("pause");
system("cls");
}
void workManager::sort_emp()
{
if (this->EmpNum != 0)
{
for (int i = 0; i < this->EmpNum - 1; i++)
{
for (int j = 0; j < this->EmpNum - 1 - i; j++)
{
if (EmpArr[j]->m_id > EmpArr[j + 1]->m_id)
{
Worker* temp = EmpArr[j];
EmpArr[j] = EmpArr[j + 1];
EmpArr[j + 1] = temp;
}
}
}
this->Save();
cout << "已为您重新排序" << endl;
cout << "排序后职工信息如下:" << endl;
this->show_emp();
}
system("pause");
system("cls");
}
管理类.h
#pragma once
#include <iostream>
#include <string>
#include "worker.h"
#include <fstream>
using namespace std;
class workManager
{
public:
//构造函数
workManager();
//析构函数
~workManager();
//显示菜单
void show_menu();
//得到空间大小
int GetSize();
//职工数组初始化
void InitEmp();
//写文件
void Save();
//返回员工索引
int GetIndex(string name);
//0.退出系统
void exit_sys();
//1.添加职工
void add_emp();
//2.显示职工
void show_emp();
//3.删除离职员工
void del_emp();
//4.修改职工信息
void modify_emp();
//5.查找职工
void find_emp();
//6.按照职工编号重新排序
void sort_emp();
//7.清空职工
void clear_emp();
int EmpNum;
Worker** EmpArr;
//文件空标志
bool FlafEmpty;
};
职工类.cpp
#include "worker.h"
//1.普通员工
Employee::Employee(int id, string name, int did)
{
m_id = id;
m_name = name;
m_did = did;
}
void Employee::showInfo()
{
cout << "职工编号:" << this->m_id << " "
<< "职工姓名:" << this->m_name << " "
<< "职工岗位:" << this->GetDID() << endl;
}
string Employee::GetDID()
{
return "员工";
}
//2.经理
Manager::Manager(int id, string name, int did)
{
m_id = id;
m_name = name;
m_did = did;
}
void Manager::showInfo()
{
cout << "职工编号:" << this->m_id<<" "
<< "职工姓名:" << this->m_name << " "
<< "职工岗位:" << this->GetDID() << endl;
}
string Manager::GetDID()
{
return "经理";
}
//3.老板
Boss::Boss(int id, string name, int did)
{
m_id = id;
m_name = name;
m_did = did;
}
void Boss::showInfo()
{
cout << "职工编号:" << this->m_id << " "
<< "职工姓名:" << this->m_name << " "
<< "职工岗位:" << this->GetDID() << endl;
}
string Boss::GetDID()
{
return "老板";
}
职工类.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Worker
{
public:
virtual void showInfo()=0;
virtual string GetDID()=0;
int m_id;
string m_name;
int m_did;
};
class Employee :public Worker
{
public:
Employee(int id,string name,int did);
void showInfo();
string GetDID();
};
class Manager :public Worker
{
public:
Manager(int id, string name, int did);
void showInfo();
string GetDID();
};
class Boss :public Worker
{
public:
Boss(int id, string name, int did);
void showInfo();
string GetDID();
};
遇到的溢出问题:
解决方法:
开辟数组时多开辟一个指针大小(x64需要加8),
在初始化函数empInit()和添加职工函数add_emp()中都需要修改: