一个简单的员工薪资管理系统(大一\二实训课)

 废话:

今天是10月19号。。抽时间把代码更新了一下,不知为何突发奇想,又添加了了一个薪资状况概览的小功能。

本来想直接用Qt修代码发桌面版的,,奈何Qt才学了两天完全修不了,,只能发普通的控制台版了,,凑活用吧,,Qt的学习进度我会加快的(泪)

 这个小系统主要功能仍然是基础4+2(增删改查,一览,排序),在这之上又添加了格式化系统这个小功能,用处还是有的(比如我自己调代码的时候,,咳咳)。

\

我最引以为豪的仍然是我做的容错系统,虽然仍有不足(比如不好  单独  判断中文的一些符号类似于¥!。,之类的),但大体上仍能规避掉绝绝绝大多数用户奇怪的错误输入,同时给出相应反应。

相较于我的第一个小项目“电话簿”,在这个相对较综合的项目里我在一览上使用了定义有些奇怪的函数指针数组调用相应输出函数,用户能选择要查看的信息类别而不是像以往信息轰炸,,同时我完全使用c++的文件io来读写文件(虽然刚学不是很熟练),小项目整体适应力更甚。

由于在csdn上不知廉耻的问到了std::cout << R"()" ; 的缘故我的代码整体比较长(虽然长不了多少),主要的内存使用可能没有太在意优化(虽然正常电脑绝对够用了)。我的代码主要供大家参考讨论批判,如果能帮上忙那我定十分欣喜,如果帮上倒忙我就,,呃,,你可以评论轰炸我我会改的...(嗯。

\

如果想生成发给别人别人也能用的exe,却不知道怎么办的话,将调试器改为release,然后点一下调试,之后在你的项目文件夹X64中的release文件夹找到exe就可以啦~

如图:

扫描二维码关注公众号,回复: 15368814 查看本文章

 

 

有bug欢迎评论!!极其欢迎!! 

好了废话不多说了,,上代码!

代码 :

/**
 * @author WitMoy
 * @version V11
 * @date : 2022-08-25 16:43
 */
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include <utility>
#include<vector>
#include<set>
#include<map>
#include<fstream>
#include<process.h>
#include <ctime>
#include<windows.h>
 //职位类型结构体
struct pos {
    std::string name;
    std::string val;
    int num;
};

//员工类
class People
{
public:
    typedef struct changedSalary {
        std::string time;
        std::string money;
    }changedSalary;
private:
    std::string name, sex, age, position, serviceLength, number, salary, positionOrder;
    std::vector<changedSalary> cSalary;
public:
    //构造器
    People() = default;
    explicit People(std::string name) {
        setName(std::move(name));
    }
    People(std::string name, std::string number) {
        setName(std::move(name)); setNumber(std::move(number));
    }
    People(std::string name, std::string number, std::string salary) {
        setName(std::move(name)); setNumber(std::move(number)); setSalary(std::move(salary));
    }
    People(std::string name, std::string number, std::string salary, std::string position) {
        setName(std::move(name)); setNumber(std::move(number)); setSalary(std::move(salary)); setPosition(std::move(position));
    }
    //名字
    void setName(std::string newName) {
        this->name = std::move(newName);
    }
    std::string getName() {
        return name;
    }
    //性别
    void setSex(std::string newSex) {
        this->sex = std::move(newSex);
    }
    std::string getSex() {
        return sex;
    }
    //年龄
    void setAge(std::string newAge) {
        this->age = std::move(newAge);
    }
    std::string getAge() {
        return age;
    }
    //职位
    void setPosition(std::string newPosition) {
        this->position = std::move(newPosition);
    }
    std::string getPosition() {
        return position;
    }
    //职位大小顺序
    void setPositionOrder(std::string order) {
        positionOrder = std::move(order);
    }
    std::string getPositionOrder() {
        return positionOrder;
    }
    //工龄
    void setServiceLength(std::string length) {
        serviceLength = std::move(length);
    }
    std::string getServiceLength() {
        return serviceLength;
    }
    //电话
    void setNumber(std::string newNumber) {
        this->number = std::move(newNumber);
    }
    std::string getNumber() {
        return number;
    }
    //薪资
    void setSalary(std::string newSalary) {
        this->salary = std::move(newSalary);
    }
    std::string getSalary() {
        return salary;
    }
    //薪资变化
    void setChangedSalary(const changedSalary& changedSalary) {
        this->cSalary.push_back(changedSalary);
    }
    std::vector<changedSalary> getChangedSalary() {
        return cSalary;
    }
};

//便捷读取
class SafeRead
{
public:
    SafeRead() = default;
    //录入纯数字的非负串(用于读取指令或角标等
    static std::string readNum(int length, const std::string& oldNum) {
        std::string inf;
        //label位置
    label:while (true) {
        std::cout << "\t请输入数字:";
        getline(std::cin, inf);
        if (inf == "\n" || inf.empty()) {
            return oldNum;
        }
        else if ((int)inf.length() > length) {
            std::cout << "\n\t数字长度超过" << length << "位,请重新输入。\n";
            continue;
        }
        for (char check : inf) {
            if (check > '9' || check < '0') {
                std::cout << "\n\t输入的不是一个数字,请重新输入\n";
                //goto位置
                goto label;
            }
        }
        break;
    }
    //删除前导零
    std::string::iterator it = inf.begin();
    for (unsigned int i = 0; i < inf.length() - 1; i++) {//单0不删,一串0只留一个
        if (inf[i] != '0') break;
        inf.erase(it);
        it++;
    }
    return inf;
    }

    //录入有限制的字符串,用于读取基本信息
    static std::string readString(int length, std::string old) {
        std::string inf;
        while (true) {
            getline(std::cin, inf);
            if (inf == "\n" || inf.empty()) {
                return old;
            }
            else if ((int)inf.length() > length) {
                std::cout << "\n\t信息长度超过" << length << ",请重新输入。\n";
                continue;
            }
            break;
        }
        return inf;
    }

    //录入职位
    static std::string* readPosition(std::vector<pos>& positionArr, int positionNumber, const std::string& oldPosition, const std::string& oldPositionOrder) {
        auto* inf = new std::string[2];
        while (true) {
            std::cout << "\t请输入职位:";
            getline(std::cin, inf[0]);
            if (inf[0] == "\n" || inf[0].empty()) {
                inf[0] = oldPosition;
                inf[1] = oldPositionOrder;
                return inf;
            }
            bool flag = false;
            for (int i = 0; i < positionNumber; i++) {
                if (inf[0] == positionArr[i].name) {
                    inf[1] = positionArr[i].val;
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                std::cout << "\n\t没有该职位,请重新输入!\n";
                continue;
            }
            break;
        }
        return inf;
    }

    //录入工资。对前导零的处理在排序区
    static std::string readSalary(int length, const std::string& oldSalary) {
        std::string inf;
        //label位置
    label:while (true) {
        std::cout << "\t请输入金额,单位可以用k(1000)表示或不加:";
        getline(std::cin, inf);
        if (inf == "\n" || inf.empty()) {
            return oldSalary;
        }
        if ((int)inf.length() > length) {
            std::cout << "\n\t输入金额过长,请重新输入\n";
            continue;
        }
        bool unitFlag = false, numberFlag = false;
        for (unsigned int i = 0; i < inf.length(); i++) {
            char check = inf[i];
            //std::string checkY = std::to_string(inf[i]);
            if (!isdigit(check) && check != 'k' && check != 'K' && check != '.' &&
                check != '+' && check != '-' && check != '$')
            {
                std::cout << "\n\t输入金额格式有误,请重新输入。\n";
                goto label;
            }
            if (check == '$' && i != 0) {
                std::cout << "\n\t$符号请放在金额首位\n";
                goto label;
            }
            if (isdigit(check)) {
                numberFlag = true;
            }
            if (!numberFlag && check == '.') {
                std::cout << "\n\t在输入小数点前请先输入数字!\n";
                goto label;
            }
            if (check == 'k' || check == 'K') {
                unitFlag = true;
            }
            if (isdigit(check) && unitFlag) {
                std::cout << "\n\t请将单位放在最后面!\n";
                goto label;
            }
        }
        break;
    }
    return inf;
    }

    //号码录入
    static std::string readNumber(int length, const std::string& oldNumber) {
        std::string inf;
        //label位置
    label:while (true) {
        std::cout << "\t请输入号码,分隔符'-'请用空格替代:";
        getline(std::cin, inf);
        if (inf == "\n" || inf.empty()) {
            return oldNumber;
        }
        if ((int)inf.length() > length) {
            std::cout << "\n\t输入的号码长度超过规定,请重新输入\n";
            continue;
        }
        for (char check : inf) {
            if (check != '+' && !isdigit(check) && check != ' ' && check != '-') {
                std::cout << "\n\t号码格式错误,请重新输入\n";
                goto label;
            }
            if (check == '-') {
                std::cout << "\n\t分隔符'-'请用空格替代!\n";
                goto label;
            }
        }
        break;
    }
    return inf;
    }
};

//string转换为double函数,用来换工资和其改变量

double strToLf(const std::string& number) {
    double lf = 0, lfi = 0, x = 10;
    int i = 0, f = 1, times = 1, length = (int)number.length();
    //录入时限定过单位位置,这里直接访问
    if (number.back() == 'k' || number.back() == 'K') {
        times = 1000;
        length--;
    }
    while (number[i] < '0' || number[i] > '9') {//跳过可能存在的¥,$ 或 -
        i++;
        if (number[i] == '-')
            f *= -1;
    }
    //整数位
    while (i < length) {
        if (number[i] == '.') {
            break;
        }
        lf = lf * 10 + number[i] - '0';
        i++;
    }
    //小数位,++i跳过‘ . ’
    while (++i < length) {
        lfi += (number[i] - '0') / x;
        x *= 10;
    }
    return times * f * (lf + lfi);
}

//qsort用的比较函数,不能写到类里,拿出来写了
int ascendingName(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getName() > t2->getName() ? 1 : -1;
}
int descendingName(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getName() < t2->getName() ? 1 : -1;
}
int ascendingAge(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getAge() > t2->getAge() ? 1 : -1;
}
int descendingAge(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getAge() < t2->getAge() ? 1 : -1;
}
int ascendingPosition(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getPositionOrder() > t2->getPositionOrder() ? 1 : -1;
}
int descendingPosition(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getPositionOrder() < t2->getPositionOrder() ? 1 : -1;
}
int ascendingServiceLength(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getServiceLength() > t2->getServiceLength() ? 1 : -1;
}
int descendingServiceLength(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return t1->getServiceLength() < t2->getServiceLength() ? 1 : -1;
}
int ascendingSalary(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return strToLf(t1->getSalary()) > strToLf(t2->getSalary()) ? 1 : -1;
}
int descendingSalary(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    return strToLf(t1->getSalary()) < strToLf(t2->getSalary()) ? 1 : -1;
}
int ascendingChangedSalary(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    std::vector<People::changedSalary> f1, f2;
    f1 = t1->getChangedSalary();
    f2 = t2->getChangedSalary();
    double v1 = 0, v2 = 0;
    for (auto& i : f1) v1 += strToLf(i.money);
    for (unsigned int i = 0; i < f1.size(); i++) v2 += strToLf(f2[i].money);
    return  v1 / (double)f1.size() > v2 / (double)f2.size() ? 1 : -1;
}
int descendingChangedSalary(const void* a, const void* b) {
    auto* t1 = (People*)a;
    auto* t2 = (People*)b;
    std::vector<People::changedSalary> f1, f2;
    f1 = t1->getChangedSalary();
    f2 = t2->getChangedSalary();
    double v1 = 0, v2 = 0;
    for (auto& i : f1) v1 += strToLf(i.money);
    for (unsigned int i = 0; i < f1.size(); i++) v2 += strToLf(f2[i].money);
    return  v1 / (double)f1.size() < v2 / (double)f2.size() ? 1 : -1;
}

//排序函数
void sorts(std::vector<People>& arr, const std::string& style) {
    if (style == "upName") qsort(&arr[0], arr.size(), sizeof(People), ascendingName);
    else if (style == "downName") qsort(&arr[0], arr.size(), sizeof(People), descendingName);
    else if (style == "upAge") qsort(&arr[0], arr.size(), sizeof(People), ascendingAge);
    else if (style == "downAge") qsort(&arr[0], arr.size(), sizeof(People), descendingAge);
    else if (style == "upSalary") qsort(&arr[0], arr.size(), sizeof(People), ascendingSalary);
    else if (style == "downSalary") qsort(&arr[0], arr.size(), sizeof(People), descendingSalary);
    else if (style == "upChangedSalary") qsort(&arr[0], arr.size(), sizeof(People), ascendingChangedSalary);
    else if (style == "downChangedSalary") qsort(&arr[0], arr.size(), sizeof(People), descendingChangedSalary);
    else if (style == "upPosition") qsort(&arr[0], arr.size(), sizeof(People), ascendingPosition);
    else if (style == "downPosition") qsort(&arr[0], arr.size(), sizeof(People), descendingPosition);
    else if (style == "upServiceLength") qsort(&arr[0], arr.size(), sizeof(People), ascendingServiceLength);
    else qsort(&arr[0], arr.size(), sizeof(People), descendingServiceLength);
}
//人员排序
void userSort(std::vector<People>& arr) {
    std::cout << R"(
    根据姓名排序请输入 1
    根据年龄排序请输入 2
    根据薪资排序请输入 3
    根据平均薪资变化排序请输入 4
    根据工龄排序请输入 5
    根据职位排序请输入 6;

    请输入:)";
    std::string ins = SafeRead::readNum(1, "1");
    std::string style = "bigName";
    std::cout << "\t升序排序请输入 0,降序排序请输入 1:";
    std::string s = SafeRead::readNum(1, "0");
    //排序规则
    if (ins == "1") {
        if (s == "0") { style = "upName"; }
        else { style = "downName"; }
    }
    else if (ins == "2") {
        if (s == "0") { style = "upAge"; }
        else { style = "downAge"; }
    }
    else if (ins == "3") {
        if (s == "0") { style = "upSalary"; }
        else { style = "downSalary"; }
    }
    else if (ins == "4") {
        if (s == "0") { style = "upChangedSalary"; }
        else { style = "downChangedSalary"; }
    }
    else if (ins == "5") {
        if (s == "0") { style = "upServiceLength"; }
        else { style = "downServiceLength"; }
    }
    else {
        if (s == "0") { style = "upPosition"; }
        else { style = "downPosition"; }
    }
    sorts(arr, style);
}

//查看各种信息
class See {
private:
    std::vector<People> arr;//信息来源
    //各类信息的输出函数
    void name(int place) {
        std::cout << "\t姓名:" << arr[place].getName() << '\n';
    }
    void sex(int place) {
        std::cout << "\t性别:" << arr[place].getSex() << '\n';
    }
    void age(int place) {
        std::cout << "\t年龄:" << arr[place].getAge() << '\n';
    }
    void position(int place) {
        std::cout << "\t职位:" << arr[place].getPosition() << '\n';
    }
    void serviceLength(int place) {
        std::cout << "\t工龄:" << arr[place].getServiceLength() << '\n';
    }
    void number(int place) {
        std::cout << "\t电话:" << arr[place].getNumber() << '\n';
    }
    void salary(int place) {
        std::cout << "\t薪资:" << arr[place].getSalary() << '\n';
    }
    void lastChangedSalary(int place) {
        std::vector<People::changedSalary> low = arr[place].getChangedSalary();
        if (low.empty()) {
            std::cout << "\t当前员工薪资暂无变化记录\n";
            return;
        }
        std::cout << "\n\t最近一次变更日期:\t变化金额:\n";
        std::cout << "\t" << low[low.size() - 1].time << "\t" << low[low.size() - 1].money << '\n';
    }
    void allChangedSalary(int place) {
        std::vector<People::changedSalary> low = arr[place].getChangedSalary();
        if (low.empty()) {
            std::cout << "\t当前员工薪资暂无变化记录\n";
            return;
        }
        std::cout << "\t该员工全部薪资变化如下:\n\t变更日期:\t\t变化金额:\n";
        for (auto& i : low) {
            std::cout << "\t" << i.time << "\t" << i.money << "\n";
        }
    }
    //获取公司总薪资情况有序表
    std::pair<std::vector<double>, std::vector<std::pair<double, std::pair<double, int>>>> getPayRollTable() {
        std::vector<double> table;
        for (auto& i : arr) {
            table.push_back(strToLf(i.getSalary()));//获取薪资
        }
        std::sort(table.begin(), table.end());
        std::map<double, std::pair<double, int>>makeMap;
        for (auto& i : table) {
            makeMap[i].first = i;
            makeMap[i].second++;
        }
        std::vector<std::pair<double, std::pair<double, int>>> mapToVec(makeMap.begin(), makeMap.end());
        std::sort(mapToVec.begin(), mapToVec.end(),
            [](std::pair<double, std::pair<double, int>>a, std::pair<double, std::pair<double, int>>b) {
                return a.second.first < b.second.first;//本来想用薪资数量作为柱状图顺序参照,后来感觉不合适,又改了
            });
        std::pair<std::vector<double>, std::vector<std::pair<double, std::pair<double, int>>>> dataSheet;
        dataSheet.first = table;
        dataSheet.second = mapToVec;
        return dataSheet;
    }
public:
    void getArr(std::vector<People> newArr) {
        this->arr = std::move(newArr);
    }
    //打印位置为i的人的一些信息
    static void printType(const std::set<int>& type, std::vector<People>people, int i) {
        /*
        * type中1 - 9分别对应姓名,性别,年龄,职位,工龄,电话,薪资,最近一次薪资变化,记录以来所有薪资变化
        */
        //构建函数指针数组
        typedef void (See::* out)(int);
        out outArr[9] = { &See::name, &See::sex, &See::age, &See::position, &See::serviceLength, &See::number, &See::salary, &See::lastChangedSalary, &See::allChangedSalary };
        See use = See();
        use.getArr(std::move(people));
        //其它的构建方式
        //void (See:: * pFunc[9])(int) = { &See::name, &See::sex, &See::age, &See::position, &See::serviceLength, &See::number, &See::salary, &See::lastChangedSalary, &See::allChangedSalary };
        for (int it : type) {
            (use.*outArr[it - 1])(i);//调用相关函数输出第i位员工信息
        }
    }
    void seeSalarySituation() {
        std::pair<std::vector<double>, std::vector<std::pair<double, std::pair<double, int>>>> sheet = getPayRollTable();
        std::vector<double> table = sheet.first;
        std::vector<std::pair<double, std::pair<double, int>>> data = sheet.second;

        double midNum = 0;//中位数
        if (table.empty()) {
            std::cout << "\n无数据!\n" << std::endl;
            return;
        }
        if (table.size() == 1) {
            std::cout << "仅有一种薪资,值为:" << table[0] << std::endl;
            return;
        }
        else if (table.size() % 2) {
            midNum = (table[table.size() / 2] + table[table.size() / 2 - 1]) / 2;
        }
        else {
            midNum = table[table.size() / 2];
        }

        double mode = data[data.size() - 1].first;//众数
        double modeNum = data[data.size() - 1].second.second;

        //平均数
        double averageNum = 0;
        for (auto& i : table) {
            averageNum += i;
        }
        averageNum /= (double)table.size();

        //最高,最低薪资与最高薪资对于中位薪资的差
        double lagSalary = table[table.size() - 1];
        double smaSalary = table[0];
        double lagSubMid = lagSalary - mode;

        //输出:
        std::cout << "\n\t薪资中位数为:" << midNum
            << "\n\t薪资众数为:" << mode << ", 数量为:" << modeNum
            << "\n\t薪资平均数为:" << averageNum
            << "\n\t最高薪资为:" << lagSalary
            << "\n\t最低薪资为:" << smaSalary
            << "\n\t最高薪资对于中位薪资的差为:" << lagSubMid << '\n' << std::endl;
        std::cout << "\n\t薪资与其相应人员数量柱状图一览:" << '\n';
        for (auto& i : data) {
            std::cout << i.first << ":\t";
            for (int j = 0; j < i.second.second; j++) {
                std::cout << "·";
            }
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
};

class Revise {
private:
    //查找相关信息用函数,返回符合条件的人员信息的角标。
    static std::vector<int> find(std::vector<People> arr, const std::string& inf) {
        std::vector<int>place;
        for (int i = 0; i < arr.size(); i++) {
            std::vector<People::changedSalary> changedSalary = arr[i].getChangedSalary();
            if (arr[i].getAge() == inf || arr[i].getName() == inf ||
                arr[i].getNumber() == inf || arr[i].getPosition() == inf || arr[i].getSalary() == inf ||
                arr[i].getServiceLength() == inf || arr[i].getSex() == inf) {
                place.push_back(i);
            }
            else {
                for (int j = 0; j < changedSalary.size(); j++) {
                    if (changedSalary[i].money == inf) {
                        place.push_back(j);
                    }
                }
            }
        }
        return place;
    }
    //处理有重复信息的人
    static int fixOne(std::vector<People>& arr, const std::string& inf) {
        std::vector<int> place = find(arr, inf);
        if (place.empty()) {
            std::cout << "\t未找到相关联系人\n";
            system("pause");
            return -1;
        }
        int cPlace = place[0];//修改位置
        if (place.size() > 1) {
            std::cout << "\t找到符合要求的联系人共有" << place.size() << "位,具体如下:\n";
            std::set<int> type;
            for (int i = 1; i < 8; i++) {//1-7为姓名-薪资
                type.insert(i);
            }
            for (int i : place) {
                std::cout << "\n";
                See::printType(type, arr, i);
            }
            std::cout << "\t您要选择第几位?不选择将默认为第一位";
            //不超过int范围
            int rank = (int)strToLf(SafeRead::readNum(8, "1")) - 1;
            cPlace = place[rank];
        }
        return cPlace;
    }
public:
    //获取当前系统时间
    static std::string getTime()
    {
        time_t rawtime = time(nullptr);
        //time(&rawtime);
        struct tm* ptminfo = localtime(&rawtime);
        std::string time;
        time = std::to_string(ptminfo->tm_year + 1900) + "-";
        std::string hms;
        hms = std::to_string(ptminfo->tm_mon + 1);
        if (hms.size() == 1) {
            hms = "0" + hms;
        }
        time = time + hms + "-";
        hms = std::to_string(ptminfo->tm_mday);
        if (hms.size() == 1) {
            hms = "0" + hms;
        }
        time = time + hms + " ";
        hms = std::to_string(ptminfo->tm_hour);
        if (hms.size() == 1) {
            hms = "0" + hms;
        }
        time = time + hms + ":";
        hms = std::to_string(ptminfo->tm_min);
        if (hms.size() == 1) {
            hms = "0" + hms;
        }
        time = time + hms + ":";
        hms = std::to_string(ptminfo->tm_sec);
        if (hms.size() == 1) {
            hms = "0" + hms;
        }
        time = time + hms;
        return time;
    }

    //添加职位
    static void addPosition(std::vector<pos>& PO) {
        std::cout << "\n\t请录入增加的职位信息和对应分级,这之间用空格隔开,以便之后使用。\n";
        std::cout << "\t例:总经理 1\n";
        std::cout << "\t输入一个职位及其分级后请按回车确认, 职位名称长度不要超过100\n\n\t请开始输入:\n\n";
        pos low = {};
        std::cin >> low.name;
        getchar();
        low.val = SafeRead::readNum(10, "1");
        PO.push_back(low);
        std::cout << "\n\t添加成功\n";
    }

    //删除职位
    static void deletePosition(std::vector<pos>& PO, const std::string& inf) {
        int place = 0;
        for (auto& i : PO) {
            if (i.name == inf) {
                break;
            }
            place++;
        }
        auto it = PO.begin() + place;
        PO.erase(it);
    }

    //增添员工
    static void addPeople(std::vector<People>& arr, std::vector<pos>& PO, int positionNum) {
        std::cout << "\n\t请填写以下信息,姓名不能为空。不填写的信息请按回车跳过:\n";
        std::string inf;
        SafeRead read = SafeRead();
        People low = People();

        std::cout << "\t姓名:";
        inf = SafeRead::readString(100, "未输入");
        low.setName(inf);

        std::cout << "\t性别:";
        inf = SafeRead::readString(10, "未输入");
        low.setSex(inf);

        std::cout << "\t年龄:";
        inf = SafeRead::readNum(5, "未输入");
        low.setAge(inf);

        std::cout << "\t职位:";
        auto* infs = new std::string[2];
        infs = SafeRead::readPosition(PO, positionNum, "未输入", "未输入");
        //修改职位人数
        if (infs[0] != "未输入") {
            for (auto& i : PO) {
                if (i.name == infs[0]) {
                    i.num++;
                    break;
                }
            }
        }
        //添加职位
        low.setPosition(infs[0]);
        low.setPositionOrder(infs[1]);

        std::cout << "\t工龄:";
        inf = SafeRead::readString(100, "未输入");
        low.setServiceLength(inf);

        std::cout << "\t电话:";
        inf = SafeRead::readNumber(20, "未输入");
        low.setNumber(inf);

        std::cout << "\t薪资:";
        inf = SafeRead::readSalary(20, "未输入");
        low.setSalary(inf);
        //添加
        arr.push_back(low);
        std::cout << "\n\t添加成功\n";
    }

    //修改员工
    static bool changePeople(std::vector<People>& arr, const std::string& inf, std::vector<pos> PO, int positionNum) {
        int cPlace = fixOne(arr, inf);
        if (cPlace == -1) return false;
        while (true) {
            std::cout << "\n\t您是要修改薪资还是要修改其他基础信息?修改薪资请按 1,修改其他信息请按 2:";
            std::string ifCSalary = SafeRead::readNum(1, "1");
            if (ifCSalary == "1") {
                std::cout << "\t该员工当前薪资:" << arr[cPlace].getSalary();
                std::cout << "\n\t请输入修改后的薪资:";
                std::string changedSalary = SafeRead::readSalary(100, arr[cPlace].getSalary());
                double difSalary = strToLf(changedSalary) - strToLf(arr[cPlace].getSalary());//计算新旧薪资差
                arr[cPlace].setSalary(changedSalary);//更新薪资
                //为该员工增添新的薪资变化
                People::changedSalary news = {};
                news.money = std::to_string(difSalary);
                news.time = getTime();
                arr[cPlace].setChangedSalary(news);
            }
            else if (ifCSalary == "2") {
                std::cout << "\n\t请填写要修改的信息,不修改的请直接按回车跳过:\n";
                std::cout << "\t姓名:";
                arr[cPlace].setName(SafeRead::readString(100, arr[cPlace].getName()));
                std::cout << "\t性别:";
                arr[cPlace].setSex(SafeRead::readString(100, arr[cPlace].getSex()));
                std::cout << "\t年龄:";
                arr[cPlace].setAge(SafeRead::readNum(100, arr[cPlace].getAge()));
                std::cout << "\t职位:";
                auto* infs = new std::string[2];
                infs = SafeRead::readPosition(PO, positionNum, arr[cPlace].getPosition(), arr[cPlace].getPositionOrder());
                int flag = 0;
                if (infs[0] != arr[cPlace].getPosition()) {
                    //修改职位人数
                    for (auto& i : PO) {
                        if (i.name == arr[cPlace].getPosition()) {
                            i.num--;
                            flag++;
                        }
                        else if (i.name == infs[0]) {
                            i.num++;
                            flag++;
                        }
                        if (flag == 2) {
                            break;
                        }
                    }
                    //重新设置当前员工职位
                    arr[cPlace].setPosition(infs[0]);
                    arr[cPlace].setPositionOrder(infs[1]);
                }
                std::cout << "\t工龄:";
                arr[cPlace].setServiceLength(SafeRead::readString(100, arr[cPlace].getServiceLength()));
                std::cout << "\t电话:";
                arr[cPlace].setNumber(SafeRead::readNumber(100, arr[cPlace].getNumber()));
            }
            else {
                std::cout << "\t没有该选项,请重新输入\n\n";
                continue;
            }
            break;
        }
        std::cout << "\n\t修改成功\n";
        return true;
    }

    //删除员工
    static bool deletePeople(std::vector<People>& arr, std::vector<pos>& PO, const std::string& inf) {
        int cPlace = fixOne(arr, inf);
        if (cPlace == -1) return false;
        //删除
        for (auto& i : PO) {
            if (i.name == arr[cPlace].getPosition()) {
                i.num--;
                break;
            }
        }
        auto it = arr.begin() + cPlace;
        arr.erase(it);
        std::cout << "\t\n删除完成\n";
        return true;
    }

    //查找员工
    static void findPeople(const std::vector<People>& arr, const std::string& inf) {
        std::vector<int> place = find(arr, inf);
        if (place.empty()) {
            std::cout << "\n\t未找到相关联系人!\n";
            Sleep(2000);
            return;
        }
        See see = See();
        std::cout << "\n\t找到符合要求的联系人共有 " << place.size() << " 位,具体如下:\n";
        std::set<int> type;
        for (int i = 1; i < 8; i++) {//1-7为姓名-薪资
            type.insert(i);
        }
        for (int i : place) {
            std::cout << "\n";
            See::printType(type, arr, i);
        }
    }
};

//文件读写
class File {
public:
    //写文件
    static void save(bool ifFirstUse, const std::vector<pos>& jobType, std::vector<People> people) {
        std::fstream use;

        use.open("ifFirstUse.txt", std::ios::out | std::ios::trunc);
        if (use.is_open()) {
            use << ifFirstUse;
            use.close();
        }

        use.open("peopleNum.txt", std::ios::out | std::ios::trunc);
        if (use.is_open()) {
            use << people.size();
            use.close();
        }

        use.open("jobTypeSize.txt", std::ios::out | std::ios::trunc);
        if (use.is_open()) {
            use << jobType.size();
            use.close();
        }
        //写入职位信息
        use.open("jobType.txt", std::ios::out | std::ios::trunc);
        if (use.is_open()) {
            for (auto& i : jobType) {
                use << i.name << '\n' << i.val << '\n' << i.num << '\n';
            }
            use.close();
        }
        //写入员工信息
        use.open("people.txt", std::ios::out | std::ios::trunc);
        if (use.is_open()) {
            std::vector<People::changedSalary> inf;
            for (auto& i : people) {
                inf = i.getChangedSalary();
                for (auto& j : inf) {
                    use << j.money << '\n' << j.time << '\n';
                }
                use << i.getName() << '\n';
                use << i.getAge() << '\n';
                use << i.getSex() << '\n';
                use << i.getPosition() << '\n';
                use << i.getServiceLength() << '\n';
                use << i.getNumber() << '\n';
                use << i.getSalary() << '\n';
                use << i.getPositionOrder() << '\n';
            }
            use.close();
        }
        //写入每个员工的薪资变更次数
        use.open("changedSalarySize.txt", std::ios::out | std::ios::trunc);
        if (use.is_open()) {
            for (auto& i : people) {
                std::vector<People::changedSalary> inf = i.getChangedSalary();
                use << inf.size() << '\n';
            }
            use.close();
        }

    }

    //读文件
    static void read(bool& ifFirstUse, std::vector<pos>& jobType, std::vector<People>& people) {
        std::fstream use;
        std::string indInf;
        int jobTypeSize = 0, peopleNum = 0;
        //读入使用状态
        use.open("ifFirstUse.txt", std::ios::in);
        if (use.is_open()) {
            //没有使用过的话不再读入信息
            use.peek();
            if (use.eof()) return;

            getline(use, indInf);
            if (indInf == "1") {
                ifFirstUse = true;
            }
            else {
                ifFirstUse = false;
            }
            use.close();
        }
        //没有使用过的话不再读入信息
        else {
            return;
        }
        //录入职位种类数目
        use.open("jobTypeSize.txt", std::ios::in);
        if (use.is_open()) {
            getline(use, indInf);
            jobTypeSize = (int)strToLf(indInf);
            use.close();
        }
        //录入人员数量
        use.open("peopleNum.txt", std::ios::in);
        if (use.is_open()) {
            getline(use, indInf);
            peopleNum = (int)strToLf(indInf);
            use.close();
        }
        //录入职位种类
        use.open("jobType.txt", std::ios::in);
        if (use.is_open()) {
            pos inf = {};
            for (int i = 0; i < jobTypeSize; i++) {
                getline(use, inf.name);
                getline(use, inf.val);
                std::string t;
                getline(use, t);
                inf.num = (int)strToLf(t);
                jobType.push_back(inf);
            }
            use.close();
        }
        //获得每个人员的薪资变更的次数
        std::vector<int>changedSalarySize;
        std::string length;
        use.open("changedSalarySize.txt", std::ios::in);
        if (use.is_open()) {
            while (getline(use, length)) {
                int t = (int)strToLf(length);
                changedSalarySize.push_back(t);
            }
            use.close();
        }
        //录入人员信息
        std::string attribute;
        People::changedSalary inf;
        use.open("people.txt", std::ios::in);
        if (use.is_open()) {
            for (int i = 0; i < peopleNum; i++) {
                People unit = {};
                //读入当前人员过往薪资变化
                for (int j = 0; j < changedSalarySize[i]; j++) {
                    getline(use, inf.money);
                    getline(use, inf.time);
                    unit.setChangedSalary(inf);
                }
                //姓名等基本信息
                getline(use, attribute);
                unit.setName(attribute);

                getline(use, attribute);
                unit.setAge(attribute);

                getline(use, attribute);
                unit.setSex(attribute);

                getline(use, attribute);
                unit.setPosition(attribute);

                getline(use, attribute);
                unit.setServiceLength(attribute);

                getline(use, attribute);
                unit.setNumber(attribute);

                getline(use, attribute);
                unit.setSalary(attribute);

                getline(use, attribute);
                unit.setPositionOrder(attribute);

                people.push_back(unit);
            }
            use.close();
        }

    }
    //格式化系统
    static void formatSystem() {
        std::ofstream use;
        use.open("people.txt", std::ios::trunc);
        if (use.is_open()) use.close();
        std::cout << "\n\t人员信息清空完成...\n";
        use.open("peopleNum.txt", std::ios::trunc);
        if (use.is_open()) use.close();
        std::cout << "\t人数统计清空完成...\n";
        use.open("changedSalarySize.txt", std::ios::trunc);
        if (use.is_open()) use.close();
        std::cout << "\t薪资变更记录清空完成...\n";
        use.open("jobType.txt", std::ios::trunc);
        if (use.is_open()) use.close();
        std::cout << "\t职位信息清空完成...\n";
        use.open("jobTypeSize.txt", std::ios::trunc);
        if (use.is_open()) use.close();
        std::cout << "\t职位统计清空完成...\n";
        std::cout << "\n\t准备更新程序状态...\n";
        use.open("ifFirstUse.txt", std::ios::trunc);
        if (use.is_open()) use.close();
        std::cout << "\n\t格式化完成...\n\n";
    }
};

//界面
class InterFace {
public:
    static void begin() {
        std::cout << R"(

                    O---------------~ 员工薪资管理系统 v 1.0.0 ~---------------O
                    |
                    |  欢迎使用该系统,此版本为初始版本,后续会酌情优化
                    |  功能说明:
                    |  该系统暂时未做可视化,各项功能仅支持指令控制。指令及对
                    |  应的功能如下:
                    |
                    |  指令 “0”:查看或修改现有职位信息
                    |  指令 “1”:添加员工
                    |  指令 “2”:修改员工信息
                    |  指令 “3”:删除员工
                    |  指令 “4”:搜索员工
                    |  指令 “5”:查看员工信息
                    |  指令 “6”:查看员工的薪资概况
                    |  指令 “7”:对员工重新排序
                    |  指令 “8”:退出程序
                    |  指令 “9”:格式化程序
                    |
                    |  如遇任何bug,请QQ提醒:3216347512
                    |  欢迎各路大神指点!
                    |
                    |                                             作者:阿白
                    |                                       2022/9/1 18:51
                    0----------------------------0----------------------------0
        )";
    }
    static void end() {
        std::cout << R"(
                    ************************* 感谢使用 *************************
        )";
    }
};

//main部分
int main()
{
    system("color E1");
    //初始化
    SafeRead read = SafeRead();
    Revise revise = Revise();
    //第一次使用
    bool ifFirstUse = false;//是否第一次使用

    std::vector<pos> jobType;
    std::vector<People>people;//员工数组

    File file = File();

    File::read(ifFirstUse, jobType, people);

    if (!ifFirstUse) {
        std::fstream use;
        use.open("firstTime.txt", std::ios::out);

        //职位信息录入
        std::cout << "\n\t注意:在第一次开始使用前,请录入您公司的职位信息和对应分级,这之间用空格隔开,以便之后使用。\n";
        std::cout << "\t例:总经理 1\n";
        std::cout << "\t每输入一个职位及其分级,请按回车确认, 职位名称长度不要超过100,全部职位输入完成后请输入#后按回车结束\n\n\t请开始输入:\n\n";
        std::string inf;
        pos low = {};
        while (true) {
            //用cin方便跳过空格
            std::cin >> inf;
            if (inf == "#") break;
            low.name = inf;
            std::cin >> inf;
            low.val = inf;
            jobType.push_back(low);
        }
        ifFirstUse = true;
        //吃掉回车
        int* rubbish = new int;
        *rubbish = getchar();
        delete(rubbish);
        std::cout << "\n\t保存中...\n";
        File::save(ifFirstUse, jobType, people);
        std::cout << "\n\t保存完成!\n\n";
        Sleep(1000);
    }

    //功能
    InterFace face = InterFace{};
    while (true) {
        system("cls");
        InterFace::begin();
        std::cout << "\n\t请输入指令:";
        std::string choose = SafeRead::readNum(1, "#");
        if (choose == "#") {
            std::cout << "\n\t您的输入为空,请重新输入\n";
            continue;
        }
        //查看职位或增添、删除职位
        if (choose == "0") {
            std::cout << "查看职位请输入0,增添职位请输入1,删除职位请输入2 :";
            std::string ins = SafeRead::readNum(1, "0");
            if (ins == "0") {
                for (auto& i : jobType) {
                    std::cout << '\n' << i.name << '\n';
                }
                system("pause");
            }
            else if (ins == "1") {
                Revise::addPosition(jobType);
                std::cout << "\n\t保存中...\n";
                File::save(ifFirstUse, jobType, people);
                std::cout << "\n\t保存完成!\n\n";
                Sleep(1000);
            }
            else {
                std::cout << "请输入要删除的职位名称: ";
                std::string posName = SafeRead::readString(100, "");
                Revise::deletePosition(jobType, posName);
                std::cout << "\n\t保存中...\n";
                File::save(ifFirstUse, jobType, people);
                std::cout << "\n\t保存完成!\n\n";
                Sleep(1000);
            }
        }

        //增添员工
        else if (choose == "1") {
            Revise::addPeople(people, jobType, (int)jobType.size());
            std::cout << "\n";
            std::cout << "\n\t保存中...\n";
            File::save(ifFirstUse, jobType, people);
            std::cout << "\n\t保存完成!\n\n";
            Sleep(1000);
        }
        //修改员工信息
        else if (choose == "2") {
            if (people.empty()) {
                std::cout << "\n\t暂无员工信息!\n\n";
                Sleep(2000);
                continue;
            }
            std::cout << "\n\t请输入您要修改的员工的原信息,如姓名等: ";
            //参数:员工数组,要查询的信息,职位数组, 职位数目
            bool flag = Revise::changePeople(people, SafeRead::readString(100, "未输入"), jobType, (int)jobType.size());
            if (flag) {
                std::cout << "\n\t保存中...\n";
                File::save(ifFirstUse, jobType, people);
                std::cout << "\n\t保存完成!\n\n";
                Sleep(1000);
            }
        }
        //删除员工
        else if (choose == "3") {
            if (people.empty()) {
                std::cout << "\n\t暂无员工信息!\n\n";
                Sleep(2000);
                continue;
            }
            std::cout << "一键删除请按 1, 删除单人请按 2:";
            std::string inst = SafeRead::readNum(1, "2");
            if (inst == "1") {
                people.clear();
                std::vector<People>().swap(people);
                std::cout << "\n\t保存中...\n";
                File::save(ifFirstUse, jobType, people);
                std::cout << "\n\t保存完成!\n\n";
                Sleep(1000);
                continue;
            }
            std::cout << "\n\t请输入要删除的人员信息,如姓名,性别,薪资等:";
            bool flag = Revise::deletePeople(people, jobType, SafeRead::readString(100, "未输入"));
            if (flag) {
                std::cout << "\n\t保存中...\n";
                File::save(ifFirstUse, jobType, people);
                std::cout << "\n\t保存完成!\n\n";
                Sleep(1000);
            }

        }
        //搜索员工
        else if (choose == "4") {
            std::string inf;
            std::cout << "\n\t请输入员工相关信息:";
            inf = SafeRead::readString(100, "");
            if (inf.empty()) {
                std::cout << "\n\t未输入任何信息!\n";
                Sleep(2000);
                continue;
            }
            Revise::findPeople(people, inf);
        }
        //查看
        else if (choose == "5") {
            if (people.empty()) {
                std::cout << "\n\t暂无员工信息\n\n";
                Sleep(2000);
                continue;
            }
            std::cout <<
                R"(
    请选择您要查看的员工信息类别(可多选),每选完一个选项按回车确定:
    查看姓名请输入 1
    查看性别请输入 2
    查看年龄请输入 3
    查看职位请输入 4
    查看工龄请输入 5
    查看电话请输入 6
    查看薪资请输入 7
    查看最近一次薪资变化请输入 8
    查看记录以来所有薪资变化请输入 9

    结束输入请输入 0

)";
            std::set<int> type;//用set防止重复输入
            std::string num;
            while (num = SafeRead::readNum(1, "1"), num != "0") {
                int number = (int)strToLf(num);//转换为int,方便后面找位置
                type.insert(number);
            }
            std::cout << "\n";
            for (int i = 0; i < people.size(); i++) {
                See::printType(type, people, i);
                std::cout << "\n";
            }
            system("pause");
        }
        //查看员工的薪资概况
        else if (choose == "6") {
            std::cout << "\n\t整理所有员工薪资概况如下:" << std::endl;
            See see = See();
            see.getArr(people);
            see.seeSalarySituation();
            system("pause");
        }
        //排序
        else if (choose == "7") {
            userSort(people);
            std::cout << "\n\t保存中...\n";
            File::save(ifFirstUse, jobType, people);
            std::cout << "\n\t保存完成!\n\n";
            Sleep(1000);
        }
        //退出程序
        else if (choose == "8") {
            File::save(ifFirstUse, jobType, people);
            InterFace::end();
            return 0;
        }
        else if (choose == "9") {
            std::cout << "确定要格式化程序吗? Y(是)/N(否), 输入其它将默认不格式化:";
            std::string clear = SafeRead::readString(1, "N");
            if (clear == "y" || clear == "Y" || clear == "是") {
                File::formatSystem();
                Sleep(2000);
                return 0;
            }
        }
        else {
            std::cout << "\n\t没有该选项!\n";
            Sleep(2000);
        }
    }
}

整体大致就这么多了,,由于还在放假没有拿到实训书(据说我们第四周才开始实训),相关的实训心得和程序逻辑图都没有弄(主要是不知道这次要求是啥),大家有需要的话自己弄吧~我实训书写好后应该会更新的..

最后,还是要求个赞后者收藏..(嗯

感谢观看!!

猜你喜欢

转载自blog.csdn.net/bairimeng16/article/details/126755985