昨天身体不舒服,所以提前把这周的摆烂份额用完了,今天就成了不能摆烂的周日了。
今天把前天的项目进行了(自以为的)优化,大致改了以下几点:
- 把容器从数组改成了vector,改的原因在于数组需要提前设定好大小,如果超出需要手动申请新的数组,然后把旧的数组拷贝进去,自认为不是很方便。使用vector可以自动帮忙申请和拷贝,所以选择了这个。并且在释放内存时,vector会自己主动delete掉,但前提是里面的元素不是指针类的,如果是指针类的,还是需要自己手动释放。
- 尝试了新的排序算法。教程中使用的是选择排序,自己重写了一个快排函数。
- 重点修改了增加员工函数。因为在测试中发现,如果输入的变量和设定变量的类型不同依然会输出“添加成功”,也就是说没有进行提示和判断,所以在增加函数那里用循环添加了判断,必须要说,这个循环还真挺有东西的。
while (!(cin >> name)) { cout << "输入数据类型错误,请重新输入!\t"; cin.clear(); while (cin.get() != '\n') continue; }
这个是我尝试过后对的代码,先放上来。我本来想的是判断worker对象是否为nullptr,如果是nullptr就循环写,也就是说用while(worker != nullptr)来写循环,但出现的问题是,当我输入错误时它会无限陷入循环,并且不给我输入的机会,这个原因我不是很理解,但肯定是有问题的(可能是系统会自动读取某个字符?因为我cout << "输入数据类型错误,请重新输入!"<<endl;本来是这么写的,可能最后一个endl被读为我的重写,然后不断的陷入循环,只是我的猜测啊),然后我就重新在网上搜了一下解决这类问题的答案,不出意外地粗心地写成了这样:
while (!(cin >> name)) { cout << "输入数据类型错误,请重新输入!"<<endl; cin.clear(); while (cin.get() != '\n') continue;//目的是清空cin的内存 }
出现了还我之前一样的死循环,仔细比较才发现是endl的问题(这也是为什么我猜测出现死循环的原因是不断将最后的endl读为我新的输入的原因)
-
和上一个练习一样,我将工号认定为唯一识别员工的关键词,理由就是大家叫一样名字这事儿我控制不了,但控制工号不一样还是easy的,所以在添加新员工时增加了判断是否已经存在该工号的功能。本来我是想用一个set来记录所有现有的工号的,但是发现在删除时,需要确定待删除员工在vector中的位置,理所应当地就想用map去替换,但是当删除完了以后,被删除的那个序号后面的所有序号都需要更新,好像还不如用IsExist()函数来判断一下是否已存在这个id了(肯定有好的解决方法嗷,比如更换一下存放员工信息的容器?目前没有想到==)。
其实也没有优化太多,但把整个项目框架重新梳理了一遍,自己把每一块需要完成的工作都认真想了一遍,进行了我以为的优化,所以对于这个练习就先告一段落啦!最后放上优化版的代码(部分)
//头文件部分
********************************************************************************
//workManager.h
********************************************************************************
#pragma once
#define FILENAME "empFile.txt"
#include<iostream>
#include<fstream>
#include<vector>
#include"worker.h"
#include"employee.h"
#include"manager.h"
#include"boss.h"
using namespace std;
class WorkerManager {
public:
int m_EmpNum;//存储员工人数
//Worker** m_EmpArray;//存储员工信息
vector<Worker*> m_EmpArray;
//bool m_FileIsEmpty;//判断是否文件是否存在
//我觉得判断m_EmpArray是否为空就可以说明是否有信息存在,所以没有必要单独再给一个变量
WorkerManager();
//展示菜单
void Show_Menu();
//退出系统
void Exit_System();
//增加职工
void Add_Emp();
//保存文件
void save();
//读取文件中人数
int get_EmpNum();
//初始化堆区数据
void init_Emp();
//显示职工
void Show_Emp();
//删除职工
void Del_Emp();
//判断职工是否存在
int IsExist(int id);
//修改职工
void Mod_Emp();
//查找职工
void Find_Emp();
//按照职工编号排序
void Sort_Emp();
void quickSort(vector<Worker*>& a, int low, int high);
//清空文档
void Clean_File();
~WorkerManager();
};
********************************************************************************
//主函数部分
********************************************************************************
//workManager.cpp
********************************************************************************
#include"workerManager.h"
#include<vector>
WorkerManager::WorkerManager() {
//根据文件的情况,将构造函数分为三种情况进行讨论
ifstream ifs;
ifs.open(FILENAME, ios::in);
//文件不存在或文件存在且空
char ch;
ifs >> ch;//读走文件的尾标志//读走最后一个尾标志是因为输入流不能再读入数据才发现已经到文件结尾了,这时才给流设定文件结尾的标志,此时调用eof才为真
if (ifs.eof()) {
cout << "文件为空" << endl;
this->m_EmpNum = 0;
this->m_EmpArray = {};
ifs.close();
return;
}
//文件存在且不为空
int num = this->get_EmpNum();
cout << "职工人数为:" << num << endl;
this->m_EmpNum = num;
//开辟空间
this->m_EmpArray = {};
//将文件中的数据存放到数组中
this->init_Emp();
for (int i = 0; i < this->m_EmpNum; i++) {
cout << "职工编号:" << this->m_EmpArray[i]->m_Id
<< "\t 职工姓名:" << this->m_EmpArray[i]->m_Name
<< "\t 部门编号:" << this->m_EmpArray[i]->m_Did << endl;
}
cout << "WorkerManger构造成功!" << endl;
}
void WorkerManager::init_Emp() {
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id;
string name;
int did;
while (ifs >> id && ifs >> name && ifs >> did) {
Worker* worker = nullptr;
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.push_back(worker);
}
ifs.close();
}
void WorkerManager::Show_Menu() {
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;
}
void WorkerManager::Add_Emp() {
cout << "请输入要添加的人数" << endl;
int addNum = 0;
cin >> addNum;
if (addNum > 0) {
for (int i = 0; i < addNum; i++) {
Worker* worker = nullptr;
int id;
string name;
int did;
cout << "请输入第" << i + 1 << "个新职工的编号," << endl;
while(! (cin>>id) || this->IsExist(id) != -1) {
if (this->IsExist(id) != -1)
cout << "该员工号已存在,请重新输入!";
else
cout << "输入数据类型错误,请重新输入!\t";
cin.clear();
while (cin.get() != '\n')
continue;
}
cout << "请输入第" << i + 1 << "个新职工的姓名," << endl;
while (!(cin >> name)) {
cout << "输入数据类型错误,请重新输入!\t";
cin.clear();
while (cin.get() != '\n')
continue;
}//但其实好像这个没什么用,因为名字不仅仅可以是中文
cout << "请选择该职工岗位:" << endl;
cout << "1、普通职工" << endl;
cout << "2、经理" << endl;
cout << "3、老板" << endl;
while (!(cin >> did)) {
cout << "输入数据类型错误,请重新输入!\t";
cin.clear();
while (cin.get() != '\n')
continue;
}
switch (did) {
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;
}
this->m_EmpArray.push_back(worker);
}
this->m_EmpNum += addNum;
cout << "成功添加" << addNum << "名新职工!" << endl;
//保存数据到文件中
this->save();
}
else {
cout << "输入有误!" << endl;
}
system("pause");
system("cls");
}
void WorkerManager::save() {
ofstream ofs;
ofs.open(FILENAME, ios::out);//写文件,且是覆盖文件的写法,如果要续写就要用ios::app
//用循环将每个人的信息写入文件
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_Did <<endl;
}
ofs.close();
}
int WorkerManager::get_EmpNum() {
ifstream ifs;
ifs.open(FILENAME, ios::in);
int num = 0;//统计人数
int id;
string name;
int did;
while (ifs >> id && ifs >> name && ifs >> did) {
num++;
}
return num;
}
void WorkerManager::Exit_System() {
cout << "欢迎下次使用!" << endl;
system("pause");
exit(0);
}
void WorkerManager::Show_Emp() {
if (this->m_EmpArray.empty()) {
cout << "文件不存在或记录为空" << endl;
}
else {
for (int i = 0; i < this->m_EmpNum; i++) {
this->m_EmpArray[i]->show_Info();
}
}
system("pause");
system("cls");
}
void WorkerManager::Del_Emp() {
if (this->m_EmpArray.empty()) {
cout << "文件不存在或记录为空!" << endl;
}
else {
cout << "请输入想要删除职工编号:" << endl;
int id = 0;
cin >> id;
int index = this->IsExist(id);
if (index != -1) {
for (int i = index; i < this->m_EmpNum - 1; i++) {
this->m_EmpArray[i] = this->m_EmpArray[i + 1];
}
this->m_EmpArray.pop_back();
this->m_EmpNum--;
this->save();//保存更新文件
cout << "删除成功!" << endl;
}
else {
cout << "删除失败,未找到该职工!" << endl;
}
}
system("pause");
system("cls");
}
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_EmpArray.empty()) {
cout << "文件不存在或记录为空!" << endl;
}
else {
cout << "请输入修改职工的编号:" << endl;
int id;
cin >> id;
int index = this->IsExist(id);
if (index != -1) {
delete this->m_EmpArray[index];
int n_id = 0;
string n_name;
int n_did = 0;
cout << "查到:" << id << "号职工,请输入新职工号:" << endl;
cin >> n_id;
cout << "请输入新姓名:" << endl;
cin >> n_name;
cout << "请输入新岗位:" << endl;
cout << "1、普通职工" << endl;
cout << "2、经理" << endl;
cout << "3、老板" << endl;
cin >> n_did;
Worker* worker = nullptr;
switch (n_did) {
case 1 :
worker = new Employee(n_id, n_name, n_did);
break;
case 2 :
worker = new Manager(n_id, n_name, n_did);
break;
case 3 :
worker = new Boss(n_id, n_name, n_did);
break;
default:
break;
}
this->m_EmpArray[index] = worker;
cout << "修改成功!" << endl;
this->save();
}
else {
cout << "修改失败,查无此人!" << endl;
}
}
system("pause");
system("cls");
}
void WorkerManager::Find_Emp() {
if (this->m_EmpArray.empty()) {
cout << "文件不存在或记录为空!" << endl;
}
else {
cout << "请输入查找的方式:" << endl;
cout << "1、按照职工的编号查找" << endl;
cout << "2、按照职工的姓名查找" << endl;
int select = 0;
cin >> select;
if (select == 1) {
int id = 0;
cout << "请输入查找的职工编号:" << endl;
cin >> id;
int ret = this->IsExist(id);
if (ret != -1) {
cout << "查找成功!该职工信息如下:" << endl;
this->m_EmpArray[ret]->show_Info();
}
else {
cout << "查找失败,查无此人!" << endl;
}
}
else if (select == 2) {
string name;
cout << "请输入查找的职工姓名:" << endl;
cin >> name;
bool flag = false;//判断是否查到
for (int i = 0; i < this->m_EmpNum; i++) {
if (this->m_EmpArray[i]->m_Name == name) {
cout << "查找成功,职工编号为:"
<< this->m_EmpArray[i]->m_Id
<< "号职工信息如下:" << endl;
this->m_EmpArray[i]->show_Info();
flag = true;
}
}
if (flag == false) {
cout << "查找失败,查无此人!" << endl;
}
}
else {
cout << "输入选项有误,请重新输入!" << endl;
}
}
system("pause");
system("cls");
}
void WorkerManager::Sort_Emp() {
if (this->m_EmpArray.empty()) {
cout << "文件不存在或记录为空!" << endl;
system("pause");
system("cls");
}
else {
int select = 0;
cout << "请选择排序方式:" << endl;
cout << "1、按职工号进行升序" << endl;
cout << "2、按职工号进行降序" << endl;
cin >> select;
quickSort(this->m_EmpArray, 0, this->m_EmpNum - 1);
if (select == 2)
reverse(this->m_EmpArray.begin(), this->m_EmpArray.end());
cout << "排序成功!排序后的结果为:" << endl;
this->save();
this->Show_Emp();
}
}
void WorkerManager::quickSort(vector<Worker*>& a, int low, int high) {
if (low >= high) {
return;
}
int first = low;
int last = high;
int key = first;
while (first < last) {
while (first < last && a[last]->m_Id > a[key]->m_Id) {
last--;
}
if (first < last) {
a[first++] = a[last];
}
while (first < last && a[first]->m_Id <= a[key]->m_Id) {
first++;
}
if (first < last) {
a[last--] = a[first];
}
}
a[first] = a[key];
quickSort(a, low, first - 1);
quickSort(a, first + 1, high);
}
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();
//判断一下堆区数组是否为空
//如果不为空的话,需要对堆区进行删除和置空
//也就是解决内存泄露问题
while (! this->m_EmpArray.empty()) {
delete this->m_EmpArray.back();
this->m_EmpArray.pop_back();
}
this->m_EmpNum = 0;
cout << "清空成功!" << endl;
}
system("pause");
system("cls");
}
WorkerManager::~WorkerManager() {
while (! this->m_EmpArray.empty()) {
delete this->m_EmpArray.back();
this->m_EmpArray.pop_back();
}
cout << "WorkerManager析构成功!" << endl;
}