1 项目需求分析
1.首先进入欢迎界面,让用户输入不同选择,进入不同选项
1.1. 0 -- 退出
1.2. 1 -- 增加职工
1.3. 2 -- 删除职工
1.4. 3 -- 显示所有职工信息
1.5. 4 -- 修改职工信息
1.6. 5 -- 查找职工
1.7. 6 -- 按职工编号进行排序
1.8. 7 -- 清空文档
2.退出- 退出管理系统
3.增加职工,添加新职工,可以批量添加多个职工,职工分为普通员工、经理以及总裁
4.删除职工,可以按照职工编号进行删除职工
5.显示所有职工信息,先判断文件是否存在或是否清空,如果存在并且有记录的情况下,展示文件内记录内所有职工的信息
6.修改职工信息,可以按照用户输入的职工编号,修改职工新的信息,并保存到文件中
7.查找职工信息,查找有两种方式,一个按职工编号查找,一个按姓名查找,如果用户查找的内容不为空显示该职工信息,如果为空提示不存在要查找的职工
8.按职工编号进行排序,用户可以将输入的所有职工按照职工编号进行升序或者降序排列,并存入文件
9.清空文档,可以将文件内当前的记录全部清空。
本案例设计到的知识点为:面向对象中的封装、继承、多态以及文件IO流,在设计中有Worker职工的基类,以及分别派生类为普通员工、经理、以及总裁,基类中有纯虚函数子类分别作了实现。然后有个文件管理类,对用户做出不同的选择分别做不同的处理。可以对系统进行基本的增删改查功能。
2 创建工程
3 创建管理类
管理类负责的内容如下:·
●与用户的沟通菜单界面
●对职工增删改查的操作
●与文件的读写交互
4 菜单功能
功能描述:与用户的沟通界面
5 退出功能
6 创建职工类
7 添加职工
8 文件交互-写文件
功能描述:对文件进行读写
在上一个添加功能中,我们只是将所有的数据添加到了内存中,一旦程序结束就无法保存了因此文件管理类中需要一个与文件进行交互的功能,对于文件进行读写操作
9 文件交互-读文件
功能描述:将文件中的内容读取到程序中
虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中数据读取到程序中而我们的程序功能中还有清空文件的需求
因此构造函数初始化数据的情况分为三种
1.第一次使用,文件未创建;
2.文件存在,但是数据被用户清空;
3.文件存在,并且保存职工的所有数据;
9.1 文件未创建
9.2 文件存在且为空
将文件创建后清空文件内容,并测试该情况下初始化功能;
我们发现文件不存在或者为空清空m_FilelsEmpty判断文件是否为空的标志都为真,那何时为假?
成功添加职工后,应该更改文件不为空的标志;
9.3 文件存在,且保存职工数据
10 显示职工
11 删除职工
功能描述:按照职工的编号进行删除职工操作;
数组中删除本质就是数据前移
12 修改职工
功能描述:能够按照职工的编号对职工信息进行修改并保存;
13 查找职工
功能描述:提供两种查找职工方式,
一种按照职工编号,
一种按照职工姓名;
14 职工排序
功能描述:按照职工编号进行排序,排序的顺序由用户指定;
15 清空文件
功能描述:将文件中记录数据清空
16 项目源码
0 职工管理系统 主文件
职工管理系统.cpp
#include <iostream>
using namespace std;
#include "workerManager.h"
#include "Employee.h"
#include "Manager.h"
#include "Boss.h"
int main() {
//实例化对象
WorkerManager wm;
int choice;//用户选择
while (true) {
wm.ShowMenu();
cout << "请输入您的选择: " << endl;
cin >> choice;//接收用户的选项
switch(choice) {
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_File();
break;
default://清空屏幕
system("cls"); //清屏
break;
}
}
system("pause");
return 0;
}
1 职工管理类 workerManager
“workerManager.h”
#pragma once // 防止头文件重复包含
#include <iostream> //包含输入输出流头文件
using namespace std; //使用标准命名空间
#include"Worker.h"
#include "Manager.h"
#include "Employee.h"
#include<fstream>
#define FILENAME "empFile.txt"
#include<algorithm>
#include"Boss.h"
class WorkerManager
{
public:
//构造函数
WorkerManager();
//显示菜单
void ShowMenu();
//退出系统
void ExitSystem();
//记录职工人数
int m_EmpNum;
//职工数组指针
Worker** m_EmpArray;
//添加职工
void Add_Emp();
//保存文件(存储职工信息)
void save();
//文件是否为空,标志
bool m_FileIsEmpty;
//统计人数
int get_EmpNum();
//初始化员工
void init_Emp();
//显示职工
void Show_Emp();
//删除职工
void Del_Emp();
//按照编号判断职工是否存在,若存在返回在数组中的下标,若不存在返回-1
int IsExist(int id);
//修改职工
void Mod_Emp();
//查找职工
void Find_Emp();
//职工排序
void Sort_Emp();
//清空文件
void Clean_File();
//析构函数
~WorkerManager();
};
workerManager.cpp
#include "workerManager.h"
//构造函数
WorkerManager::WorkerManager() {
//初始化属性
//读文件,构造函数初始化数据的情况分为三种
ifstream ifs;
ifs.open(FILENAME,ios::in);
//1.文件未创建
if (!ifs.is_open()) {
cout << "文件不存在" << endl;//测试输出
this->m_EmpNum = 0;
this->m_EmpArray = NULL;
this->m_FileIsEmpty = true;
ifs.close();
return;
}
//2.文件存在,且没有数据
char ch;
ifs >> ch;
if (ifs.eof()) {
cout << "文件存在,且为空" << endl;//测试输出
this->m_EmpNum = 0;
this->m_EmpArray = NULL;
this->m_FileIsEmpty = true;
ifs.close();
return;
}
//3.文件存在,并且保存职工的所有数据
int num = this->get_EmpNum();
cout << "职工个数为: " << num << endl;//测试代码
this->m_EmpNum = num;//更新成员属性
//开辟空间
this->m_EmpArray = new Worker * [this->m_EmpNum];
//将文件中的数据存到数组中
this->init_Emp();
//测试代码
//for (int i = 0; i < this->m_EmpNum; i++) {
// cout<< "职工编号:" << this->m_EmpArray[i]->m_id
// << "\t姓名:" << this->m_EmpArray[i]->m_name
// << "\t部门编号:" << this->m_EmpArray[i]->m_dID << endl;
//}
}
//退出系统
void WorkerManager::ExitSystem() {
cout << "欢迎下次使用" << endl;
system("pause");
exit(0);
}
//添加职工
void WorkerManager::Add_Emp() {
cout << "请输入添加职工数量: " << endl;
int addNum = 01;//保存用户输入数量
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] = m_EmpArray[i];
}
}
//批量添加新数据
for (int i = 0; i < addNum; i++) {
int id;//职工编号
string name;//职工姓名
int dSelect;//部门选择
cout << "请输入第"<< i + 1 <<"个新职工编号"<< endl;
cin >> id;
cout << "请输入第" << i + 1 << "个新职工姓名" << 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:
break;
}
//将创建的职工指针,保存到数组中
newSpace[this->m_EmpNum + i] = worker;
}
//释放原有空间
delete[] this->m_EmpArray; //因为是数组所以要加"[]"
//更改新的空间指向
this->m_EmpArray = newSpace;
//更新职工人数
this->m_EmpNum = newSize;
//提示添加成功
cout << "成功添加" << addNum<<"名职工"<<endl;
//添加成功后,把文件是否为空标志,改为不为空,即flase;
this->m_FileIsEmpty = false;
//保存文件(存储职工信息)
save();
}
else {
cout << "输入有误!" << endl;
}
//添加以后,应该,按任意键,清屏返回到上一级
system("pause");
system("cls");//清屏
}
//保存文件(存储职工信息)
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_dID << endl;
}
ofs.close();
}
//统计人数
int WorkerManager::get_EmpNum() {
ifstream ifs;
ifs.open(FILENAME,ios::in);
int id;
string name;
int dID;
int num = 0;
while (ifs >> id && ifs >> name && ifs >> dID) num++;
ifs.close();
return num;
}
//初始化员工
void WorkerManager::init_Emp() {
ifstream ifs;
ifs.open(FILENAME,ios::in);
int id;
string name;
int dID;
int index = 0;
while (ifs >> id && ifs >> name && ifs >> dID) {
Worker* worker = NULL;
//根据不同的id部门创建不同的对象
if (dID == 1) //普通员工
worker = new Employee(id,name,dID);
else if (dID == 2) //经理
worker = new Manager(id, name, dID);
else //老板
worker = new Boss(id, name, dID);
//存放在数组中
this->m_EmpArray[index] = worker;
index++;
}
ifs.close();
}
//显示职工
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");
}
//删除职工
void WorkerManager::Del_Emp() {
if(this->m_FileIsEmpty) cout << "文件不存在或记录为空 !" << endl;
else
{
int id;
cout << "请输入要删除的职工编号: " << endl;
cin >> id;
int index = this->IsExist(id);
if (index == -1) cout << "删除失败,查无此人 !" << endl;
else {
for (int i = index; i < this->m_EmpNum - 1; i++)
this->m_EmpArray[i] = this->m_EmpArray[i + 1];
}
this->m_EmpNum--;//数组中人员个数减1
//数据同步更新到文件中
this->save();
}
system("pause");
system("cls");
}
//按照编号判断职工是否存在,若存在返回在数组中的下标,若不存在返回-1
int WorkerManager::IsExist(int id) {
for (int i = 0; i < this->m_EmpNum; i++) {
if (this->m_EmpArray[i]->m_id == id)
return i;
}
return -1;
}
//修改职工
void WorkerManager::Mod_Emp() {
if (this->m_FileIsEmpty) cout << "文件不存在或记录为空 !" << endl;\
else {
cout << "请输入修改职工的编号:" << endl;
int id;
cin >> id;
int index = this->IsExist(id);
if (index != -1) {
delete this->m_EmpArray[index];//先删除该职工信息;
int newId;
string newName;
int dSlect;
cout << "职工" << id << "新的职工编号为:" << endl;
cin >> newId;
cout << "请输入新姓名:" << endl;
cin >> newName;
cout << "请选择岗位:" << endl;
cout << "1、普通员工" << endl;
cout << "经理" << endl;
cout << "老板" << endl;
cin >> dSlect;
Worker* worker = NULL;
switch (dSlect) {
case 1:
worker = new Employee(newId, newName, dSlect);
break;
case 2:
worker = new Manager(newId, newName, dSlect);
break;
case 3:
worker = new Boss(newId, newName, dSlect);
break;
default:
break;
}
//更新数据到数组
this->m_EmpArray[index] = worker;
cout << "修改成功!" << endl;
//更新文件数据
this->save();
}
else cout << "修改失败,查无此人" << endl;
}
//按任意键 清屏
system("pause");
system("cls");
}
//查找职工
void WorkerManager::Find_Emp() {
if (this->m_FileIsEmpty) cout << "文件不存在或记录为空" << endl;
else {
cout << "请输入查找方式:" << endl;
cout << "1.按职工编号查找" << endl;
cout << "2.按姓名查找" << endl;
int select;
cin >> select;
if (select == 1) {//按编号查找
cout << "请输入查找的职工编号: " << endl;
int id;
cin >> id;
int index = IsExist(id);
if (index != -1) {
cout << "查找成功!该职工信息如下:" << endl;
this->m_EmpArray[index]->ShowInfo();
}
else cout << "查找失败,查无此人!" << endl;
}
else if (select == 2) {//按姓名查找,可能会有同名,此时将所有同名信息都打印出来
cout << "请输入要查找的职工姓名:" << endl;
string name;
cin >> name;
bool flag = false;//查找标志
for (int i = 0; i < m_EmpNum; i++) {
if (this->m_EmpArray[i]->m_name == name) {
cout << "查找成功!该职工信息如下:" << endl;
this->m_EmpArray[i]->ShowInfo();
flag = true;
}
}
if (flag == false) cout << "查找失败,查无此人!" << endl;
}
else cout << "输入信息有误" << endl;
}
system("pause");
system("cls");
}
//职工排序
void WorkerManager::Sort_Emp() {
if (this->m_FileIsEmpty) cout << "文件不存在或记录为空" << endl;
else {
cout << "请选择排序方式:" << endl;
cout << "1.按职工编号升序排列" << endl;
cout << "2.按职工编号降序排列" << endl;
int select = 0;
int minOrMax = 0;
cin >> select;
for (int i = 0; i < m_EmpNum - 1; i++) {// n-1趟排序
minOrMax = i;//选择排序,第i趟排序选出当前最小/大与A[i]交换。
for (int j = i + 1; j < m_EmpNum; j++) {
if (select == 1) {//升序
if (m_EmpArray[j]->m_id < m_EmpArray[minOrMax]->m_id) minOrMax = j;//注意一定要用id比大小
}
else if (select == 2) {//降序
if (m_EmpArray[j]->m_id > m_EmpArray[minOrMax]->m_id) minOrMax = j;
}
}
if (minOrMax != i) {
Worker* temp = m_EmpArray[i];
m_EmpArray[i] = m_EmpArray[minOrMax];
m_EmpArray[minOrMax] = temp;
}
}
this->save();
cout << "排序成功!排序后结果为:" << endl;
this->Show_Emp();
}
system("pause");
system("cls");
}
//清空文件
void WorkerManager::Clean_File() {
if (this->m_FileIsEmpty) {
cout << "文件不存在或为空" << endl;
return;
}
else {
cout << "确认要清空吗?" << endl;
cout << "1.确认清空" << endl;
cout << "2.返回" << endl;
int select = 0;
cin >> select;
if (select == 1) {
//打开模式 ios::trunc 如果存在删除文件并重新创建
ofstream ofs(FILENAME,ios::trunc);//删除文件后,重新创建
ofs.close();
//此时,本地保存的txt文件已经清空了,,但是堆区数据还没有释放
//释放堆区数据
if (this->m_EmpArray != NULL) {
for (int i = 0; i < m_EmpNum; i++) {
if (this->m_EmpArray[i] != NULL) {
delete this->m_EmpArray[i]; //释放数组里的每个对象
}
}
this->m_EmpNum = 0;
delete[] this->m_EmpArray;//释放数组
this->m_EmpArray = NULL; //释放完毕,指针置空
this->m_FileIsEmpty = true;
}
cout << "清空成功!" << endl;
}
else {//2.返回
system("cls");
return;
}
//按任意键 清屏返回上一级目录
system("pause");
system("cls");
}
}
//显示菜单
void WorkerManager::ShowMenu() {
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;
}
WorkerManager::~WorkerManager() {
//析构改进: 当前析构只是简单的释放数组,而没有先释放数据空间
//if (this->m_EmpArray != NULL) {
// delete[] this->m_EmpArray;
// this->m_EmpArray = NULL;
//}
//改进如下:如果数据不为空,先释放掉每个数据对象,再释放数组
//释放堆区数据
if (this->m_EmpArray != NULL) {
for (int i = 0; i < m_EmpNum; i++) {
if (this->m_EmpArray[i] != NULL) {
delete this->m_EmpArray[i]; //释放数组里的每个对象
}
}
delete[] this->m_EmpArray;//释放数组
this->m_EmpArray = NULL; //释放完毕,指针置空
}
}
2 职工类 Worker
只有头文件,不需要.cpp文件
Worker.h
#pragma once
#include <iostream>
#include<string>
using namespace std;
class Worker
{
public:
//显示个人信息
virtual void ShowInfo() = 0;
//获取岗位名称
virtual string getDeptName() = 0;
int m_id;//职工编号
string m_name;//职工姓名
int m_dID;//所在部门编号
};
3 普工类 Employee
Employee.h
#pragma once
#include <iostream>
#include<string>
using namespace std;
#include "Worker.h"//继承
class Employee : public Worker
{
public:
//构造函数
Employee(int id, string name, int dID);
//显示个人信息
virtual void ShowInfo();
//获取岗位名称
virtual 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_dID = dID;
}
//显示个人信息
void Employee::ShowInfo() {
cout << "职工编号: " << this->m_id
<< "\t职工姓名: " << this->m_name
<< "\t岗位: " << this->getDeptName()
<< "\t岗位职责:完成经理交给的任务" << endl;
}
//获取岗位名称
string Employee::getDeptName() {
return string("员工");
}
4 经理类 Manager
Manager.h
#pragma once
#include <iostream>
#include<string>
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_dID = dID;
}
//显示个人信息
void Manager::ShowInfo() {
cout << "职工编号: " << this->m_id
<< "\t职工姓名: " << this->m_name
<< "\t岗位: " << this->getDeptName()
<< "\t岗位职责:完成老板交给的任务,并下发给员工" << endl;
}
//获取岗位名称
string Manager::getDeptName() {
return string("经理");
}
5 老板类 Boss
Boss.h
#pragma once
#include <iostream>
#include<string>
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_dID = dID;
}
//显示个人信息
void Boss::ShowInfo() {
cout << "职工编号: " << this->m_id
<< "\t职工姓名: " << this->m_name
<< "\t岗位: " << this->getDeptName()
<< "\t岗位职责:管理公司所有事务" << endl;
}
//获取岗位名称
string Boss::getDeptName() {
return string("总裁");
}