以下是课程书上的,我直接摘抄下来的:
C++语言同C语言一样,也不具有内部输入输出能力,这样做的目的是为了最大限度地保证语言与平台的无关性。计算机语言的输入输出功能都是与操作系统相关的,如果C++为某种操作系统实现内部输入输出功能,那它也就被限制在这个操作系统上了,这是我们所不希望的。
如果一个应用程序没有输入和输出,那它也就没有应用价值。在C++中,输入输出功能,是通过调用该操作系统的I/O库来实现的。
scanf、printf都是C语言标准输入输出库函数,不能否认,C语言的标准输入输出库函数也是安全、高效的,为什么说C++的输入输出更安全高效呢?关键在于C++的输入输出与C的输入输出实现方法不同。
C++的输入输出是如何实现的?是不是依据面向对象的思想,把C的标准I/O库封装成类,然后进行处理呢?比如操作一个文件,我们想确保文件能够安全地打开,及时地关闭,而不完全依赖用户调用open()、close()函数,可以构造一个文件类,定义一个成员变量,作为文件指针,分别在构造函数和析构函数中打开、关闭文件。再进一步,可以在类中实现C的标准输入输出库中所有的I/O函数,并把文件指针置为私有变量。从外面看来,这已经是一个封装得很好的文件类。在某种意义上讲,这种方法是相当有效的,我们也可以为标准I/O和存储块构造类似的类。
我们已经知道,C++是使用iostream流库,并没有使用C的输入输出库,是不是iostream流库更好呢?答案是肯定的。C的I/O库函数主要用来处理基本数据类型(字符、整型、浮点数等),使用参数表进行数据传输,使用格式字符串指定数据类型和输入输出格式。它们在运行时对格式字符串进行语法分析,并据此对变量进行解释。例如:
printf("a=%d/tb=%d/ta+b=%d/n",a,b,a+b);
C语言I/O库的缺点是:
1. 即使只使用了解释程序的一个功能,也要全部装载。如上面的例子,我们要装载整个包,包括解释浮点数和字符串那部分程序段,无法减少程序的长度。
2. 虽然printf族函数已经优化得很好,但是,它是在运行期间进行解释,如果能在编译期间分析格式字符串里的变量,根据不同的类型调用各自的函数处理,运行会快得多,而且C++编译期间的类型检查会有助于我们发现错误。
3. 对于C++来说,printf不能被扩展是它最大的缺点。我们不能通过重载函数对它进行扩展,因为重载函数要有不同类型的参数,而printf族函数把类型信息隐藏在可变参数表和格式字符串中。
iostream是通过类的继承,类成员函数的重载来实现的,利用类的可继承性和多态性,使iostream类库使用统一的函数接口操作标准I/O、文件、存储块等输入输出设备。通过函数重载,为每种内部数据类型定义了流输入输出函数,使得用户可以用相同的格式对各种数据类型进行操作,编译程序根据数据的类型自动选择相应的输入输出函数,不必将所有函数一并加载。同时,iostream拥有了很好的扩展性,用户通过重载还可以对自定义对象进行流的操作。因此,与标准C输入输出库的各种各样的函数相比,输入输出流更容易、更安全、更有效。
12.1.1 输入输出流类层次
iostream是一组C++类,用于实现面向对象模型的输入输出,可以提供无缓冲的(低级)和缓冲的I/O操作。在某些情况下,如果C++编译器提供的iostream库中没有合适的输入输出函数可用,我们还可以利用类的继承和多态特性来改进它们,下图给出了I/O流类之间的继承关系。
I/O流类层次图
对上图的解释:
抽象流基类
ios 流基类
输入流类
istream 普通输入流类和用于其它输入流的基类
ifstream 输入文件流类
istream_withassign 用于cin的输入流类
istrstream 输入串流类
输出流类
ostream 普通输出流类和用于其它输出流类的基类
ofstream 输出文件流类
ostream_withassign 用于cout、cerr和clog的流类
ostrstream. 输出串流类
输入输出流类
iostream 普通输入输出流类和用于其它输入输出流的基类
fstream 输入输出文件流类
strstream 输入输出串流类
stdiostream 用于标准输入输出文件的输入输出类
缓冲流类
streambuf 抽象缓冲流基类
filebuf 用于磁盘文件的缓冲流类
strstreambuf. 用于串的缓冲流类
stdiobuf 用于标准输入输出文件的缓冲流类
预定义流初始化类
iostream_init 预定义流初始化的类
其中,*C@垠网/h)提u|~gios、istream、ostream和streambuf类构成了C++中iostream输入输出功能的基础。
iostream类库中,streambuf、ios、istream、ostream、iostream、istream_withassign和ostream_withassign这些基本I/O流类和预定义的cin、cout、cerr和clog在iostream.h文件中说明。
filebuf、ifstream、ofstream和fstream在fstream.h中说明。
strstream、istrstream、ostrstream和strstream在strstrea.h中说明。
需要注意的是:fstream.h和strstrea.h中都包含了iostream.h,所以如果使用标准输入输出(控制台I/O),只要包含iostream.h头文件即可,如果使用fstream或者strstream,只要包含相应的fstream.h和strstrea.h即可。
四个全局的流对象:cout、cerr、clog和cin,用于标准输出和输入,cerr的数据会被立刻显示出来,非缓冲输出可以迅速把出错信息告知用户。clog也是与标准错误设备连在一起的,但它是缓冲输出。
istream有三个从流中进行非格式化抽取的成员函数:get()、getline()和read()
成员函数get()的用法
int get() | 从流中抽取单个字符并返回。 |
istream& get(char*,int,char) | 从流中抽取字符直到终止符(缺省为''''/n'''')或者抽取字符达到第二个参数给定的数量或者已到文件尾,
@国wN6Wo教软z 将其存储在第一个参数指定的字符数组里。 |
istream& get(char &) | 从流中抽取单个字符并存入引用变量中 |
istream& get(streambuf &,char) | 从流中取得字符存入streambuf对象,直到终止符或文件尾 |
成员函数getline()的用法
istream& getline(char*,int,char) | 从流中抽取字符直到终止符(缺省为''''/n''''),或者抽取字符达到参数给定的数量-1,或者已到文件尾,将其存储在第一个参数指定的字符数组里。如果发现终止符,它从流中提取终止符,但只是抛弃掉,并不把它存在结果缓冲区里。 |
成员函数read()的用法
istream& read(char*,int) | 从流中抽取字节直到参数给定的数量或者到文件结束,将其存储在第一个参数指定的字符数组里。该函数用于二进制输入流。 |
操纵算子是插入到流中或从流中抽取出来、影响流的格式状态的函数或对象。流的格式状态由ios类定义,其中包括指定数据对象的基数,如十进制、八进制、十六进制等,还有输出宽度、精度、填充字符等等。
操纵算子 | 作用 |
endl | 输出换行符并刷新流 |
ends | 输出空字符 |
flush | 刷新流 |
dec | 将数值转化为十进制 |
hex | 将数值转化为十六进制 |
oct | 将数值转化为八进制 |
ws | 跳过空白字符(用于输入) |
setiosflags(fmtflags n) | 设置由n指定的格式标志;设置一直起作用直到下一个变化为止,作用同ios::setf()。格式标志在ios类中定义,参见表12-5。 |
setbase(base n) | 把基数改成n,这里n取10、8或16(任何别的值结果为0)。如果n是0,输出基数为10,但输入使用c语言的约定: 10是10,010是8而0xf是15。推荐使用dec、oct和hex |
setfill(char n) | 把填充字符改成n,作用同ios::fill() |
setprecision(int n) | 把精度改成n,作用同ios::precision() |
setw(int n) | 把域宽改成n,作用同ios::width(),只影响它后面的要输出的数据,当这个数据打印完毕后,域宽恢复到缺省状态 |
格式标志清单
showbase | 在打印一整数值时,标明数字基数(十进制,八进制和十六进制);所用的格式能被c + +编译器读出 |
noshowbase |
|
showpos | 显示正值符号加(+) |
noshowpos |
|
uppercase | 显示代表十六进制值的大写字母a - f以及科学记数法中的e |
nouppercase |
|
showpoint | 表明浮点数值的小数点和后面的零 |
skipws | 跳过输入中的空白字符 |
noskipws |
|
left | 左对齐,
sf=无q5`网wK国Yv=} 右填充 |
right | 右对齐,左填充 |
internal | 在引导符或基数指示符和值之间填充 |
scientific | 使用科学记数法 |
fixed | setprecision()或ios::precision()设置小数点后面的位数 |
文件打开方式由下面几种:
ios::in | 打开一个输入文件, ifstream的打开方式,以防止截断一个现成的文件
h中垠MGrUlD提专7Y+"
用这个标志作为 |
ios::out | 打开一个输出文件,当用于一个没有ios::app、ios::ate或ios::in的ofstream时,ios::trunc被隐含 |
ios::app | 以追加的方式打开一个输出文件 |
ios::ate | 打开一现成文件(不论是输入还是输出)并寻找末尾 |
ios::nocreate | 仅打开一个存在的文件(否则失败) |
ios::noreplace | 仅打开一个不存在的文件(否则失败) |
ios::trunc | 如果一个文件存在,打开它并删除旧的文件 |
ios::binary | 打开一个二进制文件,缺省的是文本文件 |
文件流打开文件可以利用无参的构造函数,然后调用open():
ofstream outfile;
outfile.open("outfile", iosmode);
也可调用带参数的构造函数,指定文件名和打开方式:
ofstream outfile("outfile", iosmode);
原文地址:点击打开链接