系列文章目录
【C++基础】面向对象方法(一)
【C++基础】面向对象方法(二)
【C++基础】面向对象方法(三)
【C++基础】面向对象方法(四)
【C++基础】面向对象方法(五)
【C++基础】面向对象方法(六)
【C++基础】面向对象方法(七)
【C++基础】面向对象方法(八)
【C++基础】面向对象方法(九)
【C++基础】面向对象方法(十)
【C++基础】面向对象方法(十一)
一、文件的随机读写
有些情况下,需要从文件某个位置开始进行读/写操作。例如,要更改一名学生的信息,就需要先将文件指针定位到正确位置,再进行写操作;要查询某名学生的信息,也需要先将文件指针定位到正确位置,再进行读操作。与顺序读/写相对应,这种非顺序读/写称为随机读/写。
seekg()函数和seekp()函数分别用于定位输入文件流对象和输出文件流对象的文件指针,函数原型分别为:
istream& seekg(long offset,seek_dir origin=ios::beg);
ostream& seekp(long offset,seek_dir origin=ios::beg);
函数的功能是文件指针从参照位置origin开始移动offset个字节。
参数offset是长整型,表示文件指针相对参照位置偏移的字节数,取值为正表示向后移动文件指针,取值为负则表示向前移动文件指针。
参数origin则为参照位置,seek_dir是系统定义的枚举类型,有以下3个枚举常量:ios::beg:文件首 ios::cur:文件指针当前位置 ios::end:文件尾
假设infile是ifstream类的对象,outfile是ofstream类的对象,将infile的文件指针从当前位置向前移5个字节:
infile.seekg(-5,ios::cur);
将outfile的文件指针从文件首向后移5个字节:
outfile.seekp(5,ios::beg);
在进行文件的随机读/写时,还可使用tellg()和tellp()函数获取文件指针的当前位置。tellg()是输入文件流对象的成员函数,tellp()是输出文件流
对象的成员函数,它们的函数原型分别为:
streampos tellg();
streampos tellp();
提示:对于fstream对象,则既可使用seekg()和tellg()函数,也可使用seekp()和tellp()函数,结果完全一样。
例1:将3名学生的学号、姓名和成绩写入二进制文件studentinfo.dat中,再将第2名学生的成绩改为627。从文件中读取第m(m的值由用户从键盘输入)名学生的信息并将其输出到屏幕上。
代码如下(示例):
#include<iostream>
#include<fstream>
using namespace std;
struct Student //Student结构体类型定义
{
char num[10];
char name[20];
int score;
};
int main()
{
Student stu[3] =
{
{"1210101","张三",618},
{"1210102","李四",625},
{"1210103","王五",612}
};
int i,m;
fstream outfile("studentinfo1.dat", ios::binary | ios::out);
if (!outfile.is_open()) //判断文件打开操作是否成功
{
cout << "打开文件studentinfo.dat失败!" << endl;
return 0;
}
for (i = 0; i < 3; i++) //将第i名学生的数据写入文件
outfile.write((char*)&stu[i], sizeof(Student));
outfile.close(); //关闭文件
fstream myfile;
myfile.open("studentinfo1.dat",ios::binary|ios::in|ios::out);
if (!myfile.is_open())
{
cout << "打开文件studentinfo.dat失败!" << endl;
return 0;
}
stu[1].score = 627;
//将文件指针定位到第2名学生
myfile.seekp(1 * sizeof(Student), ios::beg);
//用新数据覆盖原来文件中保存的第2名学生的数据
myfile.write((char*)&stu[1], sizeof(Student));
cout << "请输入待查询的学生序号(1-3):";
cin >> m;
if (m < 1 || m>3)
{
cout << "学生不存在!" << endl;
return 0;
}
//将文件指针定位到第m名学生数据开始的位置
myfile.seekg((m - 1) * sizeof(Student), ios::beg);
//将指定学生的数据读入到内存中
myfile.read((char*)&stu[m - 1], sizeof(Student));
cout << "第" << m << "名学生的学号、姓名和成绩:"
<< stu[m - 1].num << ","
<< stu[m - 1].name << ","
<< stu[m - 1].score << endl;
myfile.close(); //关闭文件
return 0;
}
二、用户自定义数据类型的输入输出
C++输入/输出流类库中对提取运算符">>“和插入运算符”<<“进行了多次重载,它们能够实现多种内部类型数据的输入输出操作。例如:输入流对象in和输出流对象out调用重载运算符函数实现数据的输入/输出。 int x; in>>x;等价于in.operator>>(x); out<<x;等价于out.operator<<(x);
如果对用户自定义类型的数据也希望能直接使用”>>“和”<<"进行输入/输出,必须由编程人员对它们进行重载。
重载的函数形式为:
istream& operator>>(istream&,自定义类型&);
ostream& operator<<(ostream&,自定义类型&);
代码如下(示例):
#include<iostream>
#include<fstream>
using namespace std;
struct Student
{
char num[10];
char name[20];
int score;
};
//">>"运算符重载函数
istream& operator>>(istream& in, Student& stu)
{
in >> stu.num >> stu.name >> stu.score;
return in;
}
//"<<"运算符重载函数
ostream& operator<<(ostream& out, Student& stu)
{
out << stu.num << ' ' << stu.name << ' ' << stu.score << endl;
return out;
}
int main()
{
Student stu[3] =
{
{"1210101","张三",618},
{"1210102","李四",625},
{"1210103","王五",612}
};
int i;
fstream outfile("studentinfo.txt", ios::out);
if (!outfile.is_open()) //判断文件打开操作是否成功
{
cout << "打开文件失败!" << endl;
return 0;
}
for (i = 0; i < 3; i++)
outfile << stu[i];//调用operator<<(outfile,stu[i]);
outfile.close();//关闭文件
fstream infile("studentinfo.txt", ios::in);
if(!infile.is_open()) //判断文件打开操作是否成功
{
cout << "打开文件失败!" << endl;
return 0;
}
//将第i名学生的数据读入到内存中
for (i = 0; i < 3; i++)
infile >> stu[i];
for (i = 0; i < 3; i++)
{
cout << "第" << i + 1 << "名学生的学号、姓名和成绩:";
cout << stu[i];//调用operator<<(cout,stu[i]);
}
infile.close();//关闭文件
return 0;
}
/*提示:还可以为文件流单独编写重载函数,用二进制文件存储学生信息。*/
fstream& operator<<(fstream& outfile, Student& stu)
{
outfile.write((char*)&stu,sizeof(stu));
return outfile;
}
fstream& operator<<(fstream& infile, Student& stu)
{
infile.write((char*)&stu, sizeof(stu));
return infile;
}
总结
以上就是今天记录的内容,本文仅仅简单介绍了文件的随机读写、用户自定义数据类型的输入输出。