《C++程序设计》第十章总结

本文深入探讨了C++的流类库,包括文件、流的概念,C++流类系统如何对标准设备进行I/O操作,以及I/O函数和格式控制。介绍了iostream、fstream等类的使用,以及文本文件和二进制文件的区别。通过运算符重载和格式控制函数,可以灵活地进行数据输入输出。此外,还讨论了磁盘文件的打开、关闭和随机访问,强调了text与binary文件的特性及其在存储效率和兼容性上的差异。
摘要由CSDN通过智能技术生成


文件、流以及C++的流类库

C++流类库的优点:

  • 简明和可读性
  • 类型安全(type safe)
  • 易于扩充

文件和流的概念

文件是计算机的基本概念,一般指存储于外部介质上的信息集合
每个文件应有一个包括设备及路径信息的文件名。
其中外部介质主要指硬盘。信息是数据和程序代码的总称。

文件可分为文本(Text)文件和二进制(binary)文件。

  • 文本文件以字节(byte)为单位,每个字节对应一个ASCII码,表示一个字符,故称为字符文件。文本文件保存的是一串ASCII字符,可用文件处理器对其进行编辑,输入输出过程中系统要对内外存的数据格式进行相应转换。
  • 二进制文件以位(bit)为单位,实际上是由0和1组成的序列。输入输出过程中,系统不对相应数据进行任何转换。
  • 例如,整数12345以文本文件存储时占用5bytes,而以二进制形式存储只占用2bytes。

在程序中,文件的概念不是狭义的指键盘上的文件,所有的有输入输出功能的设备,例如键盘、控制台、显示器、打印机都被视为文件。

就输入输出操作来说,这些外设和硬盘上的文件是一致的,对于程序员来说文件只与信息的输入输出相关,而且这种输入输出是串行序列形式的。于是人们把文件的概念抽象为“流”(stream)
流是程序设计中对I/O系统中文件的抽象。C++的I/O系统定义了一系列具有某种继承派生关系的流类,并为这些抽象的流类定义了一系列的I/O操作函数。当需要进行实际的I/O操作时,只需要创建这些类的对象(称为流),并令其与相应的物理文件(硬盘或软盘文件名或者外设名)相联系。对流的操作等同于对物理文件的操作。
在这里插入图片描述


C++的流类系统

C++的I/O系统并不是C++语言的一部分,它是系统为用户提供的专用于数据的输入输出的标准类(及其函数、对象)族。
实现I/O操作的主要几个类在头文件iostream中说明。下面对几个主要的类作一简介。

  1. ios类:在其中以枚举定义方式给出一系列与I/O有关的状态标志及工作方式等常量,定义了一系列涉及输入输出格式的成员函数(包括设置域宽、数据精度等),它还有一个数据成员是流的缓冲区指针。以类ios作为虚基类,派生出了输入流类istream和输出流类ostream。
  2. streambuf类,负责管理流的缓冲区,包括负责设置缓冲区和在缓冲区与输入流和输出流之间存取字符的操作的成员函数。
  3. istream类和ostream类除继承了类ios的成员之外,主要为C++的系统数据类型分别对于运算符>><<进行重载
  4. iostream类以istream类和ostream类为基类,它同时继承二者,以便创建可以同时进行I/O操作即进行输入和输出双向操作的流。
  5. 这五个类的继承关系如图所示,其中streambuf类与ios类之间没有继承关系,当I/O操作需要使用I/O缓冲区时,可以创建缓冲区对象,通过流的缓冲区指针来完成有关缓冲区的操作。大多数I/O操作的函数包括在ios类和istream类、ostream、iostream类中。
    在这里插入图片描述
    在头文件iostream中,除了类的定义之外,还包括四个对象的说明,它们被称为标准流,或预定义流,也就是由系统创建的“标准”对象。
  • cin是类istream的对象,为标准输入流,在不作其他说明条件下,与标准输入设备(一般指键盘)相关联。
  • cout是类ostream的对象,为标准输出流,在不作其他说明的情况下,与标准输出设备(显示器)相关联。
  • cerr、clog也是类ostream的对象,与标准错误输出设备相关联,前者为非缓冲方式,后者为缓冲方式。

对标准设备的I/O操作

I/O函数

对于字符数据的I/O提供了函数put()和get()
对于字符串数据的I/O提供了函数read()和write()
这些函数主要是为磁盘文件进行字符及字符串的输入输出而提供给用户的,其使用与插入运算符“<<”和提取运算符“>>”。

//屏幕输出
cout.put(c1).put(',').put(c2).put('\n');
cout.write(s1,3).put(',').write(s2,2).put('\n');
//键盘输入
ch=cin.get();
cin.read(s1,7);

I/O函数使用的说明

friend istream& operator>>(istream& in,int& i);
friend ostream& operator<<(ostream& out,int& i);

  • 第一个参数out是输出的目标,在对标准设备输出时,它确定为cout。
  • 第二个参数i是输出的内容,这里是int型变量或常量
  • 返回类型为ostream&,返回的是引用ostream&,可达到作为左值的目的,这里是标准对象cout。
  • 用函数调用的一般方式:
    cout.operator<<(x);
    cout<<x

对用户定义类型进行运算符重载

class complex{
	...
public:
	friend istream& operator>>(istream& in,complex& c);
	friend ostream& operator<<(ostream& out,complex& c);
};
istream& operator>>(istream& in,complex& c){
	in>>c.real>>c.imag;
	return in;
}
ostream& operator<<(ostream& out,complex& c){
	out<<c.real<<" "<<c.imag<<endl;
	return out;
}

I/O的格式控制

类ios中用于格式控制的成员函数

在类ios的说明中,为了实现格式输出,做了3件事。

  • 定义了公有的格式控制标志字,它由若干标志位组成。
  • 定义了一些用于格式控制的公有成员函数,分别对于标志字中各标志位进行设置。
  • 再使用另一些成员函数根据标志字来进行格式输出。

由于ios作为诸多I/O流类的基类,因此,其公有成员函数可被各派生类的对象直接调用。
标志字(状态字)的各位都控制一定的I/O特征,例如标志字的右第一位为1,表示在输入时跳过空白符号。标志字的各位以枚举类型形式定义于ios说明中。
在这里插入图片描述

  • 可以使用位运算符“|”将多个格式控制标志位属性进行“合成”。例如,ios::dec|ios::showpos表示二进制数0000001000010000,它指出应输出十进制整数,正整数带加号“+”。
  • 标志位不允许互斥。

类ios用于格式控制的公有成员函数

公有成员函数功能
long flags()返回当前标志字
long flags(long)设置标志字并返回更新前的标志字
long setf(long)设置指定的标志位
long unsetf(long)清除指定的标志位
long setf(long,long)设置指定的标志位的值
int width()返回当前显示数据的域宽
int width(int)设置当前显示数据域宽并返回原域宽
char fill()返回当前填充字符
char fill(char)设置填充字符并返回原填充字符
int precision()返回当前浮点数精度
int precision(int)设置浮点数精度(或有效数字个数)并返回原精度

附上课本上的讲解:
在这里插入图片描述
在这里插入图片描述

格式控制符

无参格式控制符定义头文件iostream
带参控制符定义在头文件iomanip.h中

无参I/O控制符功能
endl输出时插入换行符并刷新流
ends输出时,在字符串后插入NULL作为结束符
flush刷新流,将缓冲区中的当前信息立即输出到目标设备
ws输入时略去前导的空白字符(空白、Tab键、换行)
dec令I/O数据按十进制格式(默认数制)
hex令I/O数据按十六进制格式
oct令I/O数据按八进制格式
带参I/O控制符功能
setbase(int base)设置数制转换基数为base
resetiosflags(long IFlags)清除参数IFlags所指定的标志位
setiosflags(long IFlags)设置参数IFlags所指定的标志位
setfill(char cFill)将“填充字符”设置为cFill
setprecision(int np)设置浮点数精度为np
setw(int nw)设置当前显示数据域宽为nw

其中setprecision当格式为ios::scientific或ios::fixed时,精度参数np指小数点后的位数,否则指有效数字个数。
有参格式控制符setw()只对随后一个数的域宽有效


磁盘文件的输入输出

在这里插入图片描述
包含在fstream.h头文件中
ifstream类:在本流类对象所对应的磁盘文件中输入(读)数据
ofstream类:往本流类对象所对应的磁盘文件中输出(写)数据
fstream类:往本流类对象所对应的磁盘文件进行输入和输出的双向(读写)操作。

文件的打开和关闭

文件流可分别对于ifstream类、ofstream类、fstream类说明其对象的方式创建。三个类的构造函数原型为:

ifstream::ifstream(char* name,int mode=ios::in,int file_attrb=filebuf::openprot)
ofstream::ofstream(char* name,int mode=ios::out,int file_attrb=filebuf::openprot)
fstream::fstream(char* name,int mode,int file_attrb=filebuf::openprot)
//第二个参数为对文件的I/O模式
//第三个参数指定所打开文件的保护方式
访问模式功能
ios::in用于读入
ios::out用于写入
ios::ate打开并指向文件尾
ios:app用于附加数据打开并指向文件尾
ios::trunc如文件存在,则清除其内容
ios::nocreate如文件不存在,则操作失败
ios::noreplace如文件存在,则操作失败
ios::binary二进制文件(缺省时为文本文件)
//ofstream outfile1("myfile1.txt");
ofstream outfile1;
outfile1.open("myfile1.txt");
outfile<<"Hello world!"<<endl;
outfile1.close();

//读取数据
char str1[80],str2[80];
int x2,y2;
ifstream infile1("myfile1.txt");
infile1>>str1>>str2;
infile>>x2>>y2;
infile1.close();

使用类成员函数对文件流进行操作

get()、put();read()、write();以及getline()
类成员函数get()与put()
使用类成员函数get()与put()可以对用户磁盘文件进行读与写操作。
ostream& put(char ch);
istream& get(char& rch);

类成员函数read()与write()
使用类成员函数read()与write()可以对文件进行读写操作。
通常使用read()和write()对二进制文件进行读写。
一般在处理大批量数据时,往往需要提高IO操作速度,简化IO编程,以二进制形式进行读写,效果最好。所谓二进制形式,就是简单的把文件视为一个0,1串,以位(bit)为单位,不考虑文件格式,输入输出过程中,系统不对相应数据进行任何转换
ostream& write(const char* pch,int n)
istream& read(char* pch,int n)

类成员函数getline()
istream& getline(char* pch,int n,char delim='\n');
函数getline()操作的文件通常是文本文件。


text文件和binary文件

以text文件形式存储数据,优点是具有较高的兼容性,可利用任何一个文字处理程序进行阅读或编辑修改等,缺点是存储一批纯数值信息时,要在数据之间人为地添加分隔符,否则将导致数据无法正确读出;text文件通常所占的磁盘空间较大,且不便于对数据实行随机访问(因为每一数据所占磁盘空间的大小通常不相同)。另外,在text文件的输入输出过程中,系统要对内外存的数据格式进行相应转换。

以binary文件形式存储数据,优点是便于对数据实行随机访问(每一同类型数据所占磁盘空间的大小相同,不必在数据之间人为的添加分隔符),而且所占的磁盘空间通常比text文件要小。缺点是兼容性低,不可利用文件处理程序进行阅读或编辑修改等。另外,在binary文件的输入输出过程中,系统不对数据进行任何转换。

程序员可以决定将数据存储为text文件或者binary文件,通过将打开文件的访问模式nMode设置为ios::binary,使打开的文件为binary文件形式;在默认情况下,打开的文件为text文件形式。

对数据文件进行随机访问

为了方便二进制文件的读写,系统提供了设置和读取文件的读写指针位置的函数。其中由类istream提供函数成员:
long tellg();
istream& seekg(long offset,int dir=ios::beg);
由ostream类提供函数成员:
long tellp();
ostream& seekp(long offset,int dir=ios::beg);
其中参数offset给出相对偏移字节数,参数dir有3个取值(在ios类中说明):
ios::beg相当于文件开头的位置
ios::cur相当于指针当前位置
ios::end相当于文件尾的位置

long pos=fout.tellp();//将文件流fout的写指针的当前位置取出送到变量pos
fin.seekg(0,ios::beg);//把文件流fin的读指针定位到文件开头

思维导图

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值