Maine

纵有疾风起,人生不言弃

C++ 中的流(Stream)

在我们经常使用的 iostream 标准库中提供了 cin 和 cout 方法分别用于从键盘输入数据和向屏幕输出数据(简称为标准 I/O)。除此之外,程序还可以从文件中读入数据,以及向文件中写入数据(简称为文件 I/O)。

数据输入和输出的过程其实就是数据传输的过程。数据像水流一样从一个地方流动到另一个地方,在 C++ 中将此过程形象的称为 “流(stream)”。

在 C++ 的标准类库中,进行数据输入输出的类统称为“Stream 类”。cin 是 Stream 类 istream 的对象,cout 是Stream类 ostream 的对象。要使用Stream类,需要在程序中包含相应的头文件。

C++ 中常见的几个Stream类关系如下:
cpp stream

为了避免多继承的二义性,从 ios 派生出 istreamostream 时,均使用了虚继承。

  • istream 用于键盘输入。
  • ostream 用于屏幕输出。
  • ifstream 用于从文件读取数据。
  • ofstream 用于向文件写入数据。
  • iostream 既能用于输入,又能用于输出。
  • fstream 既能从文件读取数据,又能向文件写入数据。

标准 Stream 对象

iostream 头文件中定义了四个标准流对象,它们分别是 cincoutcerrclog

  • cin 是标准输入流,可以从键盘读取数据,也可以被重定向为从文件中读取数据。
  • cout 是标准输出流,可以用于向屏幕输出数据,也可以被重定向为向文件写入数据。
  • cerr 是标准错误输出流,用于向屏幕输出出错信息,cerr 不能被重定向。
  • clog 是标准错误输出流,用于向屏幕输出出错信息,不能被重定向。

cerrclog 同样都作用于标准错误输出,它们的区别在于:cerr 不使用缓冲区,直接输出信息到屏幕;而输出到 clog 中的信息会先被存放到缓冲区,缓冲区满了或者刷新缓冲区时才会输出到屏幕。

cout 的原型可以看做:

ostream cout(&fout);

ostream 类的无参构造函数和复制构造函数都是私有的,因此在程序中一般无法定义 ostream 类的对象,唯一能用的 ostream 类的对象就是 cout。

当然,上面关于 cout 对象的定义语句说明 ostream 类是有一个公有构造函数的,如果知道这个构造函数是什么样的,那么也能自己定义 ostream 类的对象——但这么做并无必要。

cout 可以被重定向,而 cerr 不能。所谓重定向,就是将输入的源或输出的目的地改变。例如,cout 本来是输出到屏幕上的,但是经过重定向,本该输出到屏幕上的东西就可以被输出到文件中。

举个例子:

#include <iostream>
using namespace std;
int main()
{
    int x,y;
    cin >> x >> y;
    freopen("test.txt", "w", stdout);  //将标准输出重定向到 test.txt文件
    if( y == 0 )  //除数为0则输出错误信息
        cerr << "error." << endl;
    else
        cout << x /y ;
    return 0;
}

第 7 行的 freopen 是一个标准库函数,第二个参数 w 代表写模式,第三个参数代表标准输出。该语句的作用是将标准输出重定向为 test.txt 文件。

重定向之后,所有对 cout 的输出都不再出现在屏幕上,而是出现在 test.txt 文件中。

test.txt 文件会和本程序的可执行文件出现在同一个文件夹中。重定向仅对本程序有效,不影响其他程序。

运行本程序,输入
6 2
程序没有输出,但是打开 test.txt文件,可以看到文件中有
3
如果输入
4 0
则程序在屏幕上输出
error.

说明 cerr 不会被重定向。

cin 也是可以被重定向的。如果在程序中加入:

freopen("input.dat", "r", stdin);

第二个参数 r 代表只读打开,第三个参数 stdin 表示标准输入。执行此语句后,cin 就不再从键盘读入数据,而是从 input.dat 文件中读入数据,input.dat 文件中有什么内容,就相当于用户从键盘输入了什么内容。

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注