C++ 基于文件实现职工管理系统

主要技术点,
1、使用std::vector<std::shared_ptr<Worker>> 管理对象,vector.clear后,shared_ptr包含的基类对象会自动释放内存
2、使用多态实现不同的员工
程序代码如下,
main.cpp

#include "utils/work_manager.h"
#include "utils/boss.h"
#include "utils/employee.h"
#include "utils/manager.h"
using std::cin;
#include <cstdlib>

int main(int argc, char* argv[]) {
    
    WorkManager wm;

    int choice = 0;

    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:
            // 默认清屏
            wm.clearScreen();
            break;
        }
    }

    wm.pause();
    return 0;
}

utils/worker.h

#ifndef _WORKER_H_
#define _WORKER_H_

#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::endl;

class Worker {
    public:
        virtual ~Worker() {}
        // 显示个人信息
        virtual void showInfo() = 0;
        // 获取岗位名称
        virtual string getDeptName() = 0;

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

utils/employee.h

#ifndef _EMPLOYEE_H_
#define _EMPLOYEE_H_

#include "worker.h"

class Employee: public Worker {
    public:
        Employee(int id, string name, int dId);
        virtual void showInfo();
        virtual string getDeptName();

};
#endif

utils/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 "员工";
}

utils/manager.h

#ifndef _MANAGER_H_
#define _MANAGER_H_

#include "worker.h"

class Manager: public Worker {
    public:
        Manager(int id, string name, int dId);
        virtual void showInfo();
        virtual string getDeptName();

};

#endif

utils/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 "经理";
}

utils/boss.h

#ifndef _BOSS_H_
#define _BOSS_H_

#include "worker.h"

class Boss: public Worker {
    public:
        Boss(int id, string name, int dId);
        virtual void showInfo();
        virtual string getDeptName();

};

#endif

utils/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 "总裁";
}

utils/consts.h

#ifndef _CONSTS_H_
#define _CONSTS_H_

#ifndef WINDOWS
#define WINDOWS
#endif

#define FILE_NAME "empFile.txt"


#include <memory>

// 初始化特定类型文件指针的宏, stream_type是流类型,f是流变量
#define INIT_FILE_PTR(stream_type, f)  std::shared_ptr<stream_type> f(new stream_type, [](stream_type* f){ \
        f->close(); \
        delete f; \
        f = nullptr; \
    })


#endif

work_manager.h

#ifndef _WORK_MANAGER_H_
#define _WORK_MANAGER_H_

#include <iostream>
using std::cout;
using std::endl;
#include "consts.h"
#include <string>
using std::string;
#include <cstdlib>
#include <memory>
#include "employee.h"
#include "manager.h"
#include "boss.h"
#include <vector>
using std::cin;
#include <fstream>
using std::ofstream;
using std::ifstream;
#include <algorithm>

using WorkerPtr = std::shared_ptr<Worker>;
using WorkArr = std::vector<WorkerPtr>;

class WorkManager {
    public:
        WorkManager();
        ~WorkManager();
        // 显示菜单功能实现
        void showMenu();
        // 退出系统
        void exitSystem();

        // 添加职工功能
        void Add_Emp();

        // 存文件
        void save();

        // 获取员工数量
        int get_EmpNum();

        // 初始化员工信息
        void init_Emp();

        // 显示员工信息功能
        void show_Emp();

        // 删除员工信息
        void Del_Emp();

        // 修改员工信息
        void Mod_Emp();

        // 查找职工信息
        void Find_Emp();

        // 排序职工信息
        void Sort_Emp();

        // 清空所有员工信息
        void Clean_File();

        WorkArr::iterator isExist(int id);

        // 清空屏幕
        void clearScreen();
        // 暂停屏幕,请按任意键继续
        void pause();

    private:
        // 标志文件是否为空
        bool m_FileIsEmpty;
        WorkArr m_EmpArray;
        int m_EmpNum;
};
#endif

work_manager.cpp

#include "work_manager.h"


WorkManager::WorkManager() {
    // 清空原有数据
    this->m_EmpArray.clear();

    INIT_FILE_PTR(ifstream, ifs);
    ifs->open(FILE_NAME, std::ios::in);

    if(!ifs->is_open()) {
        cout << "文件不存在" << endl;
        this->m_FileIsEmpty = true;
        this->m_EmpArray.clear();
        return;
    }

    char ch;
    *ifs >> ch;
    if(ifs->eof()) {
        cout << "文件为空!" << endl;
        this->m_FileIsEmpty = true;
        this->m_EmpArray.clear();
        return;
    }

    // 获取员工个数
    this->m_EmpNum = this->get_EmpNum();  // 更新成员属性
    
    // 预分配大小
    this->m_EmpArray.resize(this->m_EmpNum);
    
    // 初始化容器
    this->init_Emp();
}

WorkManager::~WorkManager() {
     // 释放vector内存
    this->m_EmpArray.clear();
}


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

void WorkManager::Add_Emp() {
    cout << "请输入增加的职工数量: " << endl;
    int addNum = 0;
    cin >> addNum;

    // 处理错误的输入
    if(addNum <= 0) {
        cout << "输入有误" << endl;
        this->pause();
        this->clearScreen();
        return;
    }

    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;

        WorkerPtr worker;
        switch (dSelect)
        {
        case 1: // 普通员工
            worker = WorkerPtr(new Employee(id, name, 1));
            break;
        case 2: // 经理
            worker = WorkerPtr(new Manager(id, name, 2));
            break;
        case 3: // 老板
            worker = WorkerPtr(new Boss(id, name, 3));
            break;
        default:
            break;
        }

        m_EmpArray.emplace_back(worker);
    }

    cout << "成功添加 " << addNum << " 名新职工!" << endl;
    this->m_EmpNum += addNum;
    // 保存到文件
    this->save();
    this->m_FileIsEmpty = false;
    this->pause();
    this->clearScreen();
}

void WorkManager::init_Emp() {
    INIT_FILE_PTR(ifstream, ifs);

    ifs->open(FILE_NAME, std::ios::in);

    int id;
    string name;
    int dId;

    int index = 0;

    while(*ifs >> id && *ifs >> name && *ifs >> dId) {
        WorkerPtr worker;
        if(dId == 1) {
            worker = WorkerPtr(new Employee(id, name, dId));
        } else if(dId == 2) {
            worker = WorkerPtr(new Manager(id, name, dId));
        } else {
            worker = WorkerPtr(new Boss(id, name, dId));
        } 
        this->m_EmpArray[index] = worker;
        ++index;
    }
}


void WorkManager::show_Emp() {
    if(this->m_FileIsEmpty) {
        cout << "文件不存在或记录为空" << endl;
    }else {
        for(WorkArr::iterator b = m_EmpArray.begin(), e = m_EmpArray.end(); b != e; ++b) {
            (*b)->showInfo();
        }  
    }
    this->pause();
    this->clearScreen();
}

void WorkManager::Del_Emp() {
    if(this->m_FileIsEmpty) {
        cout << "文件不存在或记录为空" << endl;
    } else {
        cout << "请输入想要删除的职工号: " << endl;
        int id = 0;
        cin >> id;
        auto findIt = this->isExist(id);

        // 找到了
        if(findIt != m_EmpArray.end()) {
            m_EmpArray.erase(findIt);
            this->m_EmpNum --;
            this->save();
            cout << "删除成功 " << endl;    
        }else {
            cout << "删除失败,未找到该员工" << endl; 
        }
    }

    this->pause();
    this->clearScreen();
}

void WorkManager::Mod_Emp() {
    if(this->m_FileIsEmpty) {
        cout << "文件不存在或记录为空!" << endl;
    } else {
        cout << "请输入要修改的职工编号: " << endl;
        int id;
        cin >> id;
        auto findIt = this->isExist(id);
        if(findIt != m_EmpArray.end()) {
            // 清空原有shared_ptr数据
            WorkerPtr& oldWorker = *findIt;
            oldWorker.reset();
            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;

            switch (dSelect)
            {
            case 1:
                oldWorker = WorkerPtr(new Employee(newId, newName, dSelect));
                break;
            case 2:
                oldWorker = WorkerPtr(new Manager(newId, newName, dSelect));
                break;
            case 3:
                oldWorker = WorkerPtr(new Boss(newId, newName, dSelect));
                break;
            default:
                break;
            }

            cout << "修改成功!" << oldWorker->m_Id << endl;
            this->save();
        } else {
            cout << "修改失败,查无此人" << endl;
        }
    }

    this->pause();
    this->clearScreen();
}

void WorkManager::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;

            auto findIt = isExist(id);
            // 找到了
            if(findIt != m_EmpArray.end()) {
                cout << "查找成功!该职工信息如下: " << endl;
                (*findIt)->showInfo();
            }else {
                cout << "查找失败,查无此人" << endl;
            }
        }else if(select == 2) {  //按姓名查找
            string name;
            cout << "请输入要查找的姓名: " << endl;
            cin >> name;

            bool flag = false;
            for(auto b = m_EmpArray.begin(), e = m_EmpArray.end(); b != e; ++b) {
                if((*b)->m_Name == name) {
                    flag = true;
                    cout << "查找成功,职工编号为: "
                        << (*b)->m_Id 
                        << " 号的信息如下: " << endl;
                    (*b)->showInfo();
                    break;    
                }
            }

            if(flag == false) {
                cout << "查找失败,查无此人" << endl;
            }
        }else {
            cout << "输入选项有误" << endl;
        }
    }

    this->pause();
    this->clearScreen();
}

void WorkManager::Sort_Emp() {
    if(this->m_FileIsEmpty) {
        cout << "文件不存在或记录为空" << endl;
        this->pause();
        this->clearScreen();
        return;
    } 

    cout << "请选择排序方式: " << endl;
    cout << "1、按职工号进行升序" << endl;
    cout << "2、按职工号进行降序" << endl;

    int select = 0;
    cin >> select;

    int size = m_EmpArray.size();
    for(int i = 0; i<size; ++i) {
        int minOrMax = i;

        for(int j=i+1; j<size; ++j) {
            if(select == 1) { // 升序寻找最小值
                if(m_EmpArray[minOrMax]->m_Id > m_EmpArray[j]->m_Id) {
                    minOrMax = j;
                }
            } else { // 降序寻找最大值
                if(m_EmpArray[minOrMax]->m_Id < m_EmpArray[j]->m_Id) {
                    minOrMax = j;
                }
            }
        }

        if(i != minOrMax) {
            WorkerPtr tmp = m_EmpArray[i];
            m_EmpArray[i] = m_EmpArray[minOrMax];
            m_EmpArray[minOrMax] = tmp;
        }
    }

    cout << "排序成功,排序后结果为: " << endl;
    this->save();
    this->show_Emp();
}

void WorkManager::Clean_File() {
    cout << "确认清空?" << endl;
    cout << "1、确认" << endl;
    cout << "2、返回" << endl;

    int select = 0;
    cin >> select;

    if(select == 1) {
        INIT_FILE_PTR(ofstream, ofs);
        ofs->open(FILE_NAME, std::ios::trunc);
        this->m_EmpArray.clear();
        m_EmpNum = 0;
        m_FileIsEmpty = true;
        cout << "清空成功!" << endl;
    }    

    this->pause();
    this->clearScreen();
}

WorkArr::iterator WorkManager::isExist(int id) {
    for(auto b = m_EmpArray.begin(), e = m_EmpArray.end(); b != e; ++b) {
        if((*b)->m_Id == id) {
            return b;
        }
    }
    return m_EmpArray.end();
}

void WorkManager::save() {
    INIT_FILE_PTR(ofstream, ofs);
    ofs->open(FILE_NAME, std::ios::out);
    for(int i=0; i<this->m_EmpArray.size(); i++) {
        *ofs << this->m_EmpArray[i]->m_Id << " "
            << this->m_EmpArray[i]->m_Name << " "
            << this->m_EmpArray[i]->m_DeptId << endl;
    }
}

int WorkManager::get_EmpNum() {
    INIT_FILE_PTR(ifstream, ifs);
    ifs->open(FILE_NAME, std::ios::in);

    int id;
    string name;
    int dId;

    int num = 0;
    while(*ifs >> id && *ifs >> name && *ifs >> dId) {
        // 记录人数
        num ++;
    }
    return num;
}

void WorkManager::clearScreen() {
    string clearStr = "clear";
#ifdef WINDOWS
    clearStr = "cls";
#endif
    system(clearStr.c_str());
}

void WorkManager::pause() {
    cout << "请按任意键继续..." << endl;
    getchar();
    getchar();
}

void WorkManager::exitSystem() {
    cout << "欢迎下次使用" << endl;
    this->pause();
    exit(0);
}

Makefile

TAR=main
WORKSPACE_DIR=.
CC:=g++

.PHONY: build clear all

build:
    $(CC) $(WORKSPACE_DIR)/utils/* $(WORKSPACE_DIR)/*.*pp -g -o $(TAR)

all: clear build

clear:
    rm -rf $(TAR)

程序输出如下
显示职工信息


图片.png

修改职工信息


图片.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,176评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,928评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 171,252评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,700评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,717评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,231评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,608评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,572评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,117评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,137评论 3 344
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,280评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,908评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,597评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,067评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,202评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,784评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,308评论 2 365

推荐阅读更多精彩内容