⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 11章 c++输入输出流.txt

📁 C++大学教程txt版中文版 C++大学教程txt版中文版
💻 TXT
📖 第 1 页 / 共 5 页
字号:
 
C++大学教程(第11章 C++输入/输出流-01)  
 
教学目标
    ●了解怎样使用C++面向对象的输入/输出流
    ●能够格式化输入和输出
    ●了解I/O流类的层次结构
    ●了解怎样输入/输出用户自定义类型的对象
    ●能够建立用户自定义的流操纵算子
    ●能够确定/输出操作的成功与失败
    ●能够把输入输出流连到输人流上

11.1  简介
    C++标准库提供了—组扩展的输入/输出(I/O)功能。本章将详细介绍C++中最常用的一些I/O 操作,并对其余的输入/输出功能做一简要的概述。本章的有些内容已经在前面提到,这里对输入/输出功能做一个更全面的介绍。
    本章讨论的许多输入/输出功能都是面向对象的,读者会发现C++的I/O操作能够实现许多功能。C++式的I/O中还大量利用了C++的其他许多特点,如引用、函数重载和运算符重载等等。
    C++使用的是类型安全(typesafe)的I/O操作,各种I/O操作都是以对数据类型敏感的方式来执行的。假定某个函数被专门定义好用来处理某一特定的数据类型,那么当需要的时候,该函数会被自动调用以处理所对应的数据类型。如果实际的数据类型和函数之间不匹配,就会产生编译错误。
  因此,错误数据是不可能通过系统检测的(C语言则不然。这是C语言的漏洞,会导致某些相当微妙而又奇怪的错误)。
    用户既可以指定自定义类型的I/O,也可以指定标准类型的I/O。这种可扩展性是C++最有价值的特点之一。

    编程技巧11.1
    尽管C语言式的I/O在C++中是可以使用的,但还是应该尽量使用C++特有的I/O格式。

    软件工程视点11.1
    C++式的I/O是类型安全的。

    软件工程视点11. 2
    C++允许对预定义类型和自定义类型的I/O用同样的方法处理.从而可加快软件的开发过程,特别是能够提高软件的复用性。

11.2  流
    C++的I/O是以字节流的形式实现的,流实际上就是一个字节序列。在输入操作中,字节从输入设备(如键盘、磁盘、网络连接等)流向内存;在输出操作中,字节从内存流向输出设备(如显示器、打印机、磁盘、网络连接等)。
    应用程序把字节的含义与字节关联起来。字节可以是ASCII字符、内部格式的原始数据、图形图像、数字音频、数字视频或其他任何应用程序所需要的信息。
    输人/输出系统的任务实际上就是以一种稳定、可靠的方式在设备与内存之间传输数据。传输过程中通常包括一些机械运动,如磁盘和磁带的旋转、在键盘上击键等等,这个过程所花费的时间要比处理器处理数据的时间长得多,因此要使性能发挥到最大程度就需要周密地安排I/O操作。一些介绍操作系统的书籍(见参考文献Dc9O)深入地讨论了这类问题。
    C++提供了低级和高级I/O功能。低级I/O功能(即无格式I/O)通常只在设备和内存之间传输一些字节。这种传输过程以单个字节为单位.它确实能够提供高速度并且可以大容量的传输,但是使用起来不太方便。
    人们通常更愿意使用高级I/O功能(即格式化I/O)。高级I/O把若干个字节组合成有意义的单位,如整数、浮点数、字符、字符串以及用户自定义类型的数据。这种面向类型的I/O功能适合于大多数情况下的输入输出,但在处理大容量的I/O时不是很好。

    性能提示11.1
    处理大容量文件最好使用无格式I/O。

11.2.1  iostream类库的头文件
    C++的iostream类库提供了数百种I/O功能,iostream类库的接口部分包含在几个头文件中。
    头文件iostream.h包含了操作所有输入/输出流所需的基本信息,因此大多数C++程序都应该包含这个头文件。头文件iostream.h中含有cin、cout、cerr、clog 4个对象,对应于标准输入流、标准输出流、非缓冲和经缓冲的标准错误流。该头文件提供了无格式I/O功能和格式化I/O功能。
    在执行格式化I/O时,如果流中带有含参数的流操纵算子,头文件iomanip.h所包含的信息是有用的。
    头文件fstream.h所包含的信息对由用户控制的文件处理操作比较重要。第13章将在文件处理程序中使用这个头文件。
    每一种C++版本通常还包括其他一些与I/O相关的库,这些库提供了特定系统的某些功能,如控制专门用途的音频和视频设备。

11.2.2  输入/输出流类和对象
    iostream类库包含了许多用于处理大量I/O操作的类。其中,类istream支持流输入操作.类ostream支持流输出操作,类iostream同时支持流输入和输出操作。
    类istream和类ostream是通过单一继承从基类ios派生而来的。类iostream是通过多重继承从类istream和ostream派生而来的。继承的层次结构见图11.1。
    运算符重载为完成输入/输出提供了一种方便的途径。重载的左移位运算符(<<)表示流的输出,称为流插入运算符;重载的右移位运算符(>>)表示流的输入,称为流读取运算符。这两个运算符可以和标准流对象cin、cout、cerr、clog以及用户自定义的流对象—起使用。




    cin是类istream的对象,它与标准输入设备(通常指键盘)连在一起。下面的语句用流读取运算符把整数变量grade(假设grade为int类型)的值从cin输入到内存中。
    cin >> grade;
  注意,流读取运算符完全能够识别所处理数据的类型。假设已经正确地声明了grade的类型,那么没有必要为指明数据类型而给流读取运算符添加类型信息。
    cout是类ostream的对象,它与标准输出设备(通常指显示设备)连在一起。下面的语句用流插入运算符cout把整型变量grade的值从内存输出到标准输出设备上。
    cout << grade;
  注意,流插入运算符完全能够识别变量grade的数据类型,假定已经正确地声明了该变量,那么没有必要再为指明数据类型而给流插入运算符添加类型信息。
    cerr是类osteam的对象,它与标准错误输出设备连在一起。到对象cerr的输出是非缓冲输出,也就是说插入到cerr中的输出会被立即显示出来,非缓冲输出可迅速把出错信息告诉用户。
    clog是类ostream的对象,它与标准错误输出设备连在一起。到对象clog的输出是缓冲翰出。即每次插入clog可能使其输出保持在缓冲区,要等缓冲区刷新时才输出。
    C++中的文件处理用类ifstream执行文件的输入操作,用类ofstream执行文件的输出操作,用类fstream执行文件的输入/输出操作。类ifstream继承了类istream,类ofstream继承了类ostream,类fstream继承了类iostream。与I/O相关的类的继承关系见图11.2。虽然多数系统所支持的完整的输入/输出流类层次结构中还有很多类,但这里列出的类能够实现多数程序员所需要的绝大部分功能。如果想更多地了解有关文件处理的内容,可参看C++系统中的类库指南。







11.3  输出流
    C++的类ostream提供了格式化输出和无格式输出的功能。输出功能包括:用流插入运算符输出标准类型的数据;用成员函数put输出字符;成员函数write的无格式化输出(11.5节);输出十
进制、八进制、十六进制格式的整数(11.6.1节);输出各种精度的浮点数(11.6.2节)、输出强制带有小数点的浮点数(11.7.2节)以及用科学计数法和定点计数法表示的浮点数(11.7.6节);输出在指定域宽内对齐的数据(11.7.3节);输出在域宽内用指定字符填充空位的数据(11.7.4节);输出科学计数法和十六进制计数法中的大写字母(11.7.7节)。

11.3.1  流插入运算符
    流插入运算符(即重载的运算符<<)可实现流的输出。重载运算符<<是为了输出内部类型的数据项、字符中和指针值。11.9节要详细介绍如何用重载运算符<<输出用户自定义类型的数据项。
图11.3中的范例程序用一条流插入语句显示了输出的字符串。图11.4中的范例程序用多条流插入语句显示输出的字符串,该程序的运行结果与图11.3中程序的运行结果相同。

1 // Fig. 11.3: figll 03.cpp
2 // Outputting a string using stream insertion.
3 #include <iostream.h>
4
56 int main()
7   cout << "Welcome to C++!\n";
8
9   return O;
10 }

输出结果:
Welcome to C++!

                                图 11.3 用一条流插入语句输出字符串

1 // Fig. 11.4: figllO4.cpp
2 // Outputting a string using two stream insertions.
3 #include <iostream.h>
4
5 int main()
6{
7   cout << "Welcome to ";
8   cout << "C++!\n";
9
10   return 0;
11 }

输出结果:
Welcome to C++!

                                   图 11.4 用两条流插入语句输出字符串

    也可以用流操纵算子endl(行结束)实现转义序列\n(换行符)的功能(见图11.5)。流操纵算子endl发送一个换行符并刷新输出缓冲区(不管输出缓冲区是否已满都把输出缓冲区中的内容立即输出)。也可以用下面的语句刷新输出缓冲区:
    cout << flush;
11.6节要详细讨论流操纵算子。

1 // Fig. 11.5: fig11_05.cpp
2 // Using the endl stream manipulator.
3 #include <iostream.h>
4
5 int main{)
6 {
7   cout << "Welcome to ";
8   cout << "c++!';
9   cout << endl;  // end line stream manipulator
10
11   return 0;
12 }

输出结果:
Welcome to C++!

                                         图 11.5 使用流操纵算子endl

流插入运算符还可以输出表达式的值(见图11.6)

1 // Fig. 11.6: fig11_O6.cpp
2 // Outputting expression values.
3 #include <iostream.h>
4
5 int main()
6 {
7   cout << "47 plus 53 is ";
8
9   // parentheses not needed; used for clarity
10   cout << ( 47 + 53 );     // expression
11   cout << endt;
12
13   return O;
14 }

输出结果:
47 plus 53 is 100
  
                            图 11.6 输出一个表达式的值

    编程技巧11.2
    当输出表达式时,为防止表达式中的运算符与运算符<<之间存在运算符化先级问题,用括号将表达式括起来。

11.3.2  连续使用流插入/流读取运算符
    重载的运算符<<和>>都可以在一条浯句中连续使用(见图11.7)。
  1  file://  Fig.11.7: fig11_07.cpp
  2  file://  Cascadlng the overlOadGd << OPeratOr.
  3  #includc<iostream.h>
  4
  5  int  main()
  6  {
  7    cout << "47 plus 53 is " << ( 47 + 53 ) << endl;
  8
  9    return  O;
 10  }

输出结果:
47 plus 53 is 100

                        图 11.7 连续使用重载运算符<<

    图中多次使用流插入运算符的语句等同于下面的语句:
    ((( cout << " 47 plus 53 is " ) << 47 + 53 ) << endl);
之所以可以使用这种写法,是因为重载的运算符<<返回了对其左操作数对象(即cout)的引用,因此最左边括号内的表达式:
    ( cout << " 47 plus 53 is " )
它输出一个指定的字符串,并返回对cout的引用,因而使中间括号内的表达式解释为:
    ( cout << ( 47 + 53 ) )
它输出整数值100,并返回对cout的引用。于是最右边括号内的表达式解释为:
    cout << endl;
它输出一个换行符,刷新cout并返回对cout的引用。最后的返回结果未被使用。

11.3.3 输出char*类型的变量
    C语言式的I/O必须要提供数据类型信息。C++对此作了改进,能够自动判别数据类型。但是,C++中有时还得使用类型信息。例如,我们知道字符串是char*类型,假定需要输出其指针的值,即字符串中第一个字符的地址,但是重载运算符<<输出的只是以空(null)字符结尾的char*类型的字符串,因此使用void*类型来完成上述需求(需要输出指针变量的地址时都可以使用void*类型)。图11.8中的程序演示了如何输出char*类型的字符串及其地址,辅出的地址是用十六进制格式表示。在C++中,十六进制数以0x或0X打头,11.6.1节、11.7.4节、11.7.5节和11.7.7节要详细介绍控制数值基数的方法。
1 // Fig. 11.8: fig11_08.cpp
2 // Printing the address stored in a char* variable
3 #include <iostream.h>
4
5 int main()
6{
7   char *string = "test";
8
9   cout << "Value of string is: "<< string
10       << "\nValue of static cast< void *>( string ) is:"
11       << static_cast< void*>( string )<<endl;
12  return 0;
13}

输出结果:
Value of string is:test
Value of staticcast <void*>( string )is:Ox00416D50

                             图 11.8 输出char*类型变量的地址

11.3.4  用成员函数put输出字符和put函数的连续调
    用put成员函数用于输出一个字符,例如语句:
    cout.put('A');
  将字符A显示在屏幕上。
    也可以像下面那样在一条语句中连续调用put函数:
    cout.put('A').put('\n');
  该语句在输出字符A后输出一个换行符。和<<一样,上述语句中圆点运算符(.)从左向右结合,put
  成员函数返回调用put的对象的引用。还可以用ASCII码值表达式调用put函数,语句cout.put(65)也
  输出字符A。

11. 4  输入流
    下面我们要讨论流的输入,这是用流读取运算符(即重载的运算符>>)实现的。流读取运算符通常会跳过输人流中的空格、tab键、换行符等等的空白字符,稍后将介绍如何改变这种行为。当遇到输入流中的文件结束符时,流读取运算符返回0(false);否则,流读取运算符返回对调用该运算符的对象的引用。每个输入流都包含一组用于控制流状态(即格式化、出错状态设置等)的状态位。当输入类型有错时,流读取运算符就会设置输人流的failbit状态位;如果操作失败则设置badbit状态位,后面会介绍如何在I/O操作后测试这些状态位。11.7节和11.8节详细讨论了流的状态位。

11.4.1  流读取运算符
    图11.9中的范例程序用cin对象和重载的流读取运算符>>读取了两个整数。注意流读运算符可以连续使用。
1 // Fig. 11.9: figll_09.cpp
2 // Calculating the sum of two integers input from the keyboard
3 // with the cin oct and the stream-extraction operator.
4 #include <iostream.h>
5
6 int main()
7{
8   int x, y;
9
10  cout << "Enter two integers: ";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -