<C++>9 项目:职工管理系统
本文最后更新于:2022年5月24日 早上
9 项目:职工管理系统
9.1 业务需求
公司中员工分 3 类:普通员工、经理、老板
员工信息包含:职工编号、职工姓名、职工岗位、职责
- 普通员工职责:完成经理交代的任务
- 经理职责:完成老板交代的任务,下发任务给员工
- 老板职责:管理公司所有事物
管理系统实现功能包括:
- 退出管理程序
- 增加职工信息
- 批量添加职工
- 将职工信息导出至文件
- 显示所有职工信息
- 删除离职职工:按照编号
- 修改职工信息:按照编号
- 查找职工信息:按照编号
- 按照编号排序:按照编号,用户能指定排序规则
- 清空所有文档:二次确认
附录
职工管理系统
包含头文件后,执行:
menu0();
头文件:
MenuHead.h:菜单及菜单功能。
#pragma once //由于头文件可能被重复包含,必须加上这句,避免重定义
#include<iostream>
using namespace std;
#include<string>
#include "myHead.h"
void showMenu0(); //显示菜单。只是输出文字而已
void menu0(); //菜单的主方法。调用该方法进入管理系统
void showAll(); //显示所有员工信息
void check(); //查询员工
void add(); //添加员工
void change(); //改变员工信息
void del(); //删除员工
void sort(); //排序
void clear(); //清空文档
bool exit(); //退出
myHead.h:几种员工类,及一个数据处理类。
#pragma once
#include<iostream>
using namespace std;
#include<Windows.h>
#include<string>
class Employee { //普通员工类。该类是其余 2 种员工类的父类
public:
static int count; //count 属性是一个计数器。该值等于新员工的 ID 数
int id; //id 即 ID
string name; //姓名
string duty; //职责
string pos; //职位
Employee(string name); //构造器
Employee(); //无参构造器,因为一些原因不使用
};
class Boss :public Employee { //老板类,该类是员工类的子类
public:
Boss(string name);
};
class Manager :public Employee { //经理类。该类是员工类的子类
public:
Manager(string name);
};
class Data { //数据处理类。该类能实现菜单功能
public:
string path; //输出文件的路径
string temp_path; //临时路径
static bool add(Employee* e); //添加一个新员工
static void showAll(); //打印全部员工信息
static bool check(int id); //打印单个员工信息
static void change(Employee* e);//修改单个员工信息
static bool del(int id); //删除单个员工信息
static void sort(int func); //员工信息排序
static void clear(); //初始化员工信息
static void rollback(); //恢复数据
private:
static void flush(); //更新员工信息文档。只要进行过任何信息修改,必定调用该方法
static void showSingle(Employee* e);
//打印特定员工信息。所有打印信息方法必定调用该方法
void put(Employee* e); //添加新员工
static Data data; //持有一个信息类实例
Employee** es; //信息类实例包含的信息数组
bool desc; //信息类实例展示信息时按照升序或降序排列
int len; //信息类实例的数组长度
Data(); //构造器
void read(string ps); //从指定文件中读取数据
};
源文件:
Employee.cpp:3 个员工类
#include<iostream>
using namespace std;
#include<string>
#include "myHead.h"
Employee::Employee(string name) { //员工类构造器
this->id = count++; //count 是 Employee 类的静态变量。这样保证每个员工 ID 独一无二
this->name = name;
this->pos = "员工";
duty = "完成经理交代的任务";
}
Employee::Employee(){
}
Boss::Boss(string name) { //老板类构造器
this->id = count++;
this->name = name;
this->pos = "老板";
duty = "管理公司所有事物";
}
Manager::Manager(string name) { //经理类构造器
this->id = count++;
this->name = name;
this->pos = "经理";
duty = "完成老板交代的任务,下发任务给员工";
}
Menu.cpp:菜单类
接收用户指令,并对数据进行初步处理,最终移交给 Data 类执行
#include<iostream>
using namespace std;
#include<string>
#include "myHead.h"
#include "MenuHead.h"
void showMenu0() { //展示菜单
cout << "—————————欢迎使用职工管理系统—————————" << endl;
cout << "\t\t\t1 显示所有职工信息" << endl;
cout << "\t\t\t2 查找职工信息" << endl;
cout << "\t\t\t3 增加职工信息" << endl;
cout << "\t\t\t4 修改职工信息" << endl;
cout << "\t\t\t5 删除职工" << endl;
cout << "\t\t\t6 员工排序" << endl;
cout << "\t\t\t7 清空员工信息文档" << endl;
cout << "\t\t\t9 退出职工管理系统" << endl;
cout << "————————————————————————————" << endl;
}
void menu0() { //想进入系统就调用该方法把
bool run = true; //确定退出系统前,该值为 true
bool skipMenu = false; //跳过菜单。该值没有投入使用
while (run) {
if (!skipMenu) showMenu0(); //展示菜单
skipMenu = false;
cout << "请选择:"; //用户选择
string in = "";
cin >> in;
switch (in[0]) { //进入分支
case '1':
showAll();
break;
case '2':
check();
break;
case '3':
add();
break;
case '4':
change();
break;
case '5':
del();
break;
case '6':
sort();
break;
case '7':
clear();
break;
case '9':
if (exit()) {
cout << "再见" << endl;
return;
}
break;
default:
cout << "输入错误,请重新输入" << endl;
skipMenu = true;
break;
}
system("pause");
system("cls");
}
cout << "职工管理系统已停止" << endl;
}
void showAll() { //展示全部员工信息。
cout << "————————————————————————————" << endl;
Data::showAll();
cout << endl;
}
void check() { //展示某个员工的信息
cout << "————————————————————————————" << endl;
cout << "请输入想查询的员工编号:";
int id = -1;
cin >> id;
if (!Data::check(id)) { //Data::check(int) 会打印信息。没有该员工,则返回 false
return; //多此一举了是吧
}
}
void add() { //添加员工
cout << "————————————————————————————" << endl;
cout << "请输入员工姓名:";
string name;
cin >> name;
cout << "请选择员工职务(1员工/2经理/3老板):";
string duty;
cin >> duty;
Employee* e;
if (duty[0] == '1') { //是,也能 switch,但我偏不
e = new Employee(name);
}
else if (duty[0] == '2') {
e = new Manager(name);
}
else if (duty[0] == '3') {
e = new Boss(name);
}
else {
cout << "输入错误" << endl;
return;
}
Data::add(e);
cout << "添加成功" << endl;
}
void change() { //修改员工信息
cout << "————————————————————————————" << endl;
cout << "请输入想修改的员工编号:";
int id = -1;
cin >> id;
cout << "— — — — — — — — — — — — — —" << endl;
if (!Data::check(id)) {
return;
}
cout << "请输入修改后的员工名字:";
string name;
cin >> name;
cout << "请输入修改后的员工职务(1员工/2经理/3老板):";
string duty;
cin >> duty;
Employee* e;
if (duty[0] == '1') {
e = new Employee(name);
}
else if (duty[0] == '2') {
e = new Manager(name);
}
else if (duty[0] == '3') {
e = new Boss(name);
}
else {
cout << "输入错误" << endl;
return;
}
e->id = id;
Employee::count--; //因为只是修改员工信息,不需要 count 变化。故而把自增过的该值减小
Data::change(e);
cout << "添加成功" << endl;
}
void del() { //删除员工信息
showAll();
cout << "————————————————————————————" << endl;
cout << "请输入要删除的员工号:";
int id;
cin >> id;
cout << endl;
if (!Data::check(id)) {
return;
}
cout << "此操作不能撤销,确认要删除吗(确认请输入:YES):";
string emp;
cin >> emp;
if (emp == "YES") cout << (Data::del(id) ? "成功" : "失败") << endl;
else cout << "取消" << endl;
}
void sort() { //排序。其实根本没排序
cout << "————————————————————————————" << endl;
int desc;
cout << "请输入排序方式(1升序/2降序):";
cin >> desc;
Data::sort(desc == 2 ? 2 : 1);
}
void clear() { //清空。其实根本没清空
cout << "————————————————————————————" << endl;
cout << "即将清空员工信息文档" << endl;
cout << "该操作不可恢复,请确认(确认请输入:YES):";
string in;
cin >> in;
if (in == "YES") {
Data::clear();
cout << "员工文档已清空" << endl;
}
else if (in == "ROLLBACK") { //这是一条隐藏的恢复数据指令
Data::rollback();
}
else cout << "取消" << endl;
}
bool exit() { //退出
cout << "————————————————————————————" << endl;
cout << "即将退出操作系统,确定吗(Y/N):";
string exit;
cin >> exit;
return exit == "y" || exit == "Y";
}
Data.cpp:数据处理类
从 Menu 类处获得处理过的数据,并最终完成对数据的处理
#include<iostream>
using namespace std;
#include<fstream>
#include<string>
#include "myHead.h"
bool Data::add(Employee* e) { //添加指定员工对象
data.put(e); //向数据数组内添加员工对象
flush(); //向信息文件内写入新数据
return true;
}
void Data::showAll() { //展示全部员工信息
flush();
if (data.desc) { //按照设置的升序、降序进行输出
for (int n = data.len - 1; n >= 0; n--) {
if (data.es[n] != NULL) showSingle(data.es[n]);
}
}
else {
for (int n = 0; n < data.len; n++) {
if (data.es[n] != NULL) showSingle(data.es[n]);
}
}
}
bool Data::check(int id) { //按 ID 展示对象信息
if (id <= data.len && data.es[id] != NULL) {
showSingle(data.es[id]);
return true;
}
else {
cout << "查无此人" << endl;
return false;
}
}
void Data::change(Employee* e) { //修改对象信息
if (e->id <= data.len) {
delete data.es[e->id];
data.es[e->id] = NULL;
data.es[e->id] = e;
}
else data.put(e);
flush(); //重写信息文件
}
bool Data::del(int id) { //删除对象信息
if (id <= data.len) {
delete data.es[id];
data.es[id] = NULL;
flush();
return true;
}
else return false;
}
void Data::sort(int func) { //修改排序方法。其实只是修改了一个值
if (data.desc == (func == 2)) return;
data.desc = (func == 2);
flush();
}
void Data::clear() { //初始化数据。信息文件会作为副本得以保留
srand(time(0));
string temp = data.path + to_string(rand());//将原本的信息文件名加上了后缀
remove(temp.c_str());
rename(data.path.c_str(), temp.c_str()); //原本的信息文件改名后放在一边
for (int n = 0; n < data.len; n++) {
if (data.es[n] != NULL) delete data.es[n];
data.es[n] = NULL;
}
delete data.es;
data.len = 5;
data.es = new Employee * [data.len];
Employee::count = 0;
}
void Data::rollback() {
clear();
data.read(data.temp_path);
}
void Data::flush() { //写入信息文件。根据排序方法不同写入方式不同
ofstream ofs(data.path, ios::out | ios::trunc);
if (!data.desc) {
for (int n = 0; n < data.len; n++) {
if (data.es[n] != NULL) ofs << "ID:" << (data.es[n])->id << "\t姓名:" << data.es[n]->name << "\t职务:" << data.es[n]->pos << "\t职责:" << data.es[n]->duty << endl;
}
}
else {
for (int n = data.len - 1; n >= 0; n--) {
if (data.es[n] != NULL) ofs << "ID:" << data.es[n]->id << "\t姓名:" << data.es[n]->name << "\t职务:" << data.es[n]->pos << "\t职责:" << data.es[n]->duty << endl;
}
}
ofs.close();
}
Data::Data() { //构造器。会且只会调用一次
path = "d:\\练习\\data.data";
temp_path = "d:\\练习\\data.datat";
desc = false;
len = 5;
es = new Employee * [len]{NULL};
Employee::count = 0;
read();
}
void Data::showSingle(Employee* e) { //展示某员工对象信息
if (e == NULL) return;
cout << "ID:" << e->id << "\t姓名:" << e->name << "\t职务:" << e->pos << "\t职责:" << e->duty << endl;
}
void Data::put(Employee* e) { //将对象放入数据数组
if (e->id >= len) { //如果数组空间不够,会先扩容
int temp = len;
len = e->id + 5;
Employee** et = new Employee * [len];
for (int n = 0; n < temp; n++) {
et[n] = this->es[n];
}
delete[] es;
es = NULL;
es = et;
}
es[e->id] = e;
}
void Data::read() { //从已有文档读取信息
ifstream ifs(path, ios::in);
if (!ifs.is_open()) {
ifs.close();
return;
}
int max = 0;
int id;
string name;
string pos;
string dump;
while (ifs >> id && ifs >> name && ifs >> pos && ifs >> dump) {
Employee* e;
if (pos == "老板") e = new Boss(name);
else if (pos == "经理") e = new Manager(name);
else e = new Employee(name);
e->id = id;
Employee::count--;
if (max <= id) max = id + 1;
put(e);
}
ifs.close();
Employee::count = max;
}
int Employee::count = 0; //静态变量类外初始化
Data Data::data = Data(); //静态变量类外初始化
<C++>9 项目:职工管理系统
https://i-melody.github.io/2022/04/27/C++/入门阶段/9 项目:职工管理系统/