以前所用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上。
从操作系统的角度看,每一个与主机相连的输入输出设备都被看作一个文件。
程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件。C++的输入与输出包括以下3方面的内容:
(1) 对系统指定的标准设备的输入和输出。即从键盘输入数据,输出到显示器屏幕。称为标准的输入输出,简称标准I/O。
(2) 以外存磁盘文件为对象进行输入和输出,即从磁盘文件输入数据,数据输出到磁盘文件。称为文件的输入输出,简称文件I/O。
(3) 对内存中指定的空间进行输入和输出。通常指定一个字符数组作为存储空间(实际上可以利用该空间存储任何信息)。称为字符串输入输出,简称串I/O。
C++采取不同的方法来实现以上3种输入输出。
为了实现数据的有效流动,C++系统提供了庞大的I/O类库,调用不同的类去实现不同的功能。
在C语言中,用printf和scanf进行输入输出,往往不能保证所输入输出的数据是可靠的、安全的。
在C++的输入输出中,编译系统对数据类型进行严格的检查,凡是类型不正确的数据都不可能通过编译。因此C++的I/O操作是类型安全(type safe)的。
C++通过I/O类库来实现丰富的I/O功能。C++的输入输出优于C语言中的printf和scanf,但是比较复杂。
C++的输入输出流是指由若干字节组成的字节序列,这些字节中的数据按顺序从一个对象传送到另一对象。
实际上,在内存中为每一个数据流开辟一个内存缓冲区,用来存放流中的数据。流是与内存缓冲区相对应的,或者说,缓冲区中的数据就是流。
在C++中,输入输出流被定义为类。C++的I/O库中的类称为流类(stream class)。用流类定义的对象称为流对象。
cout和cin并不是C++语言中提供的语句,它们是iostream类的对象。
C++编译系统提供了用于输入输出的iostream类库。在iostream类库中包含许多用于输入输出的类。常用的见书中表7.1。
ios是抽象基类,由它派生出istream类和ostream类。istream类支持输入操作,ostream类支持输出操作。 iostream类是从istream类和ostream类通过多重继承而派生的类,iostream类支持输入输出操作。
C++对文件的输入输出需要用ifstream和ofstream类。ifstream支持对文件的输入操作,ofstream支持对文件的输出操作。类ifstream继承了类istream,类ofstream继承了类ostream,类fstream继承了类iostream。
(2)与iostream类库有关的头文件
iostream类库中不同的类的声明被放在不同的头文件中,用户在自己的程序中用#include命令包含了有关的头文件就相当于在本程序中声明了所需要用到的类,常用的有
iostream包含了对输入输出流进行操作所需的基本信息。
fstream用于用户管理的文件的I/O操作。
strstream用于字符串流I/O。
stdiostream用于混合使用C和C++的I/O机制时。
iomanip在使用格式化I/O时应包含此头文件。
标准输出流是流向标准输出设备(显示器)的数据。
ostream类定义了3个输出流对象,即cout,cerr,clog。
在输出数据时,有时希望数据按指定的格式输出。有两种方法可以达到此目的。一种是使用控制符;另一种是使用流对象的有关成员函数。
标准输入流是从标准输入设备(键盘)流向程序的数据。
cin是istream类的对象,它从标准输入设备(键盘)获取数据,程序中的变量通过流提取符“>>”从流中提取数据。流提取符“>>”从流中提取数据时通常跳过输入流中的空格、tab键、换行符等空白字符。
注意: 只有在输入完数据再按回车键后,该行数据才被送入键盘缓冲区,形成输入流,提取运算符“>>”才能从中提取数据。
除了可以用cin输入标准类型的数据外,还可以用istream类流对象的一些成员函数,实现字符的输入。
根据文件中数据的组织形式,可分为ASCII文件和二进制文件。
在C++的I/O类库中定义了几种文件类,专门用于对磁盘文件的输入输出操作。
(1) ifstream类,它是从istream类派生的。 用来支持从磁盘文件的输入。
(2) ofstream类,它是从ostream类派生的。 用来支持向磁盘文件的输出。
(3) fstream类,它是从iostream类派生的。 用来支持对磁盘文件的输入输出。
要以磁盘文件为对象进行输入输出,必须定义一个文件流类的对象,通过文件流对象对数据进行操作。
对ASCII文件的读写操作可以用以下两种方法:
(1) 用流插入运算符“<<”和流提取运算符“>>”输入输出标准类型的数据。
(2) 用之前介绍的文件流的put,get,geiline等成员函数进行字符的输入输出。
对二进制文件的操作也需要先打开文件,用完后要关闭文件。在打开时要用ios::binary指定为以二进制形式传送和存储。二进制文件除了可以作为输入文件或输出文件外,还可以是既能输入又能输出的文件。这是和ASCII文件不同的地方。
对二进制文件的读写主要用istream类的成员函数read和write来实现。
字符串流不是以外存文件为输入输出的对象,而以内存中用户定义的字符数组(字符串)为输入输出的对象。字符串流也称为内存流。
文件流类有ifstream,ofstream和fstream,而字符串流类有istrstream,ostrstream和strstream。文件流类和字符串流类都是ostream,istream和iostream类的派生类,因此对它们的操作方法是基本相同的。向内存中的一个字符数组写数据就如同向文件写数据一样,但有3点不同:
(1) 输出时数据不是流向外存文件,而是流向内存中的一个存储空间。输入时从内存中的存储空间读取数据。
(2) 字符串流对象关联的不是文件,而是内存中的一个字符数组,因此不需要打开和关闭文件。
(3) 每个文件的最后都有一个文件结束符,表示文件的结束。而字符串流所关联的字符数组中没有相应的结束标志,用户要指定一个特殊字符作为结束符,在向字符数组写入全部数据后要写入此字符。
字符串流类没有open成员函数,因此要在建立字符串流对象时通过给定参数来确立字符串流与字符数组的关联。
建立字符串流对象的方法如下:
ostrstream类提供的构造函数的原型为
ostrstream::ostrstream(char *buffer,int n,int mode=ios::out);
buffer是指向字符数组首元素的指针,n为指定的流缓冲区的大小(一般选与字符数组的大小相同,也可以不同),第3个参数是可选的,默认为ios::out方式。
可以用以下语句建立输出字符串流对象并与字符数组建立关联:
ostrstream strout(ch1,20);
作用是建立输出字符串流对象strout,并使strout与字符数组ch1关联(通过字符串流将数据输出到字符数组ch1),流缓冲区大小为20。
istrstream类提供了两个带参的构造函数,原型为
istrstream::istrstream(char *buffer);
istrstream::istrstream(char *buffer,int n);
buffer是指向字符数组首元素的指针,用它来初始化流对象(使流对象与字符数组建立关联)。
可以用以下语句建立输入字符串流对象:
istrstream strin(ch2);
作用是建立输入字符串流对象strin,将字符数组ch2中的全部数据作为输入字符串流的内容。
istrstream strin(ch2,20);
流缓冲区大小为20,因此只将字符数组ch2中的前20个字符作为输入字符串流的内容。
strstream类提供的构造函数的原型为
strstream::strstream(char *buffer,int n,int mode);
可以用以下语句建立输入输出字符串流对象:
strstream strio(ch3,sizeof(ch3),ios::in|ios::out);
作用是建立输入输出字符串流对象,以字符数组ch3为输入输出对象,流缓冲区大小与数组ch3相同。
以上3个字符串流类是在头文件strstream中定义的,因此程序中在用到istrstream, ostrstream和strstream类时应包含头文件strstream。