C + + 中 iostream 头的 cout、 cerr、 clog 有什么区别? 什么时候使用哪一个?

我试着在网上研究 coutcerrclog之间的区别,但是找不到一个完美的答案。我还是不清楚什么时候用哪个。谁能给我解释一下,通过简单的程序,并说明一个完美的情况下,什么时候使用哪一个?

I visited 这个网站 which shows a small program on cerr and clog, but the output obtained over there can also be obtained using cout. So, I'm confused over each one's exact use.

83704 次浏览

通常使用 std::cout表示正常输出,使用 std::cerr表示错误,使用 std::clog表示“日志记录”(这可以表示您希望它表示的任何内容)。

主要的区别是 std::cerr不像其他两个那样被缓冲。


与旧的 stdoutstderr相比,std::cout对应于 stdout,而 std::cerrstd::clog都对应于 stderr(除了 std::clog是缓冲的)。

stdoutstderr是不同的流,尽管它们都默认引用控制台输出。重定向(管道)其中一个(例如 program.exe >out.txt)不会影响另一个。

一般来说,stdout应该用于实际的程序输出,而所有的信息和错误消息应该打印到 stderr,因此,如果用户重定向输出到一个文件,信息消息仍然打印在屏幕上,而不是输出文件。

  • 使用 Cout作为标准输出。
  • 使用 塞尔显示错误。
  • 使用 木屐进行日志记录。

Coutclog都是缓冲的,但是 塞尔是非缓冲的,所有这些都是预定义的对象,它们是类 ostream 的实例。 这三个函数的基本用法是 Cout用于标准输出,而 木屐塞尔用于显示错误。 cerr没有缓冲的主要原因可能是因为假设在缓冲区中有几个输出,并且代码中提到了一个错误异常,那么您需要立即显示该错误,这可以由 cerr有效地完成。

如果我说错了,请纠正我。

标准输出流(计数器) : coutostream类的实例。cout用于在标准输出设备(通常是显示屏)上产生输出。需要显示在屏幕上的数据通过插入操作符(<<)插入到标准输出流(cout)中。

非缓冲标准错误流(cerr) : cerr是用于输出错误的标准错误流。这也是 ostream类的一个实例。因为 cerr没有缓冲,所以当我们需要立即显示错误消息时使用它。它没有任何缓冲区来存储错误消息并在以后显示。

缓冲的标准错误流(clog) : 这也是 ostream类的一个实例,用于显示错误,但与 cerr不同的是,错误首先插入到 缓冲器中,然后存储在缓冲区中,直到它没有被完全填满。

进一步阅读: Basic-input-output-c

这三个流的不同之处在于缓冲。

  1. 使用 cerr,输出刷新
    • 立即(因为 cerr 不使用 buffer)。
  2. 堵塞时,输出冲洗
    • 在你完成目前的功能之后。
    • 显式调用函数刷新。
  3. 使用 cout,输出冲洗
    • 在调用任何输出流(cout、 cerr、 clog)之后。
    • 在你完成目前的功能之后。
    • 显式调用函数刷新。

请检查下面的代码,并通过3行运行 DEBUG: f (std: : clog)、 f (std: : cerr)、 f (std: : out) ,然后打开3个输出文件以查看发生了什么。你可以交换这3行,看看会发生什么。

#include <iostream>
#include <fstream>
#include <string>


void f(std::ostream &os)
{
std::cin.clear(); // clear EOF flags
std::cin.seekg(0, std::cin.beg); // seek to begin


std::string line;
while(std::getline(std::cin, line))   //input from the file in.txt
os << line << "\n";   //output to the file out.txt
}


void test()
{
std::ifstream in("in.txt");
std::ofstream out("out.txt"), err("err.txt"), log("log.txt");
std::streambuf *cinbuf = std::cin.rdbuf(), *coutbuf = std::cout.rdbuf(), *cerrbuf = std::cerr.rdbuf(),
*clogbuf = std::clog.rdbuf();


std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!
std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!
std::cerr.rdbuf(err.rdbuf());
std::clog.rdbuf(log.rdbuf());




f(std::clog);
f(std::cerr);
f(std::cout);


std::cin.rdbuf(cinbuf);
std::cout.rdbuf(coutbuf);
std::cerr.rdbuf(cerrbuf);
std::clog.rdbuf(clogbuf);
}


int main()
{
test();
std::cout << "123";
}

来自 C + + 17标准文件草案:

30.4.3窄流对象

istream cin;

1 The object cin controls input from a stream buffer associated with the object stdin, declared in <cstdio> (30.11.1).

对象 cin初始化后,cin.tie()返回 &cout。其状态在其他方面与 basic_ios<char>::init(30.5.5.2)所需的相同。

ostream cout;

3对象 cout控制与 <cstdio>(30.11.1)中声明的对象 stdout相关联的流缓冲区的输出。

ostream cerr;

4对象 cerr控制与对象 stderr相关联的流缓冲区的输出,在 <cstdio>中声明(30.11.1)。

5初始化对象 cerr后,cerr.flags() & unitbuf为非零,cerr.tie()返回 &cout。其状态与 basic_ios<char>::init(30.5.5.2)所要求的相同。

ostream clog;

对象 clog控制与对象 stderr相关联的流缓冲区的输出,在 <cstdio>(30.11.1)中声明。

讨论..。

cout写入 stdout; cerrclog写入 stderr

标准输出(stdout)用于接收程序的非错误、非诊断输出,例如成功处理的输出,这些输出可以显示给最终用户,或者流入某个进一步处理阶段。

标准错误(stderr)用于诊断输出,例如警告和错误消息,指示程序没有或可能没有产生用户可能期望的输出。即使输出数据通过管道传输到另一个处理阶段,也可以将其显示给最终用户,或者可以将其重定向到日志文件,例如。

cincerr连接到 cout

它们都在处理 I/O 操作之前刷新 cout。这样可以确保在程序阻塞从 cin读取输入之前,发送到 cout的提示是可见的,并且在通过 cerr写入错误之前,会刷新发送到 cout的早期输出,这样当两个消息都指向同一个终端/文件/等时,消息按照生成的时间顺序保持。.

这与 clog形成了鲜明的对比——如果你在这里写,它不会被缓冲,也不会被绑定到任何东西上,所以在刷新之前它会缓冲大量的日志记录。这将产生最高的消息吞吐量,但是这意味着即使通过 cerr写入错误并在屏幕上或在日志中,消息可能不会很快被读取终端或跟踪日志的潜在消费者看到。