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;
}