C++职工管理系统

目录

 

一、头文件信息框架构建

一、程序目的

二、对类的构建

二、程序执行流程的设计

三、各函数模块的实现

一、职工类的类中函数实现

一、构造函数

二、展示函数

 三、取得职位名的函数

二、管理类的类中函数实现

一、构造函数

二、取得文件职工数量的函数

三、初始化函数

四、菜单函数

 五、职工添加函数

六、ID检查函数

七、保存函数

八、职工删除函数

 九、下标查找函数与姓名查找函数

十、职工修改函数

十一、查找职工

十二、职工排序

十三、职工信息清除

十四、析构函数

四、总结


一、头文件信息框架构建

一、程序目的

实现对职工信息的增删改查,以及文件写入读取的交互,基于B黑马程序员所授职工管理系统的进一步扩展。

二、对类的构建

首先构造一个职工类,类中成员为对职工姓名,序号,电话...之类的属性,其次对不同的职工分别派生出老板,经理,员工这三个子类,用于重写基类中的虚函数,实现各自不同的功能。

#pragma once
#define FILENAME "职工信息.mxy"//定义文件名宏常量,便于修改
#include<iostream>
#include<fstream>
#include<string>
#include<algorithm>//快速排序所需头文件
using namespace std;

class Staff
{
public:
	virtual void ShowInfo() = 0;//显示信息的虚构函数
	virtual string GetWork() = 0;//获取职工职位的虚函数
	int m_id;//职工编号
	string m_tel;//电话
	int m_salary;//薪水
	string m_name;//名字
	string m_sex;//性别
	int m_type;//这里使用编号代表不同职位
};

class Boss :public Staff
{
public:
	Boss(int id, string name, string sex, string tel, int type, int salary);//子了构造函数,创建对象并赋值
	void ShowInfo();//对虚函数的重新声明
	string GetWork();
};

class Manager :public Staff
{
public:
	Manager(int id, string name, string sex, string tel, int type, int salary);
	void ShowInfo();
	string GetWork();
};

class Employee :public Staff
{
public:
	Employee(int id, string name, string sex, string tel, int type, int salary);
	void ShowInfo();
	string GetWork();
};

 这只是搭建了基本框架,我将函数实现写在一个单独的源文件中,便于理解。

在职工的类构建好之后,需要对职工信息的管理构建一个管理类。

class StaffManagement
{
public:
	StaffManagement();//构造函数,初始化存储空间
	void Menu();//菜单
	void Exit();//退出
	bool CheckId(int n);//检查职工编号是否重复
	void AddEmployee();//添加员工
	void Save();//保存
	bool CheckFile;//表明文件状态,文件不存在或信息为空为真,反之为假
	int GetFileSize();//若需载入,取得职工个数
	void InitFile();//初始化文件,将文件信息读取到内存
	void ShowEmployee();//显示所有职工信息
	int GetRank(int n);//取得职工的当前排序数
	void NameSearch(string name);//姓名查找
	void DeleteEmployee();//删除职工
	void ModifyEmployee();//修改职工
	void SearchEmployee();//查找职工并显示信息
	void SortEmployee();//对职工进行排序
	void DestoryedInfo();//清除所有文件信息
	int P_n;//计数器
	Staff**P_arr;//指向职工数据内存的二级指针
	~StaffManagement();//析构函数,释放内存
};

管理类提供各种函数用以实现各种操作,在此做了个枚举常量,用于对应switch选择,便于后期更改,更新。

enum
{
	EXIT,
	ADD,
	DISPLAY,
	DELETE,
	MODIFY,
	SEARCH,
	SAVE,
	SORT,
	DESTORY
};

以上文件均被作为一个头文件,分文件操作对代码阅读,后续修改,扩展都有好处。

二、程序执行流程的设计

这块比较简单,你可以将操作结束后对屏幕的刷新放在各功能函数末尾(这里采用放在末尾)。也可以放在switch选择函数中。

#include"StaffManagement.h"//引用头文件

void operate()
{
	StaffManagement sm;//实例化对象
	sm.Menu();//调用菜单
	int choice;
//do while()是这类选择进入型流程常用的手段,为直到型循环。
	do
	{
		cout << "请选择:" << endl;
		cin >> choice;//输入选择
		switch (choice)//根据选项值,进入不同函数模块
		{
		case EXIT:
			sm.Exit();
			break;
		case ADD:
			sm.AddEmployee();
			break;
		case DISPLAY:
			sm.ShowEmployee();
			break;
		case DELETE:
			sm.DeleteEmployee();
			break;
		case MODIFY:
			sm.ModifyEmployee();
			break;
		case SEARCH:
			sm.SearchEmployee();
			break;
		case SAVE:
			sm.Save();
			break;
		case SORT:
			sm.SortEmployee();
			break;
		case DESTORY:
			sm.DestoryedInfo();
			break;
		default:
			cout << "输入无效,请重新输入" << endl;
			break;
		}
	} while (choice);//以0作为结束选项
}

int main()
{
	operate();
	return 0;
}

main函数起一个开头作用,告诉程序从这里开始执行,我们大可以把程序写在外部。对于时间戳(目前就知道这个)或其他特殊定义,需要定义在main()函数中才有效。

三、各函数模块的实现

一、职工类的类中函数实现

基类职工类作为公共属性,不设置构造函数,只是用来提供数据对象和函数。需要在派生类中创建构造函数,重写基类虚函数。

一、构造函数

Boss::Boss(int id, string name, string sex, string tel, int type, int salary)
{
	this->m_id = id;
	this->m_name = name;
	this->m_type = type;
	this->m_sex = sex;
	this->m_tel = tel;
	this->m_salary = salary;
}//老板类
Manager::Manager(int id, string name, string sex, string tel, int type, int salary)
{
	this->m_id = id;
	this->m_name = name;
	this->m_type = type;
	this->m_sex = sex;
	this->m_tel = tel;
	this->m_salary = salary;
}//经理类
Employee::Employee(int id, string name, string sex, string tel, int type, int salary)
{
	this->m_id = id;
	this->m_name = name;
	this->m_type = type;
	this->m_sex = sex;
	this->m_tel = tel;
	this->m_salary = salary;
}//员工类

 可以看到,构造函数用于对对象赋值,避免繁琐的cin>>A.b这样的赋值。

二、展示函数

由于三个都差不多,就拿一个来举例

void Boss::ShowInfo()
{
	cout << "职工编号:" << this->m_id
		<< "\t职工姓名:" << this->m_name
		<< "\t职工性别:" << this->m_sex
		<< "\t职工电话:" << this->m_tel
		<< "\t职工薪资:" << this->m_salary
		<< "\t职工岗位:" << this->GetWork()//因为基类采用编号代表职位,这里要根据编号取得职位名
		<< "\t岗位职责:管理公司所有事务" << endl;//这句是对职工职能的描述
}

经理职责:"\t岗位职责:完成老板布置的任务,并下发任务给员工";

员工职责:"\t岗位职责:完成经理布置的任务"

 三、取得职位名的函数

string Boss::GetWork()
{
	return string("老板");
}

string Manager::GetWork()
{
	return string("经理");
}

string Employee::GetWork()
{
	return string("员工");
}

返回一个名字即可。

二、管理类的类中函数实现

一、构造函数

因为需要读取文件,构造时要先读取文件中的数据。

StaffManagement::StaffManagement()
{
	ifstream in;
	in.open(FILENAME, ios::in | ios::binary);//我采用二进制数据(ios::binary),可以把这去掉
	if (!in.is_open())//如果文件未打成功
	{
		this->CheckFile = true;
		this->P_arr = NULL;
		this->P_n = 0;
		in.close();
		return;
	}
//如果文件为空,则将EOF读走
	char ret;
	in >> ret;
	if (in.eof())
	{
		this->CheckFile = true;
		this->P_arr = NULL;
		this->P_n = 0;
		in.close();
		return;
	}
//这里表明文件打开成功且存有数据
	this->P_n = this->GetFileSize();//获取职工数
	this->P_arr = new Staff*[this->P_n];//开辟存储空间
	this->InitFile();//跳转初始化函数
}

二、取得文件职工数量的函数

int StaffManagement::GetFileSize()
{
	ifstream in;
	in.open(FILENAME, ios::in | ios::binary);
	int count = 0, id, type ,salary;
	string name, sex, tel;//创建临时变量接收读取文件
	while (in >> id && in >> name && in >> sex && in >> tel && in && in >> salary&&in>>type)//循环读取,直到读到文件尾
	{
		count++;
	}
	return count;//返回计数值
}

三、初始化函数

void StaffManagement::InitFile()//就是把文件中的数据读取到内存中
{
	ifstream in;
	in.open(FILENAME, ios::in | ios::binary);
	int index = 0, id, type,salary;
	string name, sex, tel;
	while (in >> id && in >> name && in >> sex && in >> tel && in >> salary && in >> type )
	{
		Staff*staff = NULL;//创建临时指针,接收创建的对应的职工
		switch (type)//根据职位编号选择
		{
		case 1:
			staff = new Employee(id, name, sex, tel, type, salary);
			break;
		case 2:
			staff = new Manager(id, name, sex, tel, type, salary);
			break;
		case 3:
			staff = new Boss(id, name, sex, tel, type, salary);
			break;
		default:
			cout << "初始化错误" << endl;
			break;  
		}
		this->P_arr[index] = staff;//将创建的数据地址存給二级指
		index++;
	}
}

四、菜单函数

这块可以根据自己设计,好像可以再设个登录系统,输入密码,屏幕上显示*等操作。可以自己试试。

void StaffManagement::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 << "*************       8.清空所有职工信息     ***********" << endl;
	cout << "******************************************************" << endl;
}//上面的保存功能已内置于各功能函数中,实际上不需要手动操作,这里是为了拿出来看

 五、职工添加函数

这块比较复杂,涉及很多操作,要检查输入ID是否重复,重新开辟内存空间,以及流程设置

void StaffManagement::AddEmployee()
{
	int add_n;
	while (true)
	{
		cout << "请输入添加员工的数量" << endl;
		cin >> add_n;//可以一次添加多名员工
		if (add_n > 0)
		{
			int newsize = this->P_n + add_n;
			Staff**newspace = new Staff*[newsize];//创建新的数量及内存
			if (!this->P_arr)//将旧的内存数据拷贝到新开辟的上面
			{
				for (int i = 0; i < this->P_n; i++)
					newspace[i] = this->P_arr[i];
			}
			for (int i = 0; i < add_n; i++)
			{
				int id;
				string name;
				string sex;
				string tel;
				int salary;
				int choice;
				while (true)//对错误输入采取循环,直到全部正确
				{
					cout << "请输入第" << i + 1 << "个新职工的编号:" << endl;
					cin >> id;
					if (!this->CheckId(id))//检查Id是否重复
					{
						cout << "职工编号重复,请重新输入" << endl;
					}
					else
						break;
				}
				cout << "请输入第" << i + 1 << "个新职工的姓名:" << endl;
				cin >> name;
				cout << "请输入第" << i + 1 << "个新职工的性别:" << endl;
				cin >> sex;
				cout << "请输入第" << i + 1 << "个新职工的电话:" << endl;
				cin >> tel;
				cout << "请输入第" << i + 1 << "个新职工的薪资:" << endl;
				cin >> salary;
				cout << "请选择以下职工岗位:" << endl
					<< "1.员工" << endl
					<< "2.经理" << endl
					<< "3.老板" << endl;
				cin >> choice;
				Staff*staff = NULL;
				switch (choice)
				{
				case 1:
					staff = new Employee(id, name,sex,tel,choice,salary);
					break;
				case 2:
					staff = new Manager(id, name, sex, tel,choice, salary);
					break;
				case 3:
					staff = new Boss(id, name, sex, tel, choice, salary);
					break;
				default:
					cout << "输入无效,请从新输入" << endl;
					break;
				}
				newspace[this->P_n + i] = staff;//与初始化函数相同,不过这是直接从输入中读取
//存入新空间中
			}
			delete[] this->P_arr;//释放掉旧的内存空间
			this->P_arr = newspace;
			this->P_n = newsize;
			this->CheckFile = false;//让指针指向新的内存,并赋上新的值
			cout << "成功添加" << add_n << "名新职工" << endl;
			this->Save();//自动调用保存函数
			system("pause");//进行屏幕刷新
			system("cls");
			this->Menu();
			break;
		}
		else
			cout << "输入无效,请求重新输入" << endl;
	}
}

六、ID检查函数

bool StaffManagement::CheckId(int n)
{
	for (int i = 0; i < this->P_n; i++)
	{
		if (this->P_arr[i]->m_id == n)//遍历查找
			return false;
	}
	return true;
}

七、保存函数

一个简单的文件写入操作

void StaffManagement::Save()
{
	ofstream out;
	out.open(FILENAME, ios::out | ios::binary);
	for (int i = 0; i < this->P_n; i++)
//注意,写入要打空格和换行,一是便于人看,二是避免数字字符读成一个数,或一个字符串
	{
		out << this->P_arr[i]->m_id << " "
			<< this->P_arr[i]->m_name << " "
			<< this->P_arr[i]->m_sex << " "
			<< this->P_arr[i]->m_tel << " "
			<< this->P_arr[i]->m_salary << " "
			<< this->P_arr[i]->m_type << endl;
	}
	out.close();
	cout << "保存成功" << endl;
}

八、职工删除函数

void StaffManagement::DeleteEmployee()
{
	if (!this->P_n)//计数为零,无人员信息
		cout << "删除失败,文件不存在或文件内容为空" << endl;
	else
	{
		cout << "请输入职工编号" << endl;
		int n;
		cin >> n;
		int index = this->GetRank(n);//查找下标的函数
		if (index == -1)
			cout << "职工信息不存在" << endl;
		else
		{
			for (int i = 0; i < this->P_n - 1; i++)
				this->P_arr[i] = this->P_arr[i + 1];//进行数据移动
		}
		this->P_n--;//计数减一
		this->Save();
		cout << "删除成功" << endl;
	}
}

 九、下标查找函数与姓名查找函数

int StaffManagement::GetRank(int n)
{
	int index = -1;
	for (int i = 0; i < this->P_n; i++)
	{
		if (this->P_arr[i]->m_id == n)
		{
			index = i;
			break;
		}
	}
	return index;
}

void StaffManagement::NameSearch(string name)//这用于查找职工
{
	for (int i = 0; i < this->P_n; i++)
	{
		if (this->P_arr[i]->m_name == name)//string可以直接比较
			this->P_arr[i]->ShowInfo();//直接打印信息
	}
}

十、职工修改函数

这部分我们通常做全部修改,选择改的话代码就太复杂了。代码与之前的添加差不多,少了开辟等操作,在原基础上修改。

void StaffManagement::ModifyEmployee()
{
	if (!this->P_n)
		cout << "修改失败,文件不存在或文件内容为空" << endl;
	else
	{
		cout << "请输入职工编号" << endl;
		int n;
		cin >> n;
		int index = this->GetRank(n);
		if (index == -1)
			cout << "职工信息不存在" << endl;
		else
		{
			delete this->P_arr[index];
			int newid, newtype, newsalary;
			string newname, newsex, newtel;
			while (true)
			{
				cout << "请输入新的职工编号" << endl;
				cin >> newid;
				if (!this->CheckId(newid))
					cout << "职工编号重复,请重新输入" << endl;
				else
					break;
			}
			cout << "请输入新的职工姓名:" << endl;
			cin >> newname;
			cout << "请输入新的职工职工性别:" << endl;
			cin >> newsex;
			cout << "请输入新的职工电话:" << endl;
			cin >> newtel;
			cout << "请输入新的职工薪资:" << endl;
			cin >> newsalary;
			cout << "请选择以下职工岗位:" << endl
				<< "1.员工" << endl
				<< "2.经理" << endl
				<< "3.老板" << endl;
			cin >> newtype;
			Staff*staff = NULL;
			switch (newtype)
			{
			case 1:
				staff = new Employee(newid, newname,newsex,newtel, newtype,newsalary);
				break;
			case 2:
				staff = new Manager(newid, newname, newsex, newtel, newtype, newsalary);
				break;
			case 3:
				staff = new Boss(newid, newname, newsex, newtel, newtype, newsalary);
				break;
			default:
				cout << "输入无效,请从新输入" << endl;
				break;
			}
			this->P_arr[index] = staff;
			this->Save();
			cout << "修改成功" << endl;
		}
	}
	system("pause");
	system("cls");
	this->Menu();
}

十一、查找职工

void StaffManagement::SearchEmployee()
{
	if (!this->P_n)
		cout << "文件不存在或文件为空" << endl;
	else
	{
		while (true)
		{
			cout << "请选择查找方式:" << endl//设置两种查找方式
				<< "1.职工编号" << endl
				<< "2.职工姓名" << endl;
			int choice;
			cin >> choice;
			if (choice == 1)
			{
				cout << "请输入职工编号:" << endl;
				int id;
				cin >> id;
				if (this->GetRank(id) == -1)
					cout << "无此职工信息" << endl;
				else
				{
					cout << "查找成功,职工信息如下:" << endl;
					this->P_arr[this->GetRank(id)]->ShowInfo();
				}
				break;
			}
			else if (choice == 2)
			{
				cout << "请输入职工姓名" << endl;
				string name;
				cin >> name;
				cout << "查找结果如下:" << endl;
				this->NameSearch(name);
				break;
			}
			else
				cout << "选择无效,请重新选择" << endl;
		}
	}
	system("pause");
	system("cls");
	this->Menu();
}

十二、职工排序

我设置了好几种排序,这里用的是选择排序,还可以使用algorithm内置的快排函数sort.

void StaffManagement::SortEmployee()
{
	if (!this->P_n)
		cout << "文件不存在或文件为空" << endl;
	else
	{
		while (true)//分了很多类排序
		{
			cout << "请选择排序方式:" << endl
				<< "1.按职工编号升序" << endl
				<< "2.按职工编号降序" << endl
				<< "3.按职工姓名升序" << endl
				<< "4.按职工职工降序" << endl
				<< "5.按职工电话升序" << endl
				<< "6.按职工电话降序" << endl
				<< "7.按职工薪资升序" << endl
				<< "8.按职工薪资降序" << endl;
			int choice;
			cin >> choice;
			for (int i = 0; i < this->P_n; i++)
			{
				int minormax = i;//选择排序,设置下标
				for (int j = i + 1; j < this->P_n; j++)
				{
					switch (choice)//嵌套选择函数
					{
					case 1:
						if (this->P_arr[minormax]->m_id > this->P_arr[j]->m_id)
							minormax = j;
						break;
					case 2:
						if (this->P_arr[minormax]->m_id < this->P_arr[j]->m_id)
							minormax = j;
						break;
					case 3:
                         //string字符串比较函数
						if (this->P_arr[minormax]->m_name.compare(P_arr[j]->m_name) > 0)
							minormax = j;
						break;
					case 4:
						if (this->P_arr[minormax]->m_name.compare(P_arr[j]->m_name) < 0)
							minormax = j;
						break;
					case 5:
						if (this->P_arr[minormax]->m_tel.compare(P_arr[j]->m_tel)>0)
							minormax = j;
					case 6:
						if (this->P_arr[minormax]->m_tel.compare(P_arr[j]->m_tel)<0)
							minormax = j;
						break;
					case 7:
						if (this->P_arr[minormax]->m_salary > this->P_arr[j]->m_salary)
							minormax = j;
						break;
					case 8:
						if (this->P_arr[minormax]->m_salary < this->P_arr[j]->m_salary)
							minormax = j;
						break;
					default:
						cout << "选择无效,请重新输入" << endl;
						choice = 0;
						break;
					}
				}
				if (i != minormax)//改变则交换
				{
					Staff*temp = this->P_arr[i];
					this->P_arr[i] = this->P_arr[minormax];
					this->P_arr[minormax] = temp;
				}
			}
			if (choice)
			{
				cout << "排序完成,结果如下>:" << endl;
				this->Save();
				this->ShowEmployee();//打印排序后的数据
				break;
			}
		}
	}
}

十三、职工信息清除

与删库跑路有些相像

void StaffManagement::DestoryedInfo()
{
	cout << "确认清除所有信息?" << endl//这里设置Y/N也好
		<< "确认请输入1" << endl
		<< "返回请输入其它任意数字" << endl;
	int choice;
	cin >> choice;
	if (choice == 1)
	{
		ofstream out(FILENAME, ios::trunc);//如果文件存在则删除文件(ios::trunc)
      //所以那个check
		out.close();
		if (this->P_arr)
		{
			for (int i = 0; i < this->P_n; i++)//释放内存空间,要分级释放
			{
				delete this->P_arr[i];
				this->P_arr[i] = NULL;
			}
			delete[]this->P_arr;
			this->P_n = 0;
			this->P_arr = NULL;
			this->CheckFile = true;
			cout << "所有信息已被清除!" << endl;
		}
	}
	else
	{
		system("cls");
		this->Menu();
		return;
	}
	system("pause");
	system("cls");
	this->Menu();
}

十四、析构函数

因为C++的类会自动调用析构函数释放内存,这里写个个空实现就行

StaffManagement::~StaffManagement(){}

四、总结

可以看到,单个模块的设计并不复杂,都是可以想到,推出来的,关键在于设计思路要流畅

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
【员工管理系统】 问题描述:每个员工的信息包括:编号、姓名、性别、出生年月、学历、职务、电话、住址等。系统能够完成员工信息的查询、更新、插入、删除、排序等功能。 基本要求:排序:按不同关键字,对所有员工的信息进行排序;查询:按特定条件查找员工;更新,按编号对某个员工的某项信息进行修改;插入,加入新员工的信息;删除,按编号删除已离职的员工的信息。 选作内容:实现图形用户界面。 通过链表实现 数据结构: #include #include #include #include #include using namespace std; typedef struct workers{ char name[15];//姓名 char department[18];//单位 char gender;//性别 unsigned int age;//年龄 unsigned long long telephone;//电话 unsigned long wage;//工资 unsigned long num;//职工号 struct workers *next; }*Linklist,Lnode; void frist_print() { printf("\t\t⊙▽⊙ ⊙▽⊙ ⊙▽⊙ ⊙▽⊙ ⊙▽⊙ ⊙▽⊙ \n\n"); printf("\t\t\t欢迎进入员工管理系统\n"); } void menu() { printf("\n\t\t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); printf("\t\t \t ◎1.创建员工信息\t \n"); printf("\t\t \t ◎2.插入员工信息\t \n"); printf("\t\t \t ◎3.修改员工信息\t \n"); printf("\t\t \t ◎4.删除员工信息\t \n"); printf("\t\t \t ◎5.查询员工信息\t \n"); printf("\t\t \t ◎6.员工信息排序\t \n"); printf("\t\t \t ◎7.显示员工信息\t \n"); printf("\t\t \t ◎8.员工工资情况\t \n"); printf("\n\t\t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); printf("注意:输入均以回车作为结束\n"); printf("please choise 1--8:\t "); //putchar(12); } void Inset(Linklist Head){ Linklist s,L; unsigned int agee; unsigned long wagee,numm;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

...404 Not Found

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

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

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

打赏作者

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

抵扣说明:

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

余额充值