鱼C论坛

 找回密码
 立即注册
查看: 815|回复: 6

[已解决]关于多态的职工管理,数据前移遇到的一点问题

[复制链接]
发表于 2022-2-16 15:58:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 1094570635 于 2022-2-18 14:33 编辑

创建了一个WorkerManager类头文件
class WorkerManager
{
public:

        //构造函数
        WorkerManager();

        //展示菜单
        void Show_Menu();

        //退出系统
        void ExitSystem();


        //记录职工人数
        int m_EmpNum;

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


        //添加职工
        void Add_Emo();

        //保存文件
        void save();

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

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

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

        //显示职工
        void Show_Emp();

        //删除职工
        void Del_Emp();

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

        //析构函数
        ~WorkerManager();





};
cpp中写入对应的类WorkerManager函数数据
#include"workerManager.h"

WorkerManager::WorkerManager()
{
        //1、文件不存在
        ifstream ifs;
        ifs.open(FILENAME, ios::in); //读文件

        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;

                }*/




       
               


        ////初始化属性
        //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;

}

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

}



//添加职工
void  WorkerManager::Add_Emo()
{
        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++;

        }
        ifs.close();
        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;
}



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

        }


}
不明白为什么在数据前移操作时for (int i = index; i <this->m_EmpNum-1;i++ )
                        {
                                //数据前移
                                this->m_EmpArray[i] = this->m_EmpArray[i + 1];

                        }
m_EmpNum要减1操作,以及当指针数组长度为1时,只有一个元素要怎么前移,执行删除操作,以及删除最后一个数组下标时,怎么执行前移操作,删除对应数组元素的指针
最佳答案
2022-2-16 18:43:41
本帖最后由 jhq999 于 2022-2-16 18:52 编辑
1094570635 发表于 2022-2-16 18:39
可不可以理解为只有一个元素要前移,也不执行for (int i = index; i m_EmpNum-1;i++ )这个循环语句,对 ...


数据没有动,没有置0,只是因为m_EmpNum减一,改变的是可写范围
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-2-16 17:41:53 | 显示全部楼层
本帖最后由 jhq999 于 2022-2-16 18:14 编辑

先回答第一个问题,如果不前移,加入新元素时,怎么放,
如果直接放后面,假如这个程序运行时间非常长,新数据加入非常多,删除的元素空间不能利用,得考虑存储空间问题;
如果寻找已经删除的空间,就得重新遍历一遍,放入新数据短时间内降低效率,而且还会增加代码量,还不如在删除时在删除处前移。

而且如果删除不前移添加新元素时把原来的拷贝到重新分配 int newSize = this->m_EmpNum + addNum大小的空间会出错
比如原来this->m_EmpNum=6,空间是6 ,中间删除一个this->m_EmpNum=5,加入新元素时this->m_EmpNum=6 ,空间6,拷贝进去,添加新元素会把最后一个元素覆盖
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-16 17:51:09 | 显示全部楼层
本帖最后由 jhq999 于 2022-2-16 17:55 编辑

只有一个元素要怎么前移?
前移后this->m_EmpNum已经等于0,就已经说明是空,就和删除文件一样,只是把文件空间设置为“可写”而已。


删除最后一个数组下标时,怎么执行前移操作,
for (int i = index; i <this->m_EmpNum-1;i++ )这个循环根本不执行,m_EmpNum减一,然后和上面一样把最后一个“设置为可写”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-16 18:39:18 | 显示全部楼层
jhq999 发表于 2022-2-16 17:51
只有一个元素要怎么前移?
前移后this->m_EmpNum已经等于0,就已经说明是空,就和删除文件一样,只是把文 ...


可不可以理解为只有一个元素要前移,也不执行for (int i = index; i <this->m_EmpNum-1;i++ )这个循环语句,对应元素数组下标0的元素变成了NULL?然后删除最后一个数组下标时,可读写数组长度-1,被删除最后一个数组下标设置为“可写”,里面的数组元素变成NULL?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-16 18:43:41 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jhq999 于 2022-2-16 18:52 编辑
1094570635 发表于 2022-2-16 18:39
可不可以理解为只有一个元素要前移,也不执行for (int i = index; i m_EmpNum-1;i++ )这个循环语句,对 ...


数据没有动,没有置0,只是因为m_EmpNum减一,改变的是可写范围
无标题.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-16 19:06:35 | 显示全部楼层
本帖最后由 1094570635 于 2022-2-16 19:18 编辑
jhq999 发表于 2022-2-16 18:43
数据没有动,没有置0,只是因为m_EmpNum减一,改变的是可写范围


理解了,就是假如要删除元素4,系统就只会读取下标到3元素位置是吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-16 20:45:51 | 显示全部楼层
1094570635 发表于 2022-2-16 19:06
理解了,就是假如要删除元素4,系统就只会读取下标到3元素位置是吧

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-5 11:10

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表