[C++] 职工管理系统(新手版)-Clion

通过一段时间的学习,大概把c++的知识过了一遍,现在跟着黑马的教程做一个职工管理系统。

虽然是一个老到掉渣的经典程序了,基本上人人都会写一遍哈哈哈哈哈哈哈哈哈哈,但是我还是要写出来,记录一下,如此菜鸡的自己。

我会在这里加上一些自己的见解,当然有一部分是教程里面本身的笔记

程序的目录如下,想要看哪一部分可以直接跳转观看

1 明确 管理系统需求

职工管理系统可以用来管理公司内所有员工的信息

本教程主要利用C++来实现一个基于多态的职工管理系统

公司中的职工分为三类:普通员工、经理、老板、显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责。

普通员工职责:完成经理交给的任务

经理职责:完成老板交给的任务,并下发任务给员工

老板职责:管理公司所有事物

管理系统中需要实现的功能如下:

  • 退出管理程序: 退出当前管理系统
  • 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工的信息为:职工编号、姓名、部门编号
  • 显示职工信息:显示公司内部所有职工的信息
  • 删除离职员工: 按照编号删除指定的职工
  • 修改职工信息:按照编号修改职员个人信息
  • 查找职工信息: 按照职工的编号或者职工的姓名进行查找相关的人员信息
  • 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
  • 清空所有文档:清空文件中记录的所有职工信息(清空之前需要再次确认,防止误操作)

页面展示哈哈哈哈哈哈哈哈哈哈:

在这里插入图片描述

看到这里,我在想没有前端的世界看起来确实没有这么美好,不多说,接着

2 创建项目

创建项目步骤如下:

我使用的是clion2020

第一步

没什么值得说的,无脑newProject就完事了

第二步

这里可以给自己的项目命名,注意了,请尽量使用英文

请尽量使用英文!!

如果不使用英文的话,有可能会导致某些莫名其妙的报错和bug,总之就是所有的名称都尽量使用英文,我将这个项目名称使用驼峰命名法将其命名为StaffManagementSystem,无脑机翻就完事了

在这里插入图片描述

创建完成!

新文件后面再添加,当然如果你看main.cpp名字不顺眼,可以改改名字

在这里插入图片描述

3 创建管理类

管理类负责的内容如下:

  • 与用户的沟通菜单界面
  • 对职工增产改查的操作
  • 与文件的读写交互操作

3.1 创建文件

在文件夹下创建头文件workerManager.h和源文件workerManager.cpp

操作如下图:

在这里插入图片描述

这个是头文件的页面,源文件也是一样的,就不演示了

在这里插入图片描述

3.2 头文件的实现

在workerManager.h中设计管理类

代码如下:

#pragma once
#include<iostream>

using namespace std;



class WorkerManager{
public:

    //构造函数
    WorkerManager();

    //析构函数
    ~WorkerManager();
};

3.3 源文件的实现

在workerManager.cpp中,将代码补全

代码如下:

#include "workerManger.h"


WorkerManager::WorkerManager() {}


WorkerManager::~WorkerManager() {}


至此,管理类创建完毕

4 菜单功能实现

功能描述:与用户的沟通界面

4.1 添加成员函数

在管理类workerManger.h中添加成员函数 void show_Menu();

在这里插入图片描述

4.2 菜单功能实现

在源文件中实现Show_Menu()函数

void WorkerManager::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;
}

4.3 测试菜单功能

在main函数中输入下列代码

在这里插入图片描述

运行页面略

注意:编码一定要保持一致,不然会乱码

5 退出功能

5.1 提供功能接口

在main 函数中提供分支选择,提供每个功能·的接口

代码:

#include <iostream> //标准输入输出流
#include "workerManger.h"
using namespace std;



int main() {

    //实例化管理者对象
    WorkerManager wm;
    int choice = 0;

   while(true) {
       //调用展示成员函数
       wm.Show_Menu();

       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;
       }
   }



    system("pause");
    return 0;
}

5.2 实现退出功能

在workerManager.h中提供退出系统的成员函数 void exitSystem();

在workerManager.cpp中提供具体的功能实现

void WorkerManager::exitSystem() {
    cout<<"欢迎下次使用"<<endl;
    system("pause");
    exit(0);
}

5.3 测试功能

在main函数的分支0中,调用退出程序的接口

case 0://退出
      wm.exitSystem();
	  break;

6 创建职工类

6.1 创建职工抽象类

职工分为三类:员工、经理、老板

将三种职工都抽象到一个类中(worker),利用多态管理不同的职工种类

职工的共有特性为: 职工编号、职工姓名、职工所在部门编号

职工的行为为:岗位职责信息描述,获取岗位名称

首先,我们先创建头文件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_DeptId; //职工所在部门名称编号
};

6.2 创建普通员工类

普通员工类继承职工抽象类,并重写父类中的纯虚函数

接下来,我们分别创建头文件employee.h和 employee.cpp

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();
};

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("员工");
}


6.3 创建经理类

经理类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似

在头文件和源文件的文件夹下分别创建manager.h 和 manager.cpp文件

manager.h中代码如下:

#pragma once
#include<iostream>
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_DeptId = dId;

}

void Manager::showInfo()
{
	cout << "职工编号: " << this->m_Id
		<< " \t职工姓名: " << this->m_Name
		<< " \t岗位:" << this->getDeptName()
		<< " \t岗位职责:完成老板交给的任务,并下发任务给员工" << endl;
}

string Manager::getDeptName()
{
	return string("经理");
}


6.4 创建老板类

老板类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似

在头文件和源文件的文件夹下分别创建boss.h 和 boss.cpp文件

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();
};

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("总裁");
}

ps:这几段都是固定套路,因为他们都是继承自workerManager,其实照抄改一改就完事了

6.5 测试多态

在咋门的主函数main.cpp中添加测试函数,并且运行,能够产生多态

测试代码如下:

#include <iostream> //标准输入输出流
#include "workerManger.h"
#include "worker.h"
#include "boss.h"
#include "manager.h"
#include "employee.h"

using namespace std;

void test() {
    Worker *demo1 = new Employee( 233 ,"老话", 1);
    demo1->showInfo();
    Worker *demo2 = new Manager( 666 ,"坤", 2);
    demo2->showInfo();
    Worker *demo3 = new Boss( 888 ,"陈老板", 3);
    demo3->showInfo();

}

测试结果

在这里插入图片描述

7 添加职工

功能描述: 批量添加职工,并且保存到文件中

7.1 功能分析

分析:

用户在批量创建的时,可能会创建不同种类的职工

如果想将所有不同种类的员工都放到一个数组中,可以将所有员工的指针维护到一个数组里

如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用Worker **的指针维护

11

ps: ******是二级指针,即指针的指针,为什么要用到二级指针,因为要想读取这样一个数组,就是需要两层的指针,第一层是因为开辟栈区new关键字返回的是指针,第二层是数组的内容是指针,因此这里要用二级指针。

7.2 功能实现

在WorkerManager.h头文件中添加成员属性以及功能的代码:

 //记录文件中的人数个数
    int m_CmpNum;

    //员工数组的指针
    Worker ** m_EmpArray;

	//记录文件中的人数个数
    int m_CmpNum;


//注意前面引入worker.h

接着便可以在WorkerManager.cpp中写下这些代码:

//在workerManager.h中注意添加以下代码,因为下列代码需要引用到这些类
//#include "employee.h"
//#include "boss.h"
//#include "manager.h"



WorkerManager::WorkerManager() {
    //初始化属性
    this->m_EmpNum = 0;
    this->m_EmpArray = NULL;
}

WorkerManager::~WorkerManager() {
    if(this->m_EmpArray!=NULL) {
        delete[]this->m_EmpArray;
        this->m_EmpArray =NULL;
    }
}//执行完类之后手动释放开辟出来的指针指向的数组


void WorkerManager::Add_Emp() {
    cout << "请输入您想添加的职工的数量:" << endl;

    int addNum = 0;//保存用户输入的数量
    cin >> addNum;

    if (addNum > 0) {

        //添加并计算添加的新空间的大小
        int newSize = this->m_CmpNum + addNum;

        //开辟新空间
        Worker **newSpace = new Worker *[newSize];

        //将原来空间下的数据,拷贝到新空间下
        if (this->m_EmpArray != NULL) {
            for (int i = 0; i < this->m_CmpNum; 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 Manager(id, name, 2);
                    break;
                case 3:
                    worker = new Boss(id, name, 3);
                    break;
                default:
                    break;
            }
            //将创建职工职责,保存到数组中
            newSpace[addNum + i] = worker;
        }
        //释放原有空间
        delete[] this->m_EmpArray;//删除的是数组的话前面要加中括号

        //更新空间的指向
        this->m_EmpArray = newSpace;

        //更新新的职工人数
        this->m_CmpNum = newSize;

        //提示添加成功
        cout << "职工信息添加成功!" << endl;


    } else {
        cout << "您输入的有误,请再次选择后输入!" << endl;
        system("cls");

    }

    system("pause");
    system("cls");
}

同时,main.cpp中加上

 case 1://增加职工信息
                wm.Add_Emp();
                break;

ps:这里我解释一下代码中的 Worker **newSpace = new Worker *[newSize];

首先,原理图如上:

11

那么我们知道数组中存放的都是Worker的指针,因此,这个数组的表现形式就是如图中所示,那么前面再加一个new,就形成了二次指针,即指针的指针

其次就是解释一下实现的原理

​ 原理其实很简单,就是新创建一个名为newSpace的指向指针数组的二次指针,根据用户输入要添加的数量以及原来数组中的空间的大小来确定新开辟的空间的大小,新数组先利用for循环将原数组的所有数据都存入到自己里面,然后再添加新输入的职工的信息,接着,添加完之后,释放原有数组的空间,紧接着更新员工的数量,那么,该功能大致简单实现。

8 文件交互、写文件

功能表述:对文件惊醒读写

​ 在上一个添加功能中,我们知识将所有的数据添加到了内存中,一旦程序结束就无法保存了

​ 因此文件管理类中需要一个与文件交互的功能,对于文件进行读写操作

8.1 设定文件路径

首先我们将文件路径,在workerManager.h中添加宏常量,并且包含头文件fstream

#include <fstream>
#define FILENAME "empFile.txt"

8.2 成员函数声明

在workerManager.h中类里添加成员函数 void save();

8.3保存文件功能实现

在该类的源文件中进行编写,代码如下

//保存文件的功能
void WorkerManager::save() {
    ofstream ofs;
    ofs.open("empFile.txt", ios::out);
    for (int i = 0; i < this->m_CmpNum; i++) {
        ofs << this->m_EmpArray[i]->m_Id << "  "
            << this->m_EmpArray[i]->m_Name << "  "
            << this->m_EmpArray[i]->m_DeptId << "  "
            << endl;
    }

    ofs.close();
}

9 文件交互 - 读文件

功能描述:将文件中的内容读到程序中

虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中的数据读到程序中

而我们的功能程序还需要由清空文件的需求

因此构造函数初始化数据的情况分为三种

  1. 第一次使用,文件未被创建
  2. 文件存在,但是数据被用户清空
  3. 文件存在,并且保存职工的所有数据

9.1 文件未创建

在workerManager.h中添加新的成员属性 m_FileIsEmpty标志文件是否清空

bool m_FileIsEmpty;

并将对应的源文件的该类的构造函数代码,做以下修改:

WorkerManager::WorkerManager() {

    ifstream  ifs;
    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;
    }

}

9.2 文件存在且数据为空

在workerManager.cpp中的构造函数追加代码:

//文件存在,来判断有没有记录
    char ch;
    ifs >> ch;//这里代表文件的指针的位置向右移动一个单位
    if(ifs.eof())//判断文件的指针是否在文件的最后的位置
    {
        cout<<"文件为空!"<<endl;
        this->m_EmpNum = 0;
        this->m_EmpArray = NULL;
        this->m_FileIsEmpty = true;

        ifs.close();
        return;
    }

同时,在添加职工的函数里面添加:

        //更新职工不为空的标志
        this->m_FileIsEmpty = false;

9.3 文件存在且保存职工数据

9.3.1 获取记录的职工人数

在workerManager.h中添加成员函数 int get_EmpNum();

//统计人数
int get_EmpNum();

并在源文件中添加该代码:

//获取职工人数
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)//这里的意思是,右移代码到一个int 一个string  一个int 则满足循环的条件
    {
        num++;
    }
    ifs.close();

    return num;
}

然后在该类的构造函数中追加代码:

int num = this->get_EmpNum();
    cout<<"职工的个数为:"<<num<<endl;//测试代码
    this->m_EmpNum = num;//更新成员属性
9.3.2 初始化数组

根据职工的数据,初始化workerManageer中的Worker ** m_EmpArray指针

在workerManager.h中,添加成员函数

//初始化数组
    void init_Emp();

然后在其源文件中实现

//初始化数组,即根据文件更新员工的人数
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;
        //根据部门的不同,创建不同的对象指针
        if(dId==1){
            //普通员工
            worker = new Employee(id,name,dId);//返回的是指针,就用指针来接收
        }
        else if (dId==2){
            //经理
            worker = new Manager(id,name,dId);
        }
        else if(dId ==3){
            //BOSS
            worker = new Boss(id,name,dId);
        }

        //将创建的对象指针,保存在数组当中
        this->m_EmpArray[index] = worker;
        index++;
    }
}

同时,在其构造函数中,引入这个函数,引入位置如下:

WorkerManager::WorkerManager() {

    ifstream ifs;
    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;
    }
    //文件存在,来判断有没有记录
    char ch;
    ifs >> ch;//这里代表文件的指针的位置向右移动一个单位
    if (ifs.eof())//判断文件的指针是否在文件的最后的位置
    {
        cout << "文件为空!" << endl;
        this->m_EmpNum = 0;
        this->m_EmpArray = NULL;
        this->m_FileIsEmpty = true;

        ifs.close();
        return;
    }

    int num = this->get_EmpNum();
    cout << "职工的个数为:" << num << endl;//测试代码
    this->m_EmpNum = num;//更新成员属性

    //文件存在了,我们可以初始化数组
    //首先先根据职工·人数创建数组
    this->m_FileIsEmpty = true;
    this->m_EmpArray = new Worker *[this->m_EmpNum];
    this->init_Emp();
    
    //测试代码
    for (int i = 0; i < m_EmpNum; i++) {
        cout << "职工号: " << this->m_EmpArray[i]->m_Id
             << " 职工姓名: " << this->m_EmpArray[i]->m_Name
             << " 部门编号: " << this->m_EmpArray[i]->m_DeptId << endl;
    }

}

10 显示职工

功能描述:显示当前所有职工信息

10.1 显示职工函数声明

在workerManager.h中添加成员函数show_Emp();

//显示职工
void Show_Emp();

10.2 其函数的功能实现

在cpp文件中实现上面的成员函数

//显示职工
void WorkerManager::Show_Emp() {
    //首先先判断文件是否为空
    if(this->m_FileIsEmpty == true){
        cout<<"暂无职工信息!!"<<endl;
    }
    else {
        for (int i = 0; i < m_EmpNum; i++) {
            //利用多态调用接口
            this->m_EmpArray[i]->showInfo();
        }
    }

    system("pause");
    system("cls");
}

最后在主函数里面添加这个函数就可以了

11 删除职工

功能描述: 按照职工的编号进行删除职工的操作

11.1 删除职工函数声明

在workerManger.h中添加成员函数 void Del_Emp();

//删除职工
void Del_Emp();

11.2 职工是否存在的函数声明

很多功能需要根据职工是否存在进行操作如:删除职工、修改职工、查找职工

因此我们很有必要添加这个函数,一面后续调用

在workerManager.h中添加成员函数 int IsExist(int id);

//按照职工编号判断职工是否存在,若存在,返回职工在数组中的位置,不存在返回-1

int IsExist(int id);

11.3 是否存在的函数的实现

在workerManager.cpp中实现成员函数

//判断员工是否存在

int WorkerManager::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;
}

11.4 删除职工功能实现

代码如下

//删除职工
void WorkerManager::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++){
                //数据前移
                this->m_EmpArray[i] = this->m_EmpArray[i+1];
            }
            this->m_EmpNum--;
            //同步更新到文件中
            this->save();

            cout<<"删除成功!"<<endl;
            system("pause");
            system("cls");
            return;
        }
        else {
            cout<<"查无此人!"<<endl;
            return;

        }
    }
}

注意,这里采用的数组的删除方式是,将要删除的数组的后面的所有数据位置都往前移一位,然后再将员工数量的变量减1,因此,这里删除的算法的复杂度为n,还不够好,因此,其实我们创建的数组可以是链表的形式,这样删除的操作,复杂度是1,但是碍于技术原因,我这里没有用这个来实现,等熟练运用链表之后,我会来修改的。

12 修改职工

功能描述:能够按照职工的编号对职工的信息进行修改并保存

12.1 修改职工的函数声明

老规矩,在管理员函数头文件中添加成员函数

//修改职工
void Mod_Emp();
12.2 函数实现

在该类的源文件中添加如下代码以实现其功能

//修改职工
void WorkerManager::Mod_Emp() {
    //首先先判断是否有人
    if(this->m_FileIsEmpty){
        cout<<"没有职工!"<<endl;
    }
    else{
        //按照职工的编号来删除职工
        cout<<"请输入想要修改的职工的编号"<<endl;
        int id = 0;
        cin>>id;
        int index = this->IsExist(id);

        if(index!=-1)//说明职工存在,可以删除职工的信息
        {
            int newId = 0;
            string name = "";
            int dId = 0;
            cout<<"请输入该员工的新的员工编号"<<endl;
            cin>>newId;
            cout<<"请输入该员工的名字:"<<endl;
            cin>>name;
            cout<<"请输入该员工所在的部门的编号"<<endl;
            cout<<"1、普通职工"<<endl;
            cout<<"2、部门经理"<<endl;
            cout<<"3、老板"<<endl;
            cin>>dId;
            Worker *worker = NULL;
            switch (dId) {
                case 1: //普通员工
                    worker = new Employee(newId, name, 1);
                    break;
                case 2: //经理
                    worker = new Manager(newId, name, 2);
                    break;
                case 3:  //老板
                    worker = new Boss(newId, name, 3);
                    break;
                default:
                    break;
            }

            this->m_EmpArray[index] = worker;



            //同步更新到文件中
            this->save();

            cout<<"修改成功!"<<endl;
            system("pause");
            system("cls");
            return;
        }
        else {
            cout<<"查无此人,修改失败!"<<endl;
            return;

        }
    }
}

其逻辑上和上面的删除职工十分的相似。照着干就完事了

13 查找职工

功能描述: 提供两种查找职工的方式,一种按照职工编号,一种按照职工姓名

13.1 查找职工函数声明

在管理员类头文件中添加成员函数

//查找职工
void Find_Emp();

13.2 查找职工函数实现

老样子,在源文件中实现该函数

//查找职工
void WorkerManager::Find_Emp() {
    if (this->m_FileIsEmpty) {
        cout << "没有职工!" << endl;
    } else {
        int chioce = 0;

        cout << "请选择你要以什么方式查找职工:" << endl;
        cout << "1、职工编号" << endl;
        cout << "2、职工姓名" << endl;

        cin >> chioce;

        if (chioce == 1) {
            cout << "请输入想要查找的职工的编号" << endl;
            int id = 0;
            cin >> id;
            int index = this->IsExist(id);

            if (index != -1)//说明职工存在,可以说其存在
            {
                cout << "该职工存在!" << endl;
                this->m_EmpArray[index]->showInfo();
            } else {
                cout << "查无此人!" << endl;
            }
            system("pause");
            system("cls");
        } else if (chioce == 2) {
            cout << "请输入想要查找的职工的姓名" << endl;
            string name = "";
            cin >> name;
            bool flag = false;

            for (int i = 0; i < this->m_EmpNum;i++){
                if(this->m_EmpArray[i]->m_Name == name) {
                    flag = true;
                    cout<<"该职工存在!"<<endl;
                    this->m_EmpArray[i]->showInfo();
                }
            }
            if(flag == false) {
                cout<<"查无此人!"<<endl;
            }
            system("pause");
            system("cls");


        } else {
            cout << "您输入有误,请重试!" << endl;
        }
    }
}

套路一样的,简单,不多说了,直接看代码

14 排序

功能描述:按照职工编号进行排序,排序的顺序由用户指定

14.1 排序函数声明

老规矩,头文件添加成员函数

//排序职工
void Sort_Emp();

14.2 函数功能实现

//排序职工
void WorkerManager::Sort_Emp() {
    //首先先判断文件是否为空
    if (this->m_FileIsEmpty == true) {
        cout << "文件为空,无法排序!" << endl;
    } else {
        cout << "请选择你要以什么方式排序:" << endl;
        cout << "1、按职工编号进行升序" << endl;
        cout << "2、按职工编号进行降序" << endl;

        int select = 0;
        cin >> select;

        if (select == 1) {
            for (int i = 0; i < this->m_EmpNum; i++) {
                for (int j = 0; j < i; j++) {
                    Worker *work = NULL;
                    if (this->m_EmpArray[j]->m_Id > this->m_EmpArray[i]->m_Id) {
                        work = this->m_EmpArray[j];
                        this->m_EmpArray[j] = this->m_EmpArray[i];
                        this->m_EmpArray[i] = work;
                    }
                }
            }
            this->save();
            cout<<"排序成功!"<<endl;
        } else if (select == 2) {
            for (int i = 0; i < this->m_EmpNum; i++) {
                for (int j = 0; j < i; j++) {
                    Worker *work = NULL;
                    if (this->m_EmpArray[i]->m_Id > this->m_EmpArray[j]->m_Id) {
                        work = this->m_EmpArray[i];
                        this->m_EmpArray[i] = this->m_EmpArray[j];
                        this->m_EmpArray[j] = work;
                    }
                }
            }
            this->save();
            cout<<"排序成功!"<<endl;
        } else {
            cout << "您输入有误,请重新输入!" << endl;
        }
    }

这里的排序方法可以有很多种,我用的是冒泡排序(很经典),其他套路一致,没什么少说的

15 清空文件

功能描述:将文件中的记录都清空

不多说了,源文件代码如下,头文件创建相应函数就行了

//清空文件功能
void WorkerManager::Clean_File() {
    //首先先判断文件是否为空
    if (this->m_FileIsEmpty == true) {
        cout << "文件为空!" << endl;
    } 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();

            //堆区数据维护,指针维护
            if (this->m_EmpArray != NULL) {
                for (int i = 0; i < this->m_EmpNum;i++) {
                    if (this->m_EmpArray[i] != NULL){
                        delete m_EmpArray[i];
                    }
                }
            }
            this->m_EmpNum = 0;
            delete [] this->m_EmpArray;
            this->m_EmpArray = NULL;
            this->m_FileIsEmpty = true;
            cout<<"清空成功!"<<endl;
        }



    }

    system("pause");
    system("cls");
}

然后在主函数里面添加上就可以了。

总结

  this->m_EmpArray[i] = this->m_EmpArray[j];
                    this->m_EmpArray[j] = work;
                }
            }
        }
        this->save();
        cout<<"排序成功!"<<endl;
    } else {
        cout << "您输入有误,请重新输入!" << endl;
    }
}

这里的排序方法可以有很多种,我用的是冒泡排序(很经典),其他套路一致,没什么少说的



## 15 清空文件

功能描述:将文件中的记录都清空



不多说了,源文件代码如下,头文件创建相应函数就行了

```c++
//清空文件功能
void WorkerManager::Clean_File() {
    //首先先判断文件是否为空
    if (this->m_FileIsEmpty == true) {
        cout << "文件为空!" << endl;
    } 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();

            //堆区数据维护,指针维护
            if (this->m_EmpArray != NULL) {
                for (int i = 0; i < this->m_EmpNum;i++) {
                    if (this->m_EmpArray[i] != NULL){
                        delete m_EmpArray[i];
                    }
                }
            }
            this->m_EmpNum = 0;
            delete [] this->m_EmpArray;
            this->m_EmpArray = NULL;
            this->m_FileIsEmpty = true;
            cout<<"清空成功!"<<endl;
        }



    }

    system("pause");
    system("cls");
}

然后在主函数里面添加上就可以了。

总结

这个小程序,精华便是充分利用了面向对象的优势,封装、继承、多态都在该项目中有所体现,同时也用到了像排序算法、逻辑判断等,最重要的还是增加的对于指针的理解,知道了有二次指针这个东西,就是不知道有没有三次指针哈哈哈哈哈哈哈哈哈哈,总而言之,这个小程序对于c++的初学者的帮助还是十分大的,我也因此受益良多。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值