前言
- 如果你仅仅是想弄一份职工管理系统的源代码,不想知道过程是怎样实现的,那你可以直接拉到这篇文章的最底部找源代码,注意:这个实现过程涉及了多个头文件,cpp文件,具体创建的方法见代码下面的详解
- 这个实现过程是用C++的类实现的,而且还涉及到了文件的输入和输出。
- 这篇文章首先会讲解这个职工管理系统能实现的功能,其次会讲解过程是怎样实现的,然后是源代码,最后就是源代码的使用说明。
职工管理系统的功能
上面这个图片就是这个职工管理系统的功能图,输入对应的数字就能实现对应的功能。
这个项目的数据是文件进行保存的。保存在 empfile.txt 文件里 。
这个项目是文件保存输入输出的,一旦运行这个程序,首先就会在堆区开辟一个数组,把文件中的数据读入到这个数组里面,接下来不论执行哪个功能,都是直接对数组里面的数据进行操作,比如执行 4 修改职工信息 这个功能,实际上就是修改数组里对应的信息,等到修改完成,会把修改后的数组保存至文件中(文件中原本的数据就会被覆盖掉)。
其他的功能也是类似的,只要记住程序一旦运行,在你选择对应的功能之前,已经完成了开辟数组,并把文件中的数据保存到了数组中,接下来的操作都是对数组进行操作,操作完成之后就是把修改后数组保存到文件中。
这项目中有三类职工,分别是员工,经理,老板。每个职工都有自己的职工编号m_Id、职工姓名m_Name和部门编号m_DeptId这些属性。每个职工都有两个函数,分别是显示自己的个人信息showInfo()函数和返回自己的岗位名称getDeptName函数
员工、经理、老板,这三种都有对应自己的类。这里利用多态实现的,写了父类(Worker)。根据这个父类,利用多态定义出了员工类、经理类和老板类,具体看代码详解。
在这个项目中一共有五个cpp文件,分别是employee、manger、boss、workManger和职工管理系统主程序(main函数在这里)。其中前三个cpp文件分别是员工类、经理类、老板类的具体实现,workManger是项目中各个功能类的实现(最重要的一个类)。最后一个就是main函数的入口,在这里执行程序。
最重要的就是workMangerl类,这个类包含三个属性,
分别是记录职工人数的m_EmpNum、判断文件是否为空的标志 m_FileIsEmpty 、职工数组指针m_EmpArray。这个指针是一个二级指针,第一指向的是堆区开辟的数组指针,这个数组指针的每一个指针都指向一个职工,假如我们现在有一个员工、一个经理,一个老板,这就要在堆区开始三个内存空间来存这三组数据(每个职工都有自己的属性)。上面的数组指针就是指向这个三个内存空间的数据。然后 职工数组指针m_EmpArray 就是指向这个数组指针。这样通过一个指针就能来维护所有职工的数据。这大概就是多态的优势所在吧,不然三个类的成员数据进行保存时,要开辟三个数组,每次维护时还要进行分类讨论。数据进行保存时,三个数组还都要都进行保存。
代码的实现过程
WorkManger的构造函数
这个构造函数的作用就是初始化数据用的。如果文件不存在或者文件为空,就是职工人数赋值为0,数组指针指向为空,如果文件中有数据,首先就利用一个 get_EmpNum()函数 来计算出文件中保存的有多少职工(这个函数是自己写的)
然后根据这个字数的大小,在堆区开辟对应的指针数组,然后又利用了一个 init_Emp() 函数 ,来初始化数组,init_Emp()的实现过程就是根据文件,读出对应的数据,每次读一行(一个职工的数据),然后开辟空间存入。再把上面开辟的数组指针指向这个开辟的空间。根据这个构造函数,就实现了将文件中的数据读入到了数组中,然后剩下的操作都是对数组进行操作。
0 退出管理程序
利用exit(0)就可以正常的退出程序,具体看代码
1 增加职工信息
- 这个程序一个可以增加多名职工信息
- 计算新空间的大小,这里采取的方法是开辟新空间,新空间的大小=原空间大小+新增人数。
- 根据新空间大小,来开辟对应的数组指针
- 把原来数组中的数据存入到新数组里面。
- 输入要添加的新职工信息
- 存入职工信息(输入一个,存入一个)
- 释放原本空间的内存
- 更改新空间的指向,让 职工数组指针m_EmpArray 指向这段新空间,更改职工人数,文件是否为空标志
- 将新数组的数据存入到文件中。
2 显示职工信息
- 首先判断文件是否为空或者文件中是否有数据,如果符合条件就直接输入文件为空或者无数据就行,剩下的程序就不用执行了,这样比较方便快捷,具体原因可以自己想想
- 如果文件中有数据,直接遍历一遍数组,把数组的每一个元素调用自身的显示自己的个人信息showInfo()函数。这里利用的是多态技术,父类指针指向子类的对象。
3 删除职工信息
- 首先判断文件是否为空或者文件中是否有数据,原因和上面一样
- 如果文件中有数据,根据职工编号进行删除职工对应的信息
- 输入想要删除的职工编号,这里有一个 IsExist() 函数 这个函数的作用数传入一个职工编号,可以返回数组中这个职工编号在数组中存在的下标,如果不存在,会返回-1。利用上面这个函数就能求出来要删除职工编号对应的下标
- 知道下标后,就可以删除了,这里采取的方法是覆盖的方法,比如删除的是数组中的某一个元素,那么把这个元素后面的数据都往前移动一个位置,最后再把记录职工人数的变量减一即可,再把指针指向的最后一个元素的内存空间释放掉(代码中好像没写这个释放空间)。
- 最后把修改后的新数组保存到文件中
4 修改职工信息
- 仍旧是根据文件是否为空的标志 m_FileIsEmpty 来进行判断。
- 输入想要修改职工的编号,根据这个编号,利用IsExist() 函数 找到在数组中对应的下标
- 首先释放数组中对应下标指向的内存空间。
- 然后开辟一个新空间,把要修改的职工信息存到新空间里面,再把指针指向这个新的内存空间
- 最后 仍旧是将修改后的数组保存到文件中
5 查找职工信息
- 仍旧是根据文件是否为空的标志 m_FileIsEmpty 来进行判断。
- 这里查找职工信息有两种查找方法,分别是根据职工编号进行查询、根据职工姓名进行查询
- 如果是根据职工编号进行查询的话,直接根据这个职工编号,利用IsExist() 函数 求出下标,然后输出下标对应的信息就可以
- 如果是根据职工姓名进行查询,这里可能会发生重名的现象,所以可以直接遍历数组,如果有名字相同的,直接输出对应的信息就可以(可能会出书多个人的信息)
6 按照职工编号进行排序
- 仍旧是根据文件是否为空的标志 m_FileIsEmpty 来进行判断。
- 这里排序有升序和降序两种方法,这里排序的方法选择的是手写选择排序,当然排序方法也可以用其他的方法,比如快排。
- 将排序后的数组保存到文件中
- 这里还调用了一个 show_Emp()函数 可以输出排序后的数组信息,当然也可以不调用
7 清空所有文档
- 这里清空的方法是采取删除源文件,重新创建一个新的空文件的方法。
- 因为程序一运行,就会开辟内存空间来存原文件中的数据,所以这里需要把开辟的内存空间释放掉
最后再说一点关于WorkManger的析构函数,在这个函数中,我们要把开辟的各种指针都释放掉,防止内存泄漏
代码
worker.h的代码
#pragma once #include<iostream> using namespace std; #include<string> //职工抽象的类 class Worker { public: //显示个人信息 virtual void showInfo() = 0; //获取岗位名称 virtual string getDeptName() = 0; //职工编号 int m_Id; //职工姓名 string m_Name; //部门编号 int m_DeptId; };
employee.h的代码
//普通员工文件 #pragma once #include<iostream> using namespace std; #include "worker.h" class Employee :public Worker { public: //构造函数 Employee(int id, string name, int did); //显示个人信息 virtual void showInfo() ; //获取个人信息 virtual string getDeptName() ; };
manager.h的代码
#pragma once #include<iostream> using namespace std; #include "worker.h" //经理类 class Manger : public Worker { public: //构造函数 Manger(int id, string name, int did); //显示个人信息 virtual void showInfo() ; //获取岗位名称 virtual string getDeptName() ; };
boss.h的代码
#pragma once #include<iostream> using namespace std; #include "worker.h" //经理类 class Boss : public Worker { public: //构造函数 Boss(int id, string name, int did); //显示个人信息 virtual void showInfo(); //获取岗位名称 virtual string getDeptName(); };
workManger.h的代码
#pragma once #include <iostream> using namespace std; #include "worker.h" #include "employee.h" #include "manager.h" #include "boss.h" #include <fstream> #define FILENAME "empfile.txt" class WorkManger { public: WorkManger(); //展示菜单 void Show_Menu(); //退出系统 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(); ~WorkManger(); };
employee.cpp的代码
#include "employee.h" //构造函数 Employee::Employee(int id, string name, int did) { this->m_Id = id; this->m_Name = name; this->m_DeptId = did; } //显示个人信息 void Employee::showInfo() { cout << "职工编号: " << this->m_Id << "\t职工姓名: " << this->m_Name << "\t岗位: " << this->getDeptName() << "\t岗位职责: 完成经理交给的任务" << endl; } //获取岗位名称 string Employee::getDeptName() { return string("员工"); }
manager.cpp的代码
#include "manager.h" //构造函数 Manger::Manger(int id , string name, int did) { this->m_Id = id; this->m_Name = name; this->m_DeptId = did; } //显示个人信息 void Manger::showInfo() { cout << "职工编号: " << this->m_Id << "\t职工姓名: " << this->m_Name << "\t岗位: " << this->getDeptName() << "\t岗位职责: 完成老板交给的任务,并下发任务" << endl; } //获取岗位名称 string Manger::getDeptName() { return string("经理"); }
boss.cpp的代码
#include "boss.h" //构造函数 Boss::Boss(int id, string name, int did) { this->m_Id = id; this->m_Name = name; this->m_DeptId = did; } //显示个人信息 void Boss::showInfo() { cout << "职工编号: " << this->m_Id << "\t职工姓名: " << this->m_Name << "\t岗位: " << this->getDeptName() << "\t岗位职责: 管理公司所有事务" << endl; } //获取岗位名称 string Boss::getDeptName() { return string("老板"); }
workManger.cpp的代码
#include "workManger.h" WorkManger::WorkManger() { ifstream ifs; //1、文件不存在 ifs.open(FILENAME, ios::in); //读文件 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 << "姓名: " << this->m_EmpArray[i]->m_Name << "部门编号: " << this->m_EmpArray[i]->m_DeptId << endl; }*/ } //展示菜单 void WorkManger::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 WorkManger::ExitSystem() { cout << "欢迎下次使用" << endl; system("pause"); exit(0); } //添加职工 void WorkManger::Add_Emp() { cout << "请输入添加职工的数量: " << endl; int addNum = 0; 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; //职工编号 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, 1); break; case 2: worker = new Manger(id, name, 2); break; case 3: worker = new Boss(id, name, 3); break; default: break; } //将创建的职工职责,保存到数组中 newSpace[this->m_EmpNum + i] = worker; } //释放原有的空间 delete[] this->m_EmpArray; //更改新空间的指向 this->m_EmpArray = newSpace; //更新新的职工人数 this->m_EmpNum = newSize; //更新职工不为空标记 this->m_FileIsEmpty = false; //提示添加成功 cout << "成功添加" << addNum <<"名新职工"<< endl; //保存数据到文件中 this->save(); } else { cout << "输入数据有误" << endl; } //按任意键后 清屏回到上级目录 system("pause"); system("cls"); } //保存文件 这个保存文件是从文件头开始保存的, //文件中的数据一开始已经存入到数组中了,这时候文件中的数据 已经没用了, //保存文件时直接把原来文件中的数据覆盖了 void WorkManger::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(); } //统计文件中的人数 int WorkManger::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++; } return num; } //初始化员工 void WorkManger::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; if (dId == 1) //普通职工 { worker = new Employee(id, name, dId); } if (dId == 2) //经理 { worker = new Manger(id, name, dId); } if (dId == 3) //老板 { worker = new Boss(id, name, dId); } this->m_EmpArray[index] = worker; index++; } //关闭文件 ifs.close(); } //显示职工 void WorkManger::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 WorkManger::Del_Emp() { if (this->m_FileIsEmpty) { cout << "文件不存在或记录为空!" << endl; } else { //按照职工编号进行删除 cout << "请输入想要删除职工编号: " << endl; int id = 0; cin >> id; int index = this->IsExist(id); if (index != -1) { for (int i = index; i < this->m_EmpNum-1; i++) //如果是删除的最后一个元素,就不用移动数据,直接把数组人数-1即可 { //数据前移 this->m_EmpArray[i] = this->m_EmpArray[i + 1]; } this->m_EmpNum--;//更新数组中数组人数的 //数据同步更新到文件中 this->save(); cout << "删除成功!" << endl; } else { cout << "删除失败,未找到该职工!" << endl; } } //按任意键后清屏 system("pause"); system("cls"); } //判断职工是否存在。如果存在,返回职工所在数组中的位置,不存在返回-1 int WorkManger::IsExist(int id) { int index = -1; for (int i = 0; i < this->m_EmpNum; i++) { if (this->m_EmpArray[i]->m_Id == id) { //找到职工 index = i; break; } } return index; } //修改职工 void WorkManger::Mod_Emp() { if (this->m_FileIsEmpty) { cout << "文件不存在或者记录为空!" << endl; } else { cout << "请输入修改职工的编号" << endl; int id; cin >> id; int ret = this->IsExist(id); if (ret != -1) { //查找到编号的职工 delete this->m_EmpArray[ret]; int newId=0; string newName; int dSelect = 0; cout << "查找: " << id << "号职工,输入新职工号: " << endl; cin >> newId; cout << "请输入新姓名: " << endl; cin >> newName; cout << "请输入岗位: " << endl; cout << "1、普通职工" << endl; cout << "2、经理" << endl; cout << "3、老板" << endl; cin >> dSelect; Worker * worker = NULL; switch (dSelect) { case 1: worker = new Employee(newId, newName, dSelect); break; case 2: worker = new Manger(newId, newName, dSelect); break; case 3: worker = new Boss(newId, newName, dSelect); break; default : break; } //更新数据到数组中 this->m_EmpArray[ret] = worker; cout << "修改成功!" << endl; //保存到文件中 this->save(); } else { cout << "修改失败,查无此人!" << endl; } } //按任意键清屏 system("pause"); system("cls"); } //查找职工 按照姓名查询或按照编号查询 void WorkManger::Find_Emp() { if (this->m_FileIsEmpty) { cout << "文件不存在或者记录为空!" << endl; } else { cout << "请输入查找的方式: " << endl; cout << "1、按照职工编号查找: " << endl; cout << "2、按照职工姓名查询: " << endl; int select = 0; cin >> select; if (select == 1) { //按照编号查 int id; cout << "请输入查找的职工编号: " << endl; cin >> id; int ret = IsExist(id); if (ret != -1) { //找到职工 cout << "查找成功!该职工的信息如下: " << endl; this->m_EmpArray[ret]->showInfo(); } else { cout << "查找失败!查无此人" << endl; } } else if (select == 2) { //按照姓名查询 string name; cout << "请输入查找的姓名: " << endl; cin >> name; //假如一个判断是否查到的标志 bool flag = false;//默认未找到职工 for (int i = 0; i < m_EmpNum; i++) { if (this->m_EmpArray[i]->m_Name == name) { cout << "查找成功,职工编号为: " << this->m_EmpArray[i]->m_Id << "号职工信息如下" << endl; flag = true; //调用显示信息的接口 this->m_EmpArray[i]->showInfo(); } } if (flag == false) { cout << "查找失败!查无此人" << endl; } } else { cout << "输入选项有误,请重新输入!" << endl; } } //按任意键清屏 system("pause"); system("cls"); } //按照职工的编号进行排序 void WorkManger::Sort_Emp() { if (this->m_FileIsEmpty) { cout << "文件不存在或记录为空!" << endl; //按任意键清屏 system("pause"); system("cls"); } else { cout << "请选择排序的方式: " << endl; cout << "1、按照职工号进行升序" << endl; cout << "2、按照职工号进行降序" << endl; int select = 0; cin >> select; for (int i = 0; i < m_EmpNum; i++) { int minOrmax = i;//声明最小值 或 最大值的下标 for (int j = i + 1; j < this->m_EmpNum; j++) { if (select == 1)//升序 { if ((this->m_EmpArray[minOrmax]->m_Id) > (this->m_EmpArray[j]->m_Id)) { minOrmax = j; } } else //降序 { if((this->m_EmpArray[minOrmax]->m_Id) < (this->m_EmpArray[j]->m_Id)) { minOrmax = j; } } //判断一开始认定 最大值或最小值,是不是计算的最大值或最小值,如果不是交换数据 Worker* temp = this->m_EmpArray[i]; this->m_EmpArray[i] = this->m_EmpArray[minOrmax]; this->m_EmpArray[minOrmax] = temp; } } cout << "排序成功!排序后的结果为: " << endl; this->save();//把排序后的结果保存到文件中 this->Show_Emp();//展示所有职工 } } //清空文件操作 void WorkManger::Clean_File() { cout << "确定清空? " << endl; cout << "1、确定" << endl; cout << "2、返回" << endl; int select = 0; cin >> select; if (select == 1) { //清空文件 ofstream ofs(FILENAME, 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; } cout << "清空成功" << endl; } //按任意键清屏 system("pause"); system("cls"); } WorkManger::~WorkManger() { if (this->m_EmpArray != NULL) { for (int i = 0; i < this->m_EmpNum; i++) { if (this->m_EmpArray[i] != NULL ) { delete this->m_EmpArray[i]; } } delete[] this->m_EmpArray; this->m_EmpArray = NULL; } }
职工管理系统.cpp的代码
#include<iostream> #include "workManger.h" using namespace std; //#include "worker.h" //#include "employee.h" //#include "manager.h" //#include "Boss.h" int main() { WorkManger wm; int choice = 0; while (true) { //调用菜单函数 wm.Show_Menu(); 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: break; } } system("pause"); return 0; }
代码使用说明:
- 我用的是VS2019写的,如果要使用源代码,你可以去VS里面创一个新的项目,名字可以命名为职工管理系统
- 然后就就创建一些头文件和cpp文件,这些文件的名称如下图
注意这文件名的大小写,以及字母的拼写不要错误,我里面的manager有的好像拼写有些问题,不过你跟着我图片里的命名就可以保证你的正常运行,创建好之后,把上面对应的源代码复制到对应的文件中去。然后点击运行就可以。
- 根据图片创建对应的文件
- 把上面的源代码填入到对应的文件中去
如果上面的步骤嫌麻烦,可以直接去下载我上传的资源,里面有这个职工管理系统的压缩包,打开就可以直接运行。
如果代码和命名都没有错误,但是还无法运行,那就可以在评论出说出你的问题,我会及时回复的!!!