小白or初学者快速上手C++ And 职工管理系统

28 篇文章 18 订阅
订阅专栏

👆有VIP可以直接下载,没有的看文章里的源码,一样的,粘贴复制到分文件就能运行

👂 远走高飞 - 金志文 - 单曲 - 网易云音乐

👂  丢了你 - ukakakaxxl - 单曲 - 网易云音乐

👂  地铁等待 - 阳光开朗帅气大学生/爆音BOOM/黑崎子 - 单曲 - 网易云音乐

今日鸡汤:你已经是一个成熟的废物了,要学会搞清自己的定位(😎)

本博客适用于1,期末快速复习,或者初学者2,入门C++语法

不得不说,虽然挺适合新手入门,然而!从第二个项目《职工管理系统》开始,就一堆BUG了

权当增加熟练度吧,与之后书籍的学习互相印证,也为后续项目夯实基础

项目写的稀巴烂!!!但还是坚持跟着敲完了,连简单的东西都不会,怎么能接受更复杂的项目呢

暂定思路是,借各种管理系统和C++小游戏,这两种项目,夯实面向对象在不涉及前后端交互前提下的基础,这些200~1500行的小项目,是前期打基础所必须的

第2步,开始尝试前后端交互的简单项目,这里可能需要敲到4000,5000行左右,熟练点的话,一个寒假的一半时间就能完成(当然目前差远了,前后端交互的Demo还不会,虽然有大佬说,学C++不用往前后端交互的方向.....)

目录

🍍前言

🍍过程

🌳添加职工

🌳文件交互

🍍源代码

🌳设计思路 + 总体框架

🌳效果展示

🌳原代码

🍌worker.h

🍌employee.h

🍌manager.h

🍌boss.h

🍌workermanager.h

🍌employee.cpp

🍌manager.cpp

🍌boss.cpp

🍌workerManager.cpp

🍌main.cpp

🌼总结


🍍前言

本博客食用方式

1,先看一遍前置博客,这个过程可能需要3~5小时(涉及所有C++基础知识点)(代码跟着敲一遍;基础好可跳过)

2,再看职工管理系统的框架是怎么设计的,然后看源码以及大量注释

3,自己动手敲一遍

注意!!

如果发现程序卡住,可以采取下面的方法来测试完整的功能:

第一步:如果你输入2,显示职工,发现卡住然后退出了程序

第二步:重新运行,输入1,添加1个职工,添加完发现不能进行其他操作,卡住,退出

第三步:再次运行,发现所有数据清空了,比如输入2显示,会输出文件为空

第4步:此时新增3~5个职工就可以正确执行所有操作了,注意不要在编号或者类别中输入汉字 

前置博客

B站黑马,C++基础_千帐灯无此声的博客-CSDN博客

类和对象 --- 封装+对象特性_千帐灯无此声的博客-CSDN博客

友元 + 运算符重载_千帐灯无此声的博客-CSDN博客

C++继承_千帐灯无此声的博客-CSDN博客

C++多态和文件读写_千帐灯无此声的博客-CSDN博客

写作缘由

虽然期末大作业已经做了一个,包含彩色欢迎界面和彩色颜文字的旅馆住宿管理系统

(源代码在👇下面这篇博客结尾,可直接复制源码)

大一下暑期计划 + 2023字节青训营预告直播_千帐灯无此声的博客-CSDN博客

还是想跟着黑马C++再做一次,主要为了加深对C++纯虚函数等语法以及.h,.cpp分文件的理解,夯实基础

会结合gpt4.0和google,对不熟悉的地方进行解释

问答

C++项目,.h和.cpp以及main.cpp的功能分别是什么

在一个C++项目中,通常包含有以下三种文件:

1. .h 文件(头文件):头文件包含函数、类和变量的声明。使用 #include 指令可以将头文件包含到其他源文件中。头文件常用来定义函数原型和类的接口。

2. .cpp 文件(源文件):源文件实现了头文件中声明的函数和类的具体逻辑。它包含了函数和类的定义、实现以及其他必要的逻辑代码。

3. main.cpp 文件:main.cpp 是程序的入口点。它包含了一个名为 main 的函数,是程序执行的起始点。在 main.cpp 文件中通常会调用其他的函数和类,实现代码的逻辑。

总结一下, .h 文件用于声明函数和类的接口, .cpp 文件用于实现函数和类的逻辑, main.cpp 文件是程序的入口点,负责调用其他函数和类来实现程序的功能。

🍍过程

🌳添加职工

.....

🌳文件交互

注意后面代码中,我们写workerManager.cpp文件时,构造函数WorkerManager::WorkerManager()中,第二种情况,文件存在,数据为空中

我们需要初始化文件为空👇

//初始化文件是否为空
this->m_FileIsEmpty = true;

那么什么时候,需要

需要在后面的void WorkerManager::Add_Emp()中,也就是WorkerManager这个类作用域下的Add_Emp()函数中,增加这一行👇

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

关于get_EmpNum()函数中getline(ifs, line)和平时使用的getline(cin, line)的一点解释👇

注意line和str都是String类字符串

getline(ifs, line)getline(cin, str) 都是 C++ 标准库中提供的用于读取字符串的函数,但它们有一些异同点:

相同点:

  1. 两个函数都可以读取字符串类型的数据,不受字符串长度的限制。

  2. 两个函数都会自动忽略输入流中的换行符,并将其替换为终止符 \0

  3. 两个函数都具有可以额外指定分隔符的功能,可以通过第三个参数来指定分隔符。

不同点:

  1. getline(ifs, line) 函数从文件流中读取字符串,而 getline(cin, str) 函数从标准输入流中读取字符串。

  2. getline(ifs, line) 函数可以用于读取文件中的每一行,而 getline(cin, str) 函数主要用于读取用户从控制台输入的一行数据。

  3. 在读取用户输入时,getline(cin, str) 函数通常与 cin 流对象一起使用,由于 cin 默认会留下一个换行符,所以建议先使用 cin.ignore() 清除缓冲区的换行符再使用 getline(cin, str) 读取用户输入。而在读取文件时,不需要像读取用户输入那样清空缓冲区。

总的来说,getline(ifs, line)getline(cin, str) 都是很常用的读取字符串的函数,但是要注意二者的使用场景及要点。

关于streamstring的解释

通过 stringstream 类来解析一行文本内容,但是使用的分隔符是空格。在代码中,我们首先定义了三个字符串变量 idnamedepId,用于存储分隔后的数据。然后,我们通过 >> 运算符,依次将 ss 流中的内容读取到这三个字符串变量中。由于默认情况下,>> 运算符会以空格为分隔符,所以我们就可以很方便地实现按空格分隔一行文本内容的功能。 

stringstream 是 C++ 标准库中的一个类,它可以将一个字符串对象看作输入/输出流来处理。也就是说,我们可以通过 sstream 将一个字符串对象分解成若干个子串,或者将若干个子串拼接成一个新的字符串对象 

注意!stringstream类,需要包含头文件👇

#include <sstream> //stringstream

否则会报错:error: variable 'std::stringstream ss' has initiallizer but incomplete type

修改后,虽然.txt文件中,dId部门编号这个属性依然以方框形式(二进制读入下的奇怪符号)出现,但是人数已经能正常统计了

敲代码过程中遇到个BUG,需要.txt为空的前提下,先从键盘输入数据,才能正常进行显示和删除等操作,按弹幕的两种方法也没解决(据说是权限冲突,但是没解决)

🍍源代码

🌳设计思路 + 总体框架

主要包括以下几个文件

  • worker.h:定义了一个抽象类Worker,包含纯虚函数showInfo()和getDeptName(),以及成员变量职工编号、职工姓名和部门编号。

  • employee.h:从Worker类派生出Employee类,重写了父类的虚函数showInfo()和getDeptName()。

  • manager.h:从Worker类派生出Manager类,重写了父类的虚函数showInfo()和getDeptName()。

  • boss.h:从Worker类派生出Boss类,重写了父类的虚函数showInfo()和getDeptName()。

  • workerManager.h:定义了一个WorkerManager类,用于管理职工信息。该类包括了添加职工、保存文件、读取文件、显示职工信息、删除职工、修改职工、查找职工、排序职工等功能。

对于设计思路和基础框架,可以通过以下步骤来实现职工管理系统:

  1. 定义抽象类Worker,包含纯虚函数showInfo()和getDeptName(),以及成员变量职工编号、职工姓名和部门编号。

  2. 从Worker类派生出Employee类、Manager类和Boss类,分别重写父类的虚函数showInfo()和getDeptName()。

  3. 在workerManager.h中定义WorkerManager类,用于管理职工信息。在该类中,声明了一个保存职工信息的动态数组m_EmpArray,并定义了一些操作职工信息的成员函数,如添加职工、保存文件、读取文件、显示职工信息、删除职工、修改职工、查找职工、排序职工等。

  4. 在workerManager.cpp中实现WorkerManager类中的成员函数,具体包括创建构造函数、展示菜单、退出系统、添加职工、保存文件、判断文件是否为空、统计文件中的人数、初始化员工、显示职工、删除员工、判断职工是否存在、修改员工、查找员工、排序员工、清空文件和析构函数等。

  5. 在main.cpp中,创建WorkerManager对象,调用Show_Menu()方法展示菜单,并根据用户的选择执行相应的操作。

总体来说,该程序采用了面向对象的设计思想,将不同类别的职工(员工、经理、老板)抽象为Worker类的派生类,并使用WorkerManager类对职工进行管理和操作。通过分散功能实现的方式,使得代码结构清晰,易于扩展和维护。

补充

虽然worker.h看着没什么用,但是......

Worker类作为一个抽象类,具有以下几个必要性:

  1. 统一的接口:Worker类定义了纯虚函数showInfo()和getDeptName(),这两个函数在派生类(Employee、Manager、Boss)中被重写。这样做的好处是,无论是哪个派生类的对象,都可以通过Worker指针或引用调用这两个函数,实现了面向抽象编程,使得代码更加灵活和可扩展。

  2. 共享数据成员:Worker类中定义了职工编号、职工姓名和部门编号这三个成员变量,这些属性是所有职工共有的。通过将这些属性放在Worker类中,可以避免在每个派生类中重复定义相同的成员变量,节省了代码量。

  3. 继承关系的建立:Worker类作为父类,被Employee、Manager和Boss类所继承。通过继承机制,可以实现多态性,将不同类型的职工对象存储到同一个动态数组中,方便对职工集合进行管理和操作

虽然在当前给出的代码中,并没有直接使用Worker类创建对象,但Worker类的存在为整个程序提供了良好的面向对象设计基础,使得代码更具一般性和可扩展性。如果以后需要添加新的职工类别,例如技术人员或实习生,只需要从Worker类派生出新的子类,并重写相应的函数即可,无需对已有代码做大幅修改。因此,Worker类在该程序中是具有必要性的 

🌳效果展示

添加职工

显示职工

修改职工

后面的功能也都实现了,不过不小心在输入int编号的地方,输入了汉字,卡壳了,懒得重新弄了,就这样吧....

🌳原代码

🍌worker.h

#pragma once //防止头文件重复包含
#include<iostream>
using namespace std;

//职工抽象类
class Worker
{
public:

    //显示个人信息
    virtual void showInfo() = 0; //抽象类中, 不作实现, 用纯虚函数

    //获取岗位名称
    virtual string getDeptName() = 0;

    //职工编号
    int m_Id;
    //职工姓名
    string m_Name;
    //部门编号
    string m_DeptId;
};

🍌employee.h

//普通员工文件
#pragma once
#include<iostream>
using namespace std;
#include "worker.h"

class Employee:public Worker //子类重写父类虚函数, 父类是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 Manager:public Worker //public方式继承Worker类
{
public: //作用域

    //构造函数
    Manager(int id, string name, int dId); //职工姓名,编号,部门编号

    //经理类中重写父类纯虚函数
    //显示个人信息
    virtual void showInfo();
    //获取岗位名称
    virtual string getDeptName();
};

🍌boss.h

//老板文件
//由manager.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();
};

🍌workermanager.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 WorkerManager
{
public:
    //构造函数  用于初始化对象
    WorkerManager(); //.h声明, .cpp实现


    //展示菜单
    void Show_Menu(); //.h中声明, .cpp中实现

    //退出系统
    void ExitSystem(); //退出系统的接口

    //记录职工人数
    int m_EmpNum;

    //职工数组指针
    Worker ** m_EmpArray; //Worker**是指向Worker指针的指针类型

    //添加职工
    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();
};

🍌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"

//构造函数
Manager::Manager(int id, string name, int dId) //职工姓名,编号,部门编号
{
    this->m_Id = id; //自身的属性 = 传入的
    this->m_Name = name;
    this->m_DeptId = dId;
}

//.h声明, .cpp实现

//显示个人信息
void Manager::showInfo() //去掉virtual, 加上作用域Manager
{
    cout<<"职工编号:"<<this->m_Id
        <<"\t职工姓名:"<<this->m_Name
        <<"\t岗位:"<<this->getDeptName()
        <<"\t岗位职责:完成老板交给的任务, 并下发任务给普通员工"<<endl;
}

//获取岗位名称
string Manager::getDeptName()
{
    return string("经理");
}

🍌boss.cpp

//由manager.cpp复制粘贴过来, 略作修改

#include "boss.h"

//构造函数
Boss::Boss(int id, string name, int dId) //职工姓名,编号,部门编号
{
    this->m_Id = id; //自身的属性 = 传入的
    this->m_Name = name;
    this->m_DeptId = dId;
}

//.h声明, .cpp实现

//显示个人信息
void Boss::showInfo() //去掉virtual, 加上作用域Manager
{
    cout<<"职工编号:"<<this->m_Id
        <<"\t职工姓名:"<<this->m_Name
        <<"\t岗位:"<<this->getDeptName()
        <<"\t岗位职责:管理公司所有事务"<<endl;
}

//获取岗位名称
string Boss::getDeptName()
{
    return string("总裁");
}

🍌workerManager.cpp

#include "workerManager.h" //引入头文件
#include <sstream> //stringstream

WorkerManager::WorkerManager()
{
    //1,文件不存在
    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; //终止后续操作
    }

    //2,文件存在  数据为空
    char ch;
    ifs >> ch; //左移运算符读入一个字符
    if(ifs.eof()) { //1表示文件为空
        //文件为空
        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; //成员属性更新为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 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;
}

//退出系统  .cpp中实现
void WorkerManager::ExitSystem()
{
    cout<<"欢迎下次使用"<<endl;
    system("pause"); //按任意键后退出
    exit(0); //退出程序
}

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

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

    if(addNum > 0) {
        //添加
        //计算添加新空间大小
        int newSize = this->m_EmpNum + addNum; //新大小 = 原大小 + 新增

        //开辟新空间
        Worker ** newSpace = new Worker*[newSize]; //大小为newSize, 指向指针Worker的指针newSpace

        //将原来空间数据, 拷贝到新空间下
        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: //这里new Employee需要在.h中引入头文件
                worker = new Employee(id, name, 1); //父类指针指向子类对象
                break;
            case 2: //这里new Employee需要在.h中引入头文件
                worker = new Manager(id, name, 2);
                break;
            case 3: //这里new Employee需要在.h中引入头文件
                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(); //调用下面的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]是指向职工对象的指针
            << this->m_EmpArray[i]->m_Name<<" " //职工对象又是Worker的派生类
            << this->m_EmpArray[i]->m_DeptId<<endl; //派生类中的成员变量需要再次使用->访问
    }

    //关闭文件
    ofs.close();
}

//统计文件中的人数
//在上面的构造函数, 第3种情况, 调用该函数
int WorkerManager::get_EmpNum()
{
    ifstream ifs; //ifstream对象
    ifs.open(FILENAME, ios::in); //打开文件 读

    int id; string name; int dId; //读到的数据放变量里

    //右移运算符读入
    int num = 0;
//    while(ifs >> id && ifs >> name && ifs >> dId) {
//        //统计人数
//        num++;
//    }
    //上面3行代码,会出现dId变成方框导致人数统计为0的情况
    string line;
    while(getline(ifs, line)) {
        stringstream ss(line); //创建对象ss并初始化为字符串
        //使用stringstream按空格分隔数据
        ss >> id >> name >> dId;
        num++;
    }
    if(num > 0) this->m_FileIsEmpty = false;
    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;

        if(dId == 1) //普通职工
            worker = new Employee(id, name, dId); //new创建对象
        else if(dId = 2)
            worker = new Manager(id, name, dId);
        else //老板
            worker = new Boss(id, name, dId);
        this->m_EmpArray[index++] = worker;
    }

    //关闭文件
    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
    {
        //按照职工编号删除
        cout<<"请输入想要删除的职工编号: "<<endl;
        int id = 0;
        cin>>id;

        int index = this->IsExist(id);

        if(index != -1) //职工存在且删除 index 位置职工
        {
            //数据前移
            for(int i = index; i < this->m_EmpNum - 1; ++i) {
                this->m_EmpArray[i] = this->m_EmpArray[i + 1];
            }
            this->save();

            cout<<"删除成功"<<endl;
        }
        else
        {
            cout<<"删除失败,未找到该职工"<<endl;
        }
    }

    //任意键清屏
    system("pause");
    system("cls");
}

//判断职工是否存在  存在则返回职工所在数组的位置,不存在返回-1
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; //返回的是下标
}

//修改员工
void WorkerManager::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 Manager(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 WorkerManager::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;

                    //调用显示信息接口
                    this->m_EmpArray[i]->showInfo();
                }
            }
            if(!flag) {
                cout<<"查找失败,查无此人!"<<endl;
            }
        }
    }
    //按任意键清屏
    system("pause");
    system("cls");
}

//排序员工
void WorkerManager::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;
                    }
                }
            }

            //判断一开始认定的 最小值或最大值 是不是计算的最小值或最大值 如果不是 交换数据
            if(i != minOrMax) {
                Worker * temp = this->m_EmpArray[i]; //记录数组中下标i的元素
                this->m_EmpArray[i] = this->m_EmpArray[minOrMax];
                this->m_EmpArray[minOrMax] = temp;
            }
        }

        cout<<"排序成功!排序后的结果为:"<<endl;
        this->save(); //排序后结果保存到文件中
        this->Show_Emp(); //展示所有职工
    }
}

//清空文件
void WorkerManager::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");
}

WorkerManager::~WorkerManager()
{
    if(this->m_EmpArray != NULL) { //手动释放堆区数据
        delete [] this->m_EmpArray;
        this->m_EmpArray = NULL;
    }
}

🍌main.cpp

#include<iostream>
using namespace std;
#include "workerManager.h" //引入类对应的自定义头文件

//#include "worker.h"
//#include "employee.h"
//#include "manager.h"
//#include "boss.h"


int main()
{
    //三个不同的对象, 都调用同一个函数showInfo(), 就是多态(一个接口多种形态)

    //测试代码
//    Worker * worker = NULL; //创建一个指向父类对象的空指针
//    worker = new Employee(1,"张允", 1); //父类指针指向子类对象
//    worker->showInfo();
//    delete worker;
//
//    worker = new Manager(2, "李四", 2);
//    worker->showInfo();
//    delete worker;
//
//    worker = new Boss(3, "钻石王老五", 3);
//    worker->showInfo();
//    delete worker;

    //实例化管理者对象
    WorkerManager wm; //实现主函数对该类的访问

    int choice = 0; //存储用户选择

    while(1) {
        //调用展示菜单成员函数
        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:
            system("cls"); //清屏
            break;
        }
    }

    //调用展示菜单成员函数
    wm.Show_Menu();

    system("pause");
    return 0;
}

🌼总结

目前为止,跟了2个管理系统的项目

第一个是700行的,旅馆住宿管理系统(当时跟的gpt结合CSDN两篇比较好的博客,没用分文件,同时囫囵吞枣,只是跟着敲了一遍,但是没有尝试去弄懂每一个封装好的函数以及它们之间的联系)

第二个就是800行黑马的,职工管理系统(完全跟了一遍思路,但是说实话,很多算法或者实现写的稀巴烂,真的,不如自己设计的思路清晰,但考虑到学习效率的问题,先无脑跟了一遍)

下一步

也就是暑假要做的,B站随便都能找到20~30个不同的C++小游戏项目,大概介于200~2000行之间,有空做2~3个先,俄罗斯方块,计算器,飞机大战,植物大战僵尸等等,都是可视化的,而不是黑框 

其实想想,项目真不难,而且,一切的一切,都是以算法和数据结构为基础的,就拿这个职工管理系统来说,如果真下功夫,你也许能只用300行,而且效率比黑马的高100倍设计出一个功能更完善,时间复杂度更低的管理系统,学以致用,加油,投身到项目中,算法与项目齐头并进!

最后

最后就是前后端交互(也就是一些搞Java所谓的,入门),或者C++偏底层的东西,比如手写个STL?

还有Github找项目,先跑通,再结合ReadMe啃源码,一行一行,弄懂弄通后,自己跟着敲一遍,稍加改动看看有什么不同,会出现什么BUG,为什么,如何优化....

补充

这次项目,我还发现个自己一直以来的问题,似乎从来没发掘过编译器作为工具的作用,比如编译器自带的断点我不会,一直都是在关键地方前后cout<<来观察结果

还有就是选中某一段代码后,右键会弹出很多功能,这些都是需要慢慢掌握的,以前没接触项目,所以从未需要这些东西

希望以后在做项目中,慢慢掌握编译器的工具,同时,学会使用不同编译器,毕竟不同公司的编译器肯定不一样,尝试一专多能

写文章

热门文章

  • 蓝桥杯C++组怒刷50道真题(填空题) 446800
  • 大四的告诫 48020
  • 30个题型+代码(冲刺2023蓝桥杯)(上) 20379
  • C++实现俄罗斯方块(源码+详解) 13993
  • 2022蓝桥杯省赛C++A组初尝试 13968

分类专栏

  • 算法 + 数据结构
  • 力扣 hot 100 23篇
  • 2025蓝桥杯备赛 26篇
  • 《算法训练营入门篇》 15篇
  • 算法比赛 10篇
  • 啊哈算法 9篇
  • 408 计算机基础
  • 网络编程 4篇
  • Mysql 4篇
  • Linux 2篇
  • 语言
  • C++ 28篇
  • Go 4篇
  • Python机器学习 8篇
  • 项目
  • TinyWebServer 14篇
  • muduo 1篇
  • MIT 6.824 3篇
  • BUG收录 2篇
  • 杂记 11篇

最新评论

  • 单例模式 C++

    千帐灯无此声: https://top.interviewguide.cn/issue/673 你看看这个链接,它是不是写错了,拷贝和赋值用delete的话,那前面两个default也要换吗,这里default是什么意思

  • 单例模式 C++

    weixin_48065421: 写的真好!纠正一下,后面很多禁用拷贝构造和赋值构造delete都写成了default

  • Finalshell连接Linux超时之Connection timed out: connect

    两仪式quq: 牛的,但是不知道为啥ip会突然变了

  • WebServer -- 数据库连接池

    m0_46134217: connList是链表还是列表呢?

  • Finalshell连接Linux超时之Connection timed out: connect

    2301_76880661: 我去谢谢你!!!!!!!!!!!

大家在看

  • 【快速上手】linux环境下Neo4j的安装与使用
  • 黑神话:悟空 后话 189
  • 简单生活的快乐 337

最新文章

  • 6.824 MapReduce 代码分析
  • Lab 1 实验 MapReduce
  • 力扣 hot100 -- 技巧
2024
09月 1篇
08月 1篇
07月 7篇
06月 4篇
05月 5篇
04月 4篇
03月 9篇
02月 10篇
01月 9篇
2023年87篇
2022年24篇

目录

目录

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千帐灯无此声

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

天下网标王政府网站升级优化网站自然优化需要软件吗外贸网站优化接任务栖霞营销型网站优化公司渝中区网站优化论坛优化和其他网站有什么不同企业网站优化服务报价东莞优化网站界面姑苏网站优化哪家好厦门市网站优化报价个人如何优化网站有哪些方法网站优化最新宿迁网站优化佛山网站优化策略网站优化怎么做鹤壁郑州网站推广优化江阴营销网站设计优化价格河南网站关键词优化费用惠州企业网站关键词优化推广本地网站优化大概多少钱漳州外贸网站google优化济南优化网站方法东湖免费的网站优化皮革网站优化多少钱济南正规seo网站优化平台新乡百度网站优化找哪家泰州网站排名优化软件网站优化的分类天津网站的关键词排名优化桂林网站优化香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

天下网标王 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化