1.文本文件(写文件)
文件类型分为两种:
- 文本文件:文件以文本的ASCII码形式存储在计算机中
- 二进制文件:文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它
操作文件的三大类
- ofstream:写操作
- ifstream:读操作
- fstream:读写操作
写文件:
- 包含头文件 #include <fstream>
- 创建流对象 ofstream ofs;
- 打开文件 ofs.open(”文件路径”,打开方式);
- 写数据 ofs<<”写入的数据”;
- 关闭文件 ofs.close();
文件打开方式 | 解释 |
---|---|
ios::in | 为读文件而打开文件 |
ios::out | 为写文件而打开文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 追加方式写文件 |
ios::trunc | 如果文件存在先删除,再创建 |
ios::binary | 二进制方式 |
文件打开方式可以配合使用,利用 | 操作符。如用二进制方式写文件 ios::binary | ios::out
void test01()
{// 1.文件操作必须包含头文件fsream// 2.创建流对象ofstream ofs;// 3.制定打开方式ofs.open("test.txt", ios::out);// 4.写<<内容ofs << "张三" << endl;ofs << "男" << endl;ofs << "18" << endl;// 5.关闭文件ofs.close();
}
2.文本文件(读文件)
读文件:
- 包含头文件 #include <fstream>
- 创建流对象 ifstream ifs;
- 打开文件并判断文件是否打卡成功 ifs.open(”文件路径”,打开方式);
- 读数据
- 关闭文件 ifs.close();
void test01()
{// 1.创建流对象ifstream ifs;// 2.制定打开方式ifs.open("test.txt", ios::in);if (!ifs.is_open()) // 判断文件是否打开成功{cout << "文件打开失败" << endl;return;}// 3.读数据char buf[1024] = {0};while(ifs >> buf){cout << buf << endl;}// 一行一行读char buf[1024] = {0};while(ifs.getline(buf, sizeof(buf))){cout << buf << endl;}// 一行一行读string buf;while(getline(ifs, buf)){cout << buf << endl;}// 一个一个读char c;while((c = ifs.get()) != EOF){//cout << c;//}// 4.关闭文件ifs.close();
}
3.二进制文件(写文件)
- 二进制方式写文件主要利用流对象调用成员write
- 函数原型:ostream& write(const char* buffer,int len);
class Person
{
public:char m_Name[64];int m_Age;
};
void test01()
{// 1.包含头文件// 2.创建流对象ofstream ofs;// 3.打开文件ofs.open("person.txt", ios::out | ios::binary);// 4.写文件Person p = {"张三", 18};ofs.write((const char *)&p, sizeof(Person));// 5.关闭文件ofs.close();
}
4.二进制文件(写文件)
- 二进制方式读文件主要利用流对象调用成员函数read
- 函数原型:istream& read(char *buffer, int len);
class Person
{
public:char m_Name[64];int m_Age;
};
void test01()
{// 1.包含头文件// 2.创建流对象ifstream ifs;// 3.打开文件 判断文件是否打开成功ifs.open("person.txt", ios::in | ios::binary);if(!ifs.is_open()){cout << "文件打开失败" << endl;}// 4.写文件Person p;ifs.read((char *)&p, sizeof(Person));cout << p.m_Name << p.m_Age << endl;// 5.关闭文件ifs.close();
}
5.职工管理系统
公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责
- 普通员工职责:完成经理交给的任务
- 经理职责:完成老板交给的任务,并下发任务给员工
- 老板职责:管理公司所有事务
管理系统重需要实现的功能如下:
- 退出管理程序:退出当前管理系统
- 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
- 显示职工信息:显示公司内部所有职工的信息
- 删除离职职工:按照编号删除指定的职工
- 修改职工信息:按照编号修改职工个人信息
- 查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
- 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
- 清空所有文档:清空文件中记录的所有职工信息(清空前需要再次确认,防止误删)
第一步:实例化管理者对象
创建总执行文件 main.cpp,workerManager.h 和 workerManager.cpp 三个文件。
int main()
{// 实例化管理者对象WorkerManager wm;system("pause");return 0;
}
在workerManager.h中设置每一个用到的函数声明:
#pragma once
#include <iostream>class WorkerManager
{
public:WorkerManager(); ~WorkerManager();
};
在workerManager.cpp 里写每一个函数的具体实现:
#include <workerManager.h>// 构造函数
WorkerManager::WorkerManager()
{}// 析构函数
WorkerManager::~WorkerManager()
{}
第二步:创建抽象的员工类别,以及三个派生类(普通员工、经理、老板)
创建 worker.h,设置抽象的员工类别作为基类
#pragma once
#include <iostream>
#include <string>
using namespace std;class Worker
{
public:// 显示个人信息virtual void showInfor() = 0;// 获取岗位名称virtual string showDepartment() = 0;int m_id;string m_name;int m_deptid;
};
在基类基础上创建三种子类,表示三种员工(普通员工、经理、老板)
普通员工 employee.h 每个函数的声明:
#pragma once
#include <iostream>
#include <string>
#include <worker.h>
using namespace std;class Employee:public Worker
{
public:Employee(int id, string name, int deptid);virtual void showInfor();virtual string showDepartment();
};
普通员工 employee.cpp 每个函数的具体实现:
#include <employee.h>Employee::Employee(int id, string name, int deptid)
{m_name = name;m_id = id;m_deptid = deptid;
}
void Employee::showInfor()
{cout << "职工编号: " << this->m_id;cout << "\t职工姓名: " << this->m_name;cout << "\t岗位: " << this->showDepartment();cout << "\t岗位职责: 完成经理交代的任务" << endl;
}
string Employee::showDepartment()
{return string("员工");
}
之后再以同样的方式创建Manage.h , Mangae.cpp, Boss.h, Boss.cpp。
第三步:显示菜单
在workerManager.h中加入:
// 展示菜单
void show_Menu();
在workerManager.cpp中加入:
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;
}
第四步:选择为0时退出系统
在workerManager.h中加入声明:
// 退出
void ExitSystem();
在workerManager.cpp中加入具体实现:
void WorkerManager::ExitSystem()
{cout << "欢迎下次使用" << endl;system("pause");exit(0);
}
第五步:选择为1时添加职工
用户在批量创建时,可能会创建不同种类的职工。如果想将所有不同种类的员工都收入到一个数组中,可以将所有员工的指针维护到一个数组里。如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用Worker **的指针维护。
在workerManager.h中加入声明:
// 记录职工人数
int m_EmpNum;
// 记录职工数组的指针
Worker **m_EmpArray;
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 deptid;cout << "请输入第" << i+1 << "位职工的编号:" << endl;cin >> id;cout << "请输入第" << i+1 << "位职工的姓名:" << endl;cin >> name;cout << "请选择第" << i+1 << "位职工的岗位(1-普通员工, 2-经理, 3-老板):" << endl;cin >> deptid;Worker *worker = NULL;switch(deptid){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->is_Empty = false;// 保存数据到文件中this->save();cout << "成功添加" << addNum << "位员工!" << endl;}else{cout << "输入有误" << endl;}system("pause");system("cls");
}
第六步:将信息保存到文本文件中
在workerManager.h中加入声明:
void save();
在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();
}
第七步:选择为2时显示职工
在workerManager.h中加入声明:
// 判断文件是否为空(之前是否已经有存入的数据)bool is_Empty;// 如果有,统计文件中的人数int get_EmpNum();// 初始化m_EmpArray数组void init_Emp();// 显示职工void show_Emp();
在workerManager.cpp中加入具体实现:(在构造函数中加入三种初始情况,没有初始文件时,有出示文件但没有数据时,有文件且有数据时)对于前两种情况,在构造函数㕜将this->m_EmpNum设为0,this->m_EmpArray设为空。
WorkerManager::WorkerManager()
{// 文件不存在时ifstream ifs;ifs.open(FILENAME, ios::in);if(!ifs.is_open()){cout << "初始员工文件不存在" << endl;// 初始化属性this->m_EmpNum = 0;this->m_EmpArray = NULL;this->is_Empty = true; ifs.close(); return;}// 文件存在且数据为空char ch;ifs >> ch;if(ifs.eof()){// 代表文件为空cout << "初始员工文件为空" << endl;// 初始化属性this->m_EmpNum = 0;this->m_EmpArray = NULL;this->is_Empty = true; ifs.close(); return;}// 文件存在且有数据this->is_Empty = false;int num = this->get_EmpNum();cout << "已存储" << num << "位职工信息" << endl;this->m_EmpNum = num;this->m_EmpArray = new Worker*[num];this->init_Emp();}
对于第三种情况,有文件且有数据,首先求得文件中数据的长度,再将数据初始化到m_EmpArray中:
int WorkerManager::get_EmpNum()
{ifstream ifs;ifs.open(FILENAME, ios::in);int num = 0;int id;string name;int deptid;while(ifs >> id && ifs >> name && ifs >> deptid){num++;}return num;
}void WorkerManager::init_Emp()
{ifstream ifs;ifs.open(FILENAME, ios::in);int id;string name;int deptid;int index = 0;while(ifs >> id && ifs >> name && ifs >> deptid){Worker *worker = NULL;if (deptid == 1){worker = new Employee(id, name, deptid);}else if (deptid == 2){worker = new Manager(id, name, deptid);}else if (deptid == 3){worker = new Boss(id, name, deptid);}this->m_EmpArray[index] = worker;index++;}ifs.close();
}
显示所有职工信息:
void WorkerManager::show_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{for(int i=0; i<this->m_EmpNum; i++){this->m_EmpArray[i]->showInfor();}}system("pause");system("cls");
}
第八步:选择为3时删除职工
在workerManager.h中加入声明:
void delete_Emp();int is_exist(int id);
先判断该职工是否存在,存在则返回下标,不存在返回-1:
// 判断职工是否存在,不存在返回-1
int WorkerManager::is_exist(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::delete_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{cout << "请输入需要删除的职工的ID:" << endl;int id;cin >> id;int index = this->is_exist(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_EmpNum--;// 将文件中数据同步更新this->save();cout << "删除成功" << endl;}else{cout << "删除失败,该职工不存在" << endl;}}system("pause");system("cls");
}
第九步:选择为4时修改信息
在workerManager.h中加入声明:
void change_Emp();
在workerManager.cpp中加入具体实现,先判断传入的这个人的id是否存在,再根据新建数据的格式修改信息:
void WorkerManager::change_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{cout << "请输入需要修改信息的职工的ID:" << endl;int id;cin >> id;int index = this->is_exist(id);if(index != -1){cout << "查到系统中第" << index+1 << "号职工" << endl;delete this->m_EmpArray[index];int id;string name;int deptid;cout << "请输入新的职工编号:" << endl;cin >> id;cout << "请输入新的职工姓名:" << endl;cin >> name;cout << "请输入新的职位编号:" << endl;cin >> deptid;Worker *worker = NULL;switch(deptid){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[index] = worker;cout << "修改成功" << endl;this->save(); }else{cout << "修改失败,该职工不存在" << endl;}}system("pause");system("cls");
}
第十步:选择为5时查找员工
在workerManager.h中加入声明:
void Find_Emp();
在workerManager.cpp中加入具体实现(两种查找方式,第一种按编号查找,先判断此人是否存在,存在的返回数组指针的下标;第二种按姓名查找,遍历指针数组对应的m_name):
void WorkerManager::Find_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{cout << "请输入查找方式(1-按编号查找,2-按姓名查找):" << endl;int select = 0;cin >> select;if(select == 1){cout << "请输入需要查找的职工的ID:" << endl;int id;cin >> id;int index = this->is_exist(id);if(index != -1){cout << "查找成功,该职工信息如下:" << endl;this->m_EmpArray[index]->showInfor();}else{cout << "查找失败,该职工不存在" << endl;}}else if(select == 2){cout << "请输入需要查找的职工的姓名:" << endl;bool tag = false;string name;cin >> name;for(int i=0; i<this->m_EmpNum; i++){if(this->m_EmpArray[i]->m_name == name){tag = true;cout << "查找成功,该职工信息如下:" << endl;this->m_EmpArray[i]->showInfor();}}if(tag == false){cout << "查找失败,该职工不存在" << endl;}}else{cout << "输入错误" << endl;}}system("pause");system("cls");
}
第11步:选择为6时排序
在workerManager.h中加入声明:
void sort_Emp();
在workerManager.cpp中加入具体实现,有两种排序方式,按照职工编号升序或降序。用双重循环找到最小的职工对应的m_id,同时按照升序/降序排列。外层循环是确定最大值/最小值所放的位置,内层循环是寻找未排序数组中的最小值:
void WorkerManager::sort_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;system("pause");system("cls");}else{cout << "请选择排序方式(1-按照职工编号升序排列,2-按照职工编号降序排列):" << endl;int select = 0;cin >> select;for(int i=0; i<this->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();}
}
第12步:选择为7时清除信息
在workerManager.h中加入声明:
void deleteall();
在workerManager.cpp中加入具体实现,在删除之前先进行确认:
void WorkerManager::deleteall()
{cout << "确认清空? (1-yes,2-no)" << endl;int select = 0;cin >> select;if(select == 1){ofstream ofs;ofs.open(FILENAME, ios::trunc); // 删除文件后重新创建ofs.close();// 删除堆区的每个职工对象和数组指针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;this->m_EmpNum = 0;this->is_Empty = true;cout << "清空完毕" << endl;}}system("pause");system("cls");
}
根据这里的实现,进一步修改WorkerManager的析构函数:
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;}
}
最后:主函数设置分支结构
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: // 增加职工wm.Add_Emp();break;case 2: // 显示职工wm.show_Emp();break;case 3: // 删除职工wm.delete_Emp();break;case 4: // 修改职工wm.change_Emp();break;case 5: // 查找职工wm.Find_Emp();break;case 6: // 排序职工wm.sort_Emp();break;case 7: // 清空职工wm.deleteall();break; default:system("cls"); // 清屏break;}}system("pause");return 0;
}