<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 项目:职工管理系统/
作者
Melody
发布于
2022年4月27日
许可协议