基于多态的职工管理系统学习记录

news2025/5/22 12:42:31

职工管理系统

1、管理系统需求

公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责

普通员工职责:完成经理交给的任务

经理职责:完成老板交给的任务,并下发任务给员工

老板职责:管理公司所有事务

管理系统中需要实现的功能如下:

退出管理程序:退出当前管理系统

增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部 门编号

显示职工信息:显示公司内部所有职工的信息

删除离职职工:按照编号删除指定的职工

修改职工信息:按照编号修改职工个人信息

查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息

按照编号排序:按照职工编号,进行排序,排序规则由用户指定

清空所有文档:清空文件中记录的所有职工信息 (清空前需要再次确认,防止误删)

2、创建项目(略)

创建项目步骤如下:

创建新项目

添加文件

3、创建管理类

管理类负责的内容如下:

与用户的沟通菜单界面、对职工增删改查的操作、与文件的读写交互

3.1创建文件:在头文件和源文件的文件夹下分别创建workerManager.h 和 workerManager.cpp文件

3.2 头文件实现:在workerManager.h中设计管理类,代码如下:

#pragma once	//防止头文件重复包含
#include<iostream>	//包含输入输出流头文件
using namespace std;	//使用标准命名空间

class WorkerManager
{
public:
	//构造函数
	WorkerManager();	

	//析构函数
	~WorkerManager();
};

3.3 源文件实现:在workerManager.cpp中将构造和析构函数空实现补全 

#include "WorkerManager.h"

WorkerManager::WorkerManager()
{
}

WorkerManager::~WorkerManager()
{
}

4、菜单功能

功能描述:与用户的沟通界面

4.1 添加成员函数:在管理类workerManager.h中添加成员函数 void Show_Menu();代码如下:

#pragma once	//防止头文件重复包含
#include<iostream>	//包含输入输出流头文件
using namespace std;	//使用标准命名空间

class WorkerManager
{
public:
	//构造函数
	WorkerManager();

	//展示菜单
	void show_Menu();

	//析构函数
	~WorkerManager();

};

4.2 菜单功能实现:在管理类workerManager.cpp中实现 Show_Menu()函数,代码如下:

#include "WorkerManager.h"

WorkerManager::WorkerManager()
{
}

//展示菜单
void WorkerManager::show_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 << "******************************************" << endl;
	cout << endl;

}

WorkerManager::~WorkerManager()
{
}

4.3 测试菜单功能:在(职工管理系统.cpp)中测试菜单功能,代码如下:

#include<iostream>
using namespace std;
#include"workerManager.h"

int main()
{
	//实例化管理者对象
	WorkerManager wm;

    //调用展示菜单成员函数
    wm.show_Menu();

	return 0;
}

5、退出功能

5.1 提供功能接口,在main函数中提供分支选择,提供每个功能接口,代码如下:

#include<iostream>
using namespace std;
#include"workerManager.h"

int main()
{
	//实例化管理者对象
	WorkerManager wm;

	int choice = 0;//用来存储用户的选项

	while (true)
	{
		//调用展示菜单成员函数
		wm.show_Menu();

		cout << "请输入您的选择:" << endl;
		cin >> choice;//接受用户的选择

		switch (choice)
		{
		case 0://退出系统
			wm.ExitSystem();
			break;
		case 1://增加职工
			break;
		case 2://显示职工
			break;
		case 3://删除职工
			break;
		case 4://修改职工
			break;
		case 5://查找职工
			break;
		case 6://排序职工
			break;
		case 7://清空文档
			break;
		default:
			system("cls");//清屏
			break;
		}

	}

	return 0;
}

5.2 实现退出功能

在workerManager.h中提供退出系统的成员函数 void exitSystem();代码如下:

#pragma once	//防止头文件重复包含
#include<iostream>	//包含输入输出流头文件
using namespace std;	//使用标准命名空间

class WorkerManager
{
public:
	//构造函数
	WorkerManager();

	//展示菜单
	void show_Menu();

	//退出系统
	void ExitSystem();
	
	//析构函数
	~WorkerManager();

};

在workerManager.cpp中提供具体的功能实现,代码如下:

//退出系统
void WorkerManager::ExitSystem()
{
	cout << "欢迎下次使用" << endl;
	system("pause");
	exit(0);//退出程序
}

5.3测试功能:在main函数分支 0 选项中,调用退出程序的接口。代码如下:

#include<iostream>
using namespace std;
#include"workerManager.h"

int main()
{
	//实例化管理者对象
	WorkerManager wm;

	int choice = 0;//用来存储用户的选项

	while (true)
	{
		//调用展示菜单成员函数
		wm.show_Menu();

		cout << "请输入您的选择:" << endl;
		cin >> choice;//接受用户的选择

		switch (choice)
		{
		case 0://退出系统
			wm.ExitSystem();
			break;
		case 1://增加职工
			break;
		case 2://显示职工
			break;
		case 3://删除职工
			break;
		case 4://修改职工
			break;
		case 5://查找职工
			break;
		case 6://排序职工
			break;
		case 7://清空文档
			break;
		default:
			system("cls");//清屏
			break;
		}

	}

	return 0;
}

6、创建职工类

6.1 创建职工抽象类

职工的分类为:普通员工、经理、老板

将三种职工抽象到一个类(worker)中,利用多态管理不同职工种类

职工的属性为:职工编号、职工姓名、职工所在部门编号

职工的行为为:岗位职责信息描述,获取岗位名称

头文件文件夹下 创建文件worker.h 文件并且添加如下代码:

#pragma once
#include<iostream>
using namespace std;
#include<string>

//职工抽象类
class Worker
{
public:
	//显示个人信息
	virtual void showInfo() = 0;

	//获取岗位名称
	virtual string getDeptName() = 0;

	//职工编号
	int m_Id;

	//职工姓名
	string m_Name;

	//部门编号
	int m_DeptId;
};

6.2 创建普通员工类

普通员工类继承职工抽象类,并重写父类中纯虚函数

在头文件和源文件的文件夹下分别创建employee.h 和 employee.cpp文件

employee.h中代码如下:子类继承父类,要记得写职工抽象类的头文件

//普通员工共文件
#pragma once
#include<iostream>
using namespace std;
#include"worker.h"

class Employee :public Worker
{
public:
	//构造函数
	Employee(int id,string name,int dId);

	//显示个人信息
	virtual void showInfo();

	//获取岗位名称
	virtual string getDeptName();
};

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 string("员工");
}

6.3 创建经理类(此步骤与普通员工类似,仅仅岗位名称和职责有变化)

经理类继承职工抽象类,并重写父类中纯虚函数

在头文件和源文件的文件夹下分别创建manager.h 和 manager.cpp文件

manager.h中代码如下:

#pragma once
#include<iostream>
using namespace std;
#include"worker.h"

//经理类
class Manager :public Worker
{
public:

	//构造函数
	Manager(int id, string name, int dId);

	//显示个人信息
	virtual void showInfo();

	//获取岗位名称
	virtual string getDeptName();
};

manager.cpp中代码如下:

#include"manager.h"
#include<string>

//构造函数
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 string("经理");
}

6.4 创建老板类(此步骤与普通员工类似,仅仅岗位名称和职责有变化)

老板类继承职工抽象类,并重写父类中纯虚函数

在头文件和源文件的文件夹下分别创建boss.h 和 boss.cpp文件

boss.h中代码如下:

#pragma once
#include<iostream>
using namespace std;
#include"worker.h"

//老板类
class Boss :public Worker
{
public:

	//构造函数
	Boss(int id, string name, int dId);

	//显示个人信息
	virtual void showInfo();

	//获取岗位名称
	virtual string getDeptName();
};

boss.cpp中代码如下:

#include"boss.h"
#include<string>

//构造函数
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 string("总裁");
}

6.5 测试多态

在职工管理系统.cpp中添加测试函数,并且运行能够产生多态

测试代码如下:

#include"worker.h"
#include"employee.h"
#include"manager.h"
#include"boss.h"

void test()
{

	//测试代码
	Worker* worker = NULL;
    //初始化为空,这可以避免未初始化的指针指向随机的内存地址,从而成为野指针。
	worker = new Employee(1, "张三",1);
	worker->showInfo();
	delete worker;

	worker = new Manager(2, "李四", 2);
	worker->showInfo();
	delete worker;

	worker = new Boss(3, "王五", 3);
	worker->showInfo();
	delete worker;
}

注:测试成功后,测试代码可以注释保留,或者选择删除

7、添加职工

功能描述:批量添加职工,并且保存到文件中

7.1 功能分析

用户在批量创建时,可能会创建不同种类的职工,如果想将所有不同种类的员工都放入到一个数组中,可以将所有员工的指针维护到一个数组里,如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用Worker **的指针维护

 上图解释:

创建普通员工:
new empliyee    返回的是    employee*
创建经理:
new manager     返回的是    manager*
创建老板:
new boss        返回的是    boss*

返回的指针不一样,利用多态可以统一指针,都可以用父类指针指向子类对象

再用一个数组(开辟到堆区,因为栈区用完便被释放了)保存所有父类指针

new一个每个元素都是wokrer*的数组,一共有五个元素:

worker** = new worker*[5]

new的是worker*,那么返回的则是worker**(因为new返回的是该对象的指针)[指向指针(worker*数组的指针)的指针,或者二级指针]

即:worker** 指向的是一系列指针,而这些指针(worker*)则各自指向一个 worker 对象。

7.2 功能实现

在WokerManager.h头文件中添加成员属性代码:(并包含worker.h、manager.h、boss.h头文件)

//记录职工人数
int m_EmpNum;

//职工数组指针
Worker** m_EmpArray;

在WorkerManager.cpp的WorkerManager构造函数中初始化属性:

WorkerManager::WorkerManager()
{
    //初始化属性
	//初始化记录人数
	this->m_EmpNum = 0;

	//初始化数组指针
	this->m_EmpArray = NULL;

}

在workerManager.h中添加成员函数:

//添加职工
void Add_Emp();

workerManager.cpp中实现该函数:

//添加职工
void WorkerManager::Add_Emp()
{
	cout << "请输入添加职工数量: " << endl;

	int addNum = 0;//保存用户的输入数量
	cin >> addNum;

	if (addNum > 0)
	{
		//添加
		//计算添加新空间大小
		int newSize = this->m_EmpNum + addNum;//新空间人数 = 原来记录人数 + 新增人数
		
		//开辟新空间
		Worker ** newSpace = new Worker* [newSize];

		//将原来空间下数据拷贝到新空间下
		if (this->m_EmpArray != NULL)
		{
			for (int i = 0; i < this->m_EmpNum; i++)
			{
				newSpace[i] = this->m_EmpArray[i];
			}
		}

		//批量添加新数据
		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;

			Worker* worker = NULL;
			switch (dSelect)
			{
			case 1:
				worker = new Employee(id, name, 1);
				break;
			case 2:
				worker = new Manager(id, name, 2);
				break;
			case 3:
				worker = new Boss(id, name, 3);
				break;
			default:
				break;
			}
			//将创建的的职工指针,保存到数组中
			newSpace[this->m_EmpNum + i] = worker;
		}
		//释放原有的空间
		delete[] this->m_EmpArray;

		//更改新空间指向
		this->m_EmpArray = newSpace;

		//更新新的职工人数
		this->m_EmpNum = newSize;
	
		//提示添加成功
		cout << "成功添加" << addNum << "名新职工" << endl;
	}
	else
	{
		cout << "输入数据有误" << endl;
	}

	//按任意键后清屏返回上级目录
	system("pause");
	system("cls");
}

在WorkerManager.cpp的析构函数中,释放堆区数据:

WorkerManager::~WorkerManager()
{
	if (this->m_EmpArray != NULL)
	{
		delete[] this->m_EmpArray;
		this->m_EmpArray = NULL;
	}
}

7.3 测试添加

在main函数分支 1 选项中,调用添加职工接口:

case 1://增加职工
	wm.Add_Emp();
	break;

8、文件交互 - 写文件

功能描述:对文件进行读写

在上一个添加功能中,我们只是将所有的数据添加到了内存中,一旦程序结束就无法保存了,因此文件管理类中需要一个与文件进行交互的功能,对于文件进行读写操作

8.1 设定文件路径

首先我们将文件路径,在workerManager.h中添加宏常量,并且包含头文件 fstream

#include<fstream>
#define FILENAME "empFile.txt"

8.2 成员函数声明 在workerManager.h中类里添加成员函数 void save()

//保存文件
void save();

8.3 保存文件功能实现

在workerManager.cpp下实现:

//保存文件
void WorkerManager::save()
{
	ofstream ofs;
	ofs.open(FILENAME, ios::out);	//用输出的方式打开文件--写文件

	//将每个人数据写入到文件中
	for (int i = 0; i < this->m_EmpNum; i++)
	{
		ofs << this->m_EmpArray[i]->m_Id << " "
			<< this->m_EmpArray[i]->m_Name << " "
			<< this->m_EmpArray[i]->m_DeptId << endl;
	}

	//关闭文件
	ofs.close();
}

8.4 保存文件功能测试

在workerManager.cpp添加职工功能中添加成功后添加保存文件函数:

//成功添加后保存数据到文件中
this->save();

9、文件交互 - 读文件

功能描述:将文件中的内容读取到程序中

虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中数据读取到程序中,而我们的程序功能中还有清空文件的需求,因此构造函数初始化数据的情况分为三种:

①第一次使用,文件未创建

②文件存在,但是数据被用户清空

③文件存在,并且保存职工的所有数据

9.1 文件未创建

在workerManager.h中添加新的成员属性 m_FileIsEmpty标志文件是否为空:

//判断文件是否为空 标志
bool m_FileIsEmpty;

修改WorkerManager.cpp中构造函数代码:

WorkerManager::WorkerManager()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);//读文件

	//1.文件不存在
	if (!ifs.is_open())
	{
		cout << "文件不存在" << endl;
		//初始化属性
		//初始化记录人数
		this->m_EmpNum = 0;
		//初始化数组指针
		this->m_EmpArray = NULL;
		//初始化文件是否为空
		this->m_FileIsEmpty = true;
		ifs.close();
		return;
	}

9.2 文件存在且数据为空

在workerManager.cpp中的构造函数追加代码:

//2.文件存在 数据为空
char ch;
ifs >> ch;
if (ifs.eof())
{
	//cout << "文件为空!" << endl;
	//初始化记录人数
	this->m_EmpNum = 0;
	//初始化数组指针
	this->m_EmpArray = NULL;
	//初始化文件是否为空
	this->m_FileIsEmpty = true;
	ifs.close();
	return;
}

我们发现文件不存在或者为空清空 m_FileIsEmpty 判断文件是否为空的标志都为真,那何时为假?

成功添加职工后,应该更改文件不为空的标志

在 void WorkerManager::Add_Emp() 成员函数中添加:

//更新职工不为空标志
this->m_FileIsEmpty = false;

9.3 文件存在且保存职工数据

9.3.1 获取记录的职工人数

在workerManager.h中添加成员函数 int get_EmpNum();

//统计文件中人数
int get_EmpNum();

workerManager.cpp中实现:

//统计文件中人数
int WorkerManager::get_EmpNum()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);//打开文件

	int id;
	string name;
	int dId;

	int num = 0;
	while (ifs >> id && ifs >> name && ifs >> dId)
	{
		//统计人数变量 
		num++;
	}
	return num;
}

在workerManager.cpp构造函数中继续追加代码:

//3.当文件存在并且记录数据
int num = this->get_EmpNum();
cout << "职工人数为: " << num << endl;//测试代码
this->m_EmpNum = num;//更新成员属性

9.3.2 初始化数组

根据职工的数据以及职工数据,初始化workerManager中的Worker ** m_EmpArray 指针

在WorkerManager.h中添加成员函数 void init_Emp();

//初始化职工
void init_Emp();

在WorkerManager.cpp中实现:

//初始化员工
void WorkerManager::init_Emp()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);

	int id;
	string name;
	int dId;

	int index = 0;
	while (ifs >> id && ifs >> name && ifs >> dId)
	{
        //根据不同的部门Id创建不同对象
		Worker* worker = NULL;
		if (dId == 1)//普通员工
		{
			worker = new Employee(id, name, dId);
		}
		else if (dId == 2)//经理
		{
			worker = new Manager(id, name, dId);
		}
		else//老板
		{
			worker = new Boss(id, name, dId);
		}
        //存放在数组中
		this->m_EmpArray[index] = worker;
		index++;
	}

	//关闭文件
	ifs.close();
}

在workerManager.cpp构造函数中追加代码:

//开辟空间
this->m_EmpArray = new Worker * [this->m_EmpNum];
//将文件中的数据存到数组中
this->init_Emp();

//测试代码
for (int i = 0; i < this->m_EmpNum; i++)
{
	cout << "职工编号:" << this->m_EmpArray[i]->m_Id
		<< "姓名:" << this->m_EmpArray[i]->m_Name
		<< "部门编号:" << this->m_EmpArray[i]->m_DeptId << endl;
}

10、显示职工

功能描述:显示当前所有职工信息

10.1 显示职工函数声明

在workerManager.h中添加成员函数 void Show_Emp();

//显示职工
void Show_Emp();

10.2 显示职工函数实现

在workerManager.cpp中实现成员函数 void Show_Emp();

//显示职工
void WorkerManager::Show_Emp()
{
	//判断文件是否为空
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或者记录为空!" << endl;
	}
	else
	{
		for (int i = 0; i < m_EmpNum; i++)
		{
			//利用多态调用程序接口
			this->m_EmpArray[i]->showInfo();
		}
	}
	
	//按任意键清屏
	system("pause");
	system("cls");
}

11、删除职工

功能描述:按照职工的编号进行删除职工操作

11.1 删除职工函数声明

在workerManager.h中添加成员函数 void Del_Emp();

//删除职工
void Del_Emp();

11.2 职工是否存在函数声明

很多功能都需要用到根据职工是否存在来进行操作如:删除职工、修改职工、查找职工

因此添加该公告函数,以便后续调用

在workerManager.h中添加成员函数 int IsExist(int id);

//判断职工是否存在,如果存在返回职工所在数组中的位置,不存在返回-1
int IsExist(int id);

11.3 职工是否存在函数实现

在workerManager.cpp中实现成员函数 int IsExist(int id);

int WorkerManager::IsExist(int id)
{
	int index = -1;

	for (int i = 0; i < this->m_EmpNum; i++)
	{
		if (this->m_EmpArray[i]->m_Id == id)
		{
			//找到职工
			index = i;
			break;
		}
	}
	return index;
}

11.4 删除职工函数实现

在workerManager.cpp中实现成员函数 void Del_Emp();

//删除员工
void WorkerManager::Del_Emp()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或者记录为空!" << endl;
	}
	else
	{
		//按照职工编号删除
		cout << "请输入想要删除职工编号:" << endl;
		int id = 0;
		cin >> id;

		int index = this->IsExist(id);

		if (index != -1)//说明职工存在,并且要删除index位置上的职工
		{
			//数据前移
			for (int i = index; i < this->m_EmpNum - 1; i++)
			{
				this->m_EmpArray[i] = this->m_EmpArray[i + 1];
			}
			this->m_EmpNum--;//更新数组中记录人员个数
			//同步更新到文件中
			this->save();

			cout << "删除成功!" << endl;
		}
		else
		{
			cout << "删除失败,未找到该职工" << endl;
		}
	}

	//按任意键清屏
	system("pause");
	system("cls");
}

12、修改职工

功能描述:能够按照职工的编号对职工信息进行修改并保存

12.1 修改职工函数声明

在workerManager.h中添加成员函数 void Mod_Emp();

//修改职工
void Mod_Emp();

12.2 修改职工函数实现

在workerManager.cpp中实现成员函数 void Mod_Emp();

//修改职工
void WorkerManager::Mod_Emp()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或者记录为空!" << endl;
	}
	else
	{
		cout << "请输入修改职工的编号: " << endl;
		int id;
		cin >> id;

		int ret = this->IsExist(id);
		if (ret != -1)
		{
			//查找到编号的职工
			delete this->m_EmpArray[ret];

			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;
			Worker* worker = NULL;
			switch (dSelect)
			{
			case 1:
				worker = new Employee(newId, newName, dSelect);
				break;
			case 2:
				worker = new Manager(newId, newName, dSelect);
				break;
			case 3:
				worker = new Boss(newId, newName, dSelect);
				break;
			}

			//更新数据到数组中
			this->m_EmpArray[ret] = worker;

			cout << "修改成功!" << endl;

			//保存到文件中
			this->save();

		}
		else
		{
			cout << "修改失败,查无此人!" << endl;
		}
	}
	//按任意键清屏
	system("pause");
	system("cls");
}

13、查找职工

功能描述:提供两种查找职工方式,一种按照职工编号,一种按照职工姓名

13.1 查找职工函数声明

在workerManager.h中添加成员函数 void Find_Emp();

//查找职工
void Find_Emp();

13.2 查找职工函数实现

在workerManager.cpp中实现成员函数 void Find_Emp();

//查找职工
void WorkerManager::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;

			int ret = IsExist(id);
			if (ret != -1)
			{
				//找到职工
				cout << "查找成功!该职工信息如下:" << endl;
				this->m_EmpArray[ret]->showInfo();
			}
			else
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else if (select == 2)
		{
			//按姓名查
			string name;
			cout << "请输入查找的姓名:" << endl;
			cin >> name;

			//加入判断是否查到的标志
			bool flag = false;

			for (int i = 0; i < m_EmpNum; i++)
			{
				if (this->m_EmpArray[i]->m_Name == name)
				{
					cout << "查找成功,职工编号为: "
						<< this->m_EmpArray[i]->m_Id
						<< "号职工信息如下:" << endl;

					flag = true;

					//调用显示信息接口
					this->m_EmpArray[i]->showInfo();
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else
		{
			cout << "输入选项有误!" << endl;
		}
		{
		}
		//按任意键清屏
		system("pause");
		system("cls");
	}
}

14、排序

功能描述:按照职工编号进行排序,排序的顺序由用户指定

14.1 排序函数声明

在workerManager.h中添加成员函数 void Sort_Emp();

//按照编号排序
void Sort_Emp();

14.2 排序函数实现

在workerManager.cpp中实现成员函数 void Sort_Emp();

//按照编号排序
void WorkerManager::Sort_Emp()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
		system("pause");
		system("cls");
	}
	else
	{
		cout << "请选择排序方式: " << endl;
		cout << "1、按职工号进行升序" << endl;
		cout << "2、按职工号进行降序" << endl;

		int select = 0;
		cin >> select;
		for (int i = 0; i < m_EmpNum; i++)
		{
			int minOrMax = i;//声明最小值或最大值下标
			for (int j = i + 1; j < this->m_EmpNum; j++)
			{
				if (select == 1)	//升序
				{
					if (this->m_EmpArray[minOrMax]->m_Id > this->m_EmpArray[j]->m_Id)
					{
						minOrMax = j;
					}
				}
				else    //降序
				{
					if (this->m_EmpArray[minOrMax]->m_Id < this->m_EmpArray[j]->m_Id)
					{
						minOrMax = j;
					}
				}
			}
			//判断一开始认定的最小值或最大值是不是计算的最小值或最大值,如果不是,交换数据
			if (i != minOrMax)
			{
				Worker* temp = this->m_EmpArray[i];
				this->m_EmpArray[i] = this->m_EmpArray[minOrMax];
				this->m_EmpArray[minOrMax] = temp;
			}
		}

		cout << "排序成功!排序后的结果为:" << endl;
		this->save();//排序后结果保存到文件中
		this->Show_Emp();
	}
}

15、清空文件

功能描述:将文件中记录数据清空

15.1 清空函数声明

在workerManager.h中添加成员函数 void Clean_File();

//清空文件
void Clean_File();

15.2 清空函数实现

在workerManager.cpp中实现员函数 void Clean_File();

//清空文件
void WorkerManager::Clean_File()
{
	cout << "确定清空?" << endl;
	cout << "1、确定" << endl;
	cout << "2、返回" << endl;

	int select = 0;
	cin >> select;

	if (select == 1)
	{
		//清空文件
		ofstream ofs(FILENAME, ios::trunc);//删除文件后重新创建
		ofs.close();

		if (this->m_EmpArray != NULL)
		{
			//删除堆区的每个职工对象
			for (int i = 0; i < this->m_EmpNum; i++)
			{
				delete this->m_EmpArray[i];
				this->m_EmpArray[i] = NULL;

			}

			//删除堆区数组指针
			delete[] this->m_EmpArray;
			this->m_EmpArray = NULL;
			this->m_EmpNum = 0;
			this->m_FileIsEmpty = true;
		}

		cout << "清空成功!" << endl;
	}
	system("pause");
	system("cls");
}

至此,职工管理系统制作完毕!!!

workerManager.cpp代码汇总如下:

#include "WorkerManager.h"

WorkerManager::WorkerManager()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);//读文件

	//1.文件不存在
	if (!ifs.is_open())
	{
		//cout << "文件不存在" << endl;
		//初始化属性
		//初始化记录人数
		this->m_EmpNum = 0;
		//初始化数组指针
		this->m_EmpArray = NULL;
		//初始化文件是否为空
		this->m_FileIsEmpty = true;
		ifs.close();
		return;
	}

	//2.文件存在 数据为空
	char ch;
	ifs >> ch;
	if (ifs.eof())
	{
		//cout << "文件为空!" << endl;
		//初始化记录人数
		this->m_EmpNum = 0;
		//初始化数组指针
		this->m_EmpArray = NULL;
		//初始化文件是否为空
		this->m_FileIsEmpty = true;
		ifs.close();
		return;
	}

	//3.当文件存在并且记录数据
	int num = this->get_EmpNum();
	//cout << "职工人数为: " << num << endl;//测试代码
	this->m_EmpNum = num;//更新成员属性

	//开辟空间
	this->m_EmpArray = new Worker * [this->m_EmpNum];
	//将文件中的数据存到数组中
	this->init_Emp();

	//测试代码
	//for (int i = 0; i < this->m_EmpNum; i++)
	//{
	//	cout << "职工编号:" << this->m_EmpArray[i]->m_Id
	//		<< "姓名:" << this->m_EmpArray[i]->m_Name
	//		<< "部门编号:" << this->m_EmpArray[i]->m_DeptId << endl;
	//}

	//当时遇到的问题:按2之后不显示txt中的东西。把这行注释掉就可以了
	初始化属性
	//this->m_EmpNum = 0;
	//this->m_EmpArray = NULL;
}

//展示菜单
void WorkerManager::show_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 << "******************************************" << endl;
	cout << endl;

}

//退出系统
void WorkerManager::ExitSystem()
{
	cout << "欢迎下次使用" << endl;
	system("pause");
	exit(0);//退出程序
}

//添加职工
void WorkerManager::Add_Emp()
{
	cout << "请输入添加职工数量: " << endl;

	int addNum = 0;//保存用户的输入数量
	cin >> addNum;

	if (addNum > 0)
	{
		//添加
		//计算添加新空间大小
		int newSize = this->m_EmpNum + addNum;//新空间人数 = 原来记录人数 + 新增人数
		
		//开辟新空间
		Worker ** newSpace = new Worker* [newSize];

		//将原来空间下数据拷贝到新空间下
		if (this->m_EmpArray != NULL)
		{
			for (int i = 0; i < this->m_EmpNum; i++)
			{
				newSpace[i] = this->m_EmpArray[i];
			}
		}

		//批量添加新数据
		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;

			Worker* worker = NULL;
			switch (dSelect)
			{
			case 1:
				worker = new Employee(id, name, 1);
				break;
			case 2:
				worker = new Manager(id, name, 2);
				break;
			case 3:
				worker = new Boss(id, name, 3);
				break;
			default:
				break;
			}
			//将创建的的职工指针,保存到数组中
			newSpace[this->m_EmpNum + i] = worker;
		}
		//释放原有的空间
		delete[] this->m_EmpArray;

		//更改新空间指向
		this->m_EmpArray = newSpace;

		//更新新的职工人数
		this->m_EmpNum = newSize;

		//更新职工不为空标志
		this->m_FileIsEmpty = false;
	
		//提示添加成功
		cout << "成功添加" << addNum << "名新职工" << endl;

		//成功添加后保存数据到文件中
		this->save();
	}
	else
	{
		cout << "输入数据有误" << endl;
	}
	//按任意键后清屏返回上级目录
	system("pause");
	system("cls");
}

//保存文件
void WorkerManager::save()
{
	ofstream ofs;
	ofs.open(FILENAME, ios::out);	//用输出的方式打开文件--写文件

	//将每个人数据写入到文件中
	for (int i = 0; i < this->m_EmpNum; i++)
	{
		ofs << this->m_EmpArray[i]->m_Id << " "
			<< this->m_EmpArray[i]->m_Name << " "
			<< this->m_EmpArray[i]->m_DeptId << endl;
	}

	//关闭文件
	ofs.close();
}

//统计文件中人数
int WorkerManager::get_EmpNum()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);//打开文件

	int id;
	string name;
	int dId;

	int num = 0;
	while (ifs >> id && ifs >> name && ifs >> dId)
	{
		//统计人数变量 
		num++;
	}
	return num;
}

//初始化员工
void WorkerManager::init_Emp()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);

	int id;
	string name;
	int dId;

	int index = 0;
	while (ifs >> id && ifs >> name && ifs >> dId)
	{
		Worker* worker = NULL;
		if (dId == 1)//普通员工
		{
			worker = new Employee(id, name, dId);
		}
		else if (dId == 2)//经理
		{
			worker = new Manager(id, name, dId);
		}
		else
		{
			worker = new Boss(id, name, dId);
		}
		this->m_EmpArray[index] = worker;
		index++;
	}

	//关闭文件
	ifs.close();
}

//显示职工
void WorkerManager::Show_Emp()
{
	//判断文件是否为空
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或者记录为空!" << endl;
	}
	else
	{
		for (int i = 0; i < m_EmpNum; i++)
		{
			//利用多态调用程序接口
			this->m_EmpArray[i]->showInfo();
		}
	}
	

	//按任意键清屏
	system("pause");
	system("cls");
}

//删除员工
void WorkerManager::Del_Emp()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或者记录为空!" << endl;
	}
	else
	{
		//按照职工编号删除
		cout << "请输入想要删除职工编号:" << endl;
		int id = 0;
		cin >> id;

		int index = this->IsExist(id);

		if (index != -1)//说明职工存在,并且要删除index位置上的职工
		{
			//数据前移
			for (int i = index; i < this->m_EmpNum - 1; i++)
			{
				this->m_EmpArray[i] = this->m_EmpArray[i + 1];
			}
			this->m_EmpNum--;//更新数组中记录人员个数
			//同步更新到文件中
			this->save();

			cout << "删除成功!" << endl;
		}
		else
		{
			cout << "删除失败,未找到该职工" << endl;
		}
	}

	//按任意键清屏
	system("pause");
	system("cls");
}

//判断职工是否存在,如果存在返回职工所在数组中的位置,不存在返回-1
int WorkerManager::IsExist(int id)
{
	int index = -1;

	for (int i = 0; i < this->m_EmpNum; i++)
	{
		if (this->m_EmpArray[i]->m_Id == id)
		{
			//找到职工
			index = i;
			break;
		}
	}
	return index;
}

//修改职工
void WorkerManager::Mod_Emp()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或者记录为空!" << endl;
	}
	else
	{
		cout << "请输入修改职工的编号: " << endl;
		int id;
		cin >> id;

		int ret = this->IsExist(id);
		if (ret != -1)
		{
			//查找到编号的职工
			delete this->m_EmpArray[ret];

			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;
			Worker* worker = NULL;
			switch (dSelect)
			{
			case 1:
				worker = new Employee(newId, newName, dSelect);
				break;
			case 2:
				worker = new Manager(newId, newName, dSelect);
				break;
			case 3:
				worker = new Boss(newId, newName, dSelect);
				break;
			}

			//更新数据到数组中
			this->m_EmpArray[ret] = worker;

			cout << "修改成功!" << endl;

			//保存到文件中
			this->save();

		}
		else
		{
			cout << "修改失败,查无此人!" << endl;
		}
	}
	//按任意键清屏
	system("pause");
	system("cls");
}

//查找职工
void WorkerManager::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;

			int ret = IsExist(id);
			if (ret != -1)
			{
				//找到职工
				cout << "查找成功!该职工信息如下:" << endl;
				this->m_EmpArray[ret]->showInfo();
			}
			else
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else if (select == 2)
		{
			//按姓名查
			string name;
			cout << "请输入查找的姓名:" << endl;
			cin >> name;

			//加入判断是否查到的标志
			bool flag = false;

			for (int i = 0; i < m_EmpNum; i++)
			{
				if (this->m_EmpArray[i]->m_Name == name)
				{
					cout << "查找成功,职工编号为: "
						<< this->m_EmpArray[i]->m_Id
						<< "号职工信息如下:" << endl;

					flag = true;

					//调用显示信息接口
					this->m_EmpArray[i]->showInfo();
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else
		{
			cout << "输入选项有误!" << endl;
		}
		{
		}
		//按任意键清屏
		system("pause");
		system("cls");
	}
}

//按照编号排序
void WorkerManager::Sort_Emp()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
		system("pause");
		system("cls");
	}
	else
	{
		cout << "请选择排序方式: " << endl;
		cout << "1、按职工号进行升序" << endl;
		cout << "2、按职工号进行降序" << endl;

		int select = 0;
		cin >> select;
		for (int i = 0; i < m_EmpNum; i++)
		{
			int minOrMax = i;//声明最小值或最大值下标
			for (int j = i + 1; j < this->m_EmpNum; j++)
			{
				if (select == 1)	//升序
				{
					if (this->m_EmpArray[minOrMax]->m_Id > this->m_EmpArray[j]->m_Id)
					{
						minOrMax = j;
					}
				}
				else    //降序
				{
					if (this->m_EmpArray[minOrMax]->m_Id < this->m_EmpArray[j]->m_Id)
					{
						minOrMax = j;
					}
				}
			}
			//判断一开始认定的最小值或最大值是不是计算的最小值或最大值,如果不是,交换数据
			if (i != minOrMax)
			{
				Worker* temp = this->m_EmpArray[i];
				this->m_EmpArray[i] = this->m_EmpArray[minOrMax];
				this->m_EmpArray[minOrMax] = temp;
			}
		}

		cout << "排序成功!排序后的结果为:" << endl;
		this->save();//排序后结果保存到文件中
		this->Show_Emp();
	}
}

//清空文件
void WorkerManager::Clean_File()
{
	cout << "确定清空?" << endl;
	cout << "1、确定" << endl;
	cout << "2、返回" << endl;

	int select = 0;
	cin >> select;

	if (select == 1)
	{
		//清空文件
		ofstream ofs(FILENAME, ios::trunc);//删除文件后重新创建
		ofs.close();

		if (this->m_EmpArray != NULL)
		{
			//删除堆区的每个职工对象
			for (int i = 0; i < this->m_EmpNum; i++)
			{
				delete this->m_EmpArray[i];
				this->m_EmpArray[i] = NULL;

			}

			//删除堆区数组指针
			delete[] this->m_EmpArray;
			this->m_EmpArray = NULL;
			this->m_EmpNum = 0;
			this->m_FileIsEmpty = true;
		}

		cout << "清空成功!" << endl;
	}
	system("pause");
	system("cls");
}

WorkerManager::~WorkerManager()
{
	if (this->m_EmpArray != NULL)
	{
		for (int i = 0; i < this->m_EmpNum; i++)
		{
			if (this->m_EmpArray[i] != NULL)
			{
				delete this->m_EmpArray[i];
			}
		}
		delete[] this->m_EmpArray;
		this->m_EmpArray = NULL;
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1537006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人脸表情识别系统项目完整实现详解——(二)使用SSD模型检测人脸

摘要&#xff1a;人脸检测是人脸表情识别系统中至关重要的一环&#xff0c;其准确性直接影响到整个系统的性能表现。本文介绍了使用SSD模型和OpenCV进行高效人脸检测的完整代码实现。我们详细介绍了SSD人脸检测器的工作原理&#xff0c;包括如何加载预训练的SSD模型&#xff0c…

【C++】1311. 分跳绳

问题&#xff1a;1311. 分跳绳 类型&#xff1a;基本运算、整数运算 题目描述&#xff1a; 学校新买来 m 根跳绳&#xff0c;每个班分 n 根&#xff0c;最多可以分给几个班的同学&#xff0c;还剩多少根&#xff1f;&#xff08;m≥n&#xff09;。 输入&#xff1a; 两个整…

【python绘图colorbar对齐】

[Toc]# 1、问题描述 python在绘图过程中&#xff0c;可能会出现colorbar高度与主图不匹配情况&#xff0c;需要进行调整&#xff0c;使得与主图高度对齐&#xff0c;使图像更美观。示例&#xff1a;colorbar位置高于主图 2、解决方法 通过调整shrink参数匹配对齐,pad调整x轴…

2024 年 AI 辅助研发趋势将更加强调智能化、自动化和个性化

目录 前言 AI辅助研发的技术进展 行业应用案例 医药行业 汽车行业 电子行业 面临的挑战与机遇 技术挑战 伦理问题 数据安全 机遇和解决方案 未来趋势预测 1. 深度融合AI与研发流程 2. 智能研发平台的崛起 3. 强化AI与人类智慧的融合 前言 当谈到人工智能&#xff…

台达变频通过Modbus转Profinet网关可以在环网冗余中使用

Modbus转Profinet网关&#xff08;如XD-MDPN100&#xff09;是一种能够实现Modbus协议与Profinet协议之间转换的设备。它支持Modbus RTU协议和Profinet协议还支持MRP环网冗余系统&#xff0c;,可以通过配置软件进行协议转换&#xff0c;使得原本只能使用Modbus协议的设备可以与…

禁止区域入侵检测

1. 物体检测 Object detection with deep learning and OpenCV In the first part of today’s post on object detection using deep learning we’ll discuss Single Shot Detectors and MobileNets. When combined together these methods can be used for super fast, real…

马蹄集oj赛(双周赛第二十三次)

目录 数列分割 小码哥的地毯 小码哥的三色墙 palace 高数考试 新全排列 黑白双煞 等差 数三角形 区间修改 相对马高 小码哥剪绳子 数列分割 难度:黄金 时间限制:1秒巴 占用内存:64 M 小码哥给你一个长度为n的数列&#xff0c;求将该数列分割成两个左右两个部分且两…

【CVTE 一面凉经Ⅰ】循环依赖如何解决

目录 一.&#x1f981; 开始前的废话二. &#x1f981; 什么是循环依赖&#xff1f;三. &#x1f981;Spring 容器解决循环依赖的原理是什么?五. &#x1f981; 三级缓存解决循环依赖的原理六. &#x1f981; 由有参构造方法注入属性的循环依赖如何解决&#xff1f;七.&#x…

【算法分析与设计】相同的树

题目 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 示例 1&#xff1a; 输入&#xff1a;p [1,2,3], q [1,2,3] 输出&#xff1a;true示…

IDEA创建Maven项目实现数据库表查询

在此之前&#xff0c;务必确保你本地环境已经正确配置了 JDK 和 Maven&#xff0c;并且相关的环境变量已经设置。这是你踏上编程之旅的第一步&#xff0c;也是你与代码交互的基础。可通过命令提示符中输入 java -version 和 mvn -v 命令&#xff0c;以验证你的 JDK 和 Maven 是…

多ip多进程代理的实现方法

目录 写在前面 一、背景 二、实现方法 1. 使用多线程处理代理请求 2. 使用多进程处理代理请求 3. 实现多IP代理 三、总结 写在前面 实现多IP多进程代理需要使用Python的多线程和多进程模块。本文将介绍如何使用这些模块来实现多IP多进程代理&#xff0c;并提供相关的代…

蓝桥杯练习——神秘咒语——axios

目标 完善 index.js 中的 TODO 部分&#xff0c;通过新增或者修改代码&#xff0c;完成以下目标&#xff1a; 点击钥匙 1 和钥匙 2 按钮时会通过 axios 发送请求&#xff0c;在发送请求时需要在请求头中添加 Authorization 字段携带 token&#xff0c;token 的值为 2b58f9a8-…

五.java数组

1.int [] arr{1,2,3} 2.lenarr.length; 3.数组内存执行原理 java程序编译后产生一个class文件然后提交到内存中的虚拟机JVM中去运行&#xff0c;java为了便于虚拟机运行程序就将虚拟机的这块内存划分为5个区域&#xff1a;方法区&#xff0c;栈&#xff0c;堆。。。 经典函数…

Matlab快捷键与函数

注释&#xff1a;注释对于代码的重要性我们就不做过多的解释了。不做注释的代码不是好代码。选中要注释的语句&#xff0c;按快捷键CtrlR,或者在命令行窗口上面的注释地方可以进行注释。当然也可以直接在语句前面“%”就可以&#xff08;注意&#xff1a;一定要用英文符号&…

BigDecimal类的使用,用于精确计算任意精度的数字

BigDecimal类 BigDecimal 是 Java 中用于精确表示任意精度的十进制数的类。在很多情况下,使用基本数据类型(如 double 或 float)进行浮点数计算可能会导致精度丢失或舍入错误。BigDecimal 提供了一种更精确的解决方案,可以处理需要高精度计算的场景,比如财务应用或科学计算…

29-3 哥斯拉安装使用

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、哥斯拉 (Godzilla) 介绍 哥斯拉是一个基于流量、HTTP全加密的webshell管理工具,具有以下特点: 内置了3种Payload以及6种加密器,6种支持脚本后缀,20个内置插件基于Java,可…

第十三届蓝桥杯省赛真题 Java B 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: 星期计算试题 B: 山试题 C: 字符统计试题 D: 最少刷题数试题 E \mathrm{E} E : 求阶乘试题 F : \mathrm{F}: F: 最大子矩阵试题 G: 数组切分试题 H: 回忆迷宫试题 I: 红绿灯试题 J 拉箱子 发现宝藏 前些天发现了一个巨牛的人工智能学习…

仿muduo库实现one thread one loop式并发服务器

文章目录 一、项目简介 二、项目整体认识 2、1 HTTP服务器 2、2 Reactor模型 三、预备知识 3、1 C11 中的 bind 3、2 简单的秒级定时任务实现 3、3 正则库的简单使用 3、4 通用类型any类型的实现 四、服务器功能模块划分与实现 4、1 Buffer模块 4、2 Socket模块 4、3 Channel模…

【TD3思路及代码】【自用笔记】

1 组成&#xff08;Target Network Delayed Training&#xff09; Actor网络&#xff1a;这个网络负责根据当前的状态输出动作值。在训练过程中&#xff0c;Actor网络会不断地学习和优化&#xff0c;以输出更合适的动作。Critic网络&#xff1a;TD3中有两个Critic网络&#xff…

解决:springboot项目访问hdfs文件提示guava版本不兼容

1、问题描述 版本说明&#xff1a;我用的hadoop版本&#xff1a;3.1.3 项目可以正常启动&#xff0c;但是调用访问hdfs的服务时候报错,报错消息如下&#xff1a;com.google.common.base.preconditions.checkArgument(ZL java/lang/String;Ljava/lang/Object:)V 原因分析&#x…