【问题标题】:What is the difference between cout, cerr, clog of iostream header in c++? When to use which one?c++中iostream标头的cout,cerr,clog有什么区别?什么时候用哪一个?
【发布时间】:2013-05-22 06:58:22
【问题描述】:

我尝试在互联网上研究coutcerrclog 之间的区别,但找不到完美的答案。我仍然不清楚何时使用哪个。谁能通过简单的程序向我解释并说明何时使用哪一个的完美情况?

我访问了this site,它在cerrclog上显示了一个小程序,但是那里得到的输出也可以使用cout得到。所以,我对每个人的确切用途感到困惑。

【问题讨论】:

  • 每个都有一个默认使用的计算机识别流stdoutstdin(对于cin)和stderr。我相信 clog 只是 cerr 有一个缓冲变化。

标签: c++ iostream cout clog


【解决方案1】:

通常您使用std::cout 进行正常输出,std::cerr 用于错误,std::clog 用于“记录”(可以表示任何您想要的意思)。

主要区别在于std::cerr 不像其他两个那样缓冲。


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

【讨论】:

  • 我读到clog 也输出到cerr。那么基于此,你会选择哪一个呢?如果clog 通常用于“记录”,我为什么要让它进入错误流?日志看起来更像是“普通日志”(又名cout)而不是错误。
  • @void.pointer 正如我在回答中所说,cerrclog 都使用标准的“错误”输出,但 clog 被缓冲,这可能就是为什么它看起来更像 @ 987654340@。选择哪一个作为错误输出?取决于我的猜测,我无法列出的原因更多,必须根据具体情况来决定。
  • “缓冲”是什么意思?
  • @simplename 输出不是直接写入的,而是存储在 buffer 中,直到缓冲区flushed。输出到文件或终端一直很慢(终端或控制台仍然很慢),逐个字符写入无效,写入一大块字节更有效。
  • context: cerr 未缓冲,因为如果程序以非正常方式崩溃,您可能会将有用的调试信息卡在缓冲区中,而不是打印到 stderr。
【解决方案2】:

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

一般情况下,stdout 应该用于实际程序输出,而所有信息和错误消息都应该打印到stderr,这样如果用户将输出重定向到文件,信息消息仍然会打印在屏幕上并且不是输出文件。

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

    • until it is not fully filled.--这不应该说until it IS fully filled吗?
    • 仅供参考:看起来像TutorialsPoint.com has directly plagiarized your answer, here。我于 2020 年 10 月 23 日通过电子邮件向 TutorialsPoint 发送了关于可能的抄袭的电子邮件,他们在 2020 年 10 月 25 日回复说:“当然,加布里埃尔,我们会调查的。”在那之后我再也没有收到他们的回复,但他们似乎没有看进入它。
    【解决方案4】:

    这 3 个流的区别在于缓冲。

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

    请检查以下代码,并通过 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";
    }
    

    【讨论】:

      【解决方案5】:
      • 使用 cout 作为标准输出。
      • 使用 cerr 来显示错误。
      • 使用 clog 进行日志记录。

      【讨论】:

      • 错了,cerr 比 cout 慢,因为没有缓冲!就像 write vs printf
      【解决方案6】:

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

      30.4.3 窄流对象 [narrow.stream.objects]

      istream cin;

      1 对象 cin 控制来自与对象 stdin 关联的流缓冲区的输入,该对象在 &lt;cstdio&gt; (30.11.1) 中声明。

      2 对象cin初始化后,cin.tie()返回&amp;cout。其状态与 basic_ios&lt;char&gt;::init (30.5.5.2) 所需的其他状态相同。

      ostream cout;

      3 对象cout 控制输出到与stdout 对象关联的流缓冲区,在&lt;cstdio&gt; (30.11.1) 中声明。

      ostream cerr;

      4 对象cerr 控制输出到与对象stderr 关联的流缓冲区,在&lt;cstdio&gt; (30.11.1) 中声明。

      5 对象cerr 初始化后,cerr.flags() &amp; unitbuf 非零,cerr.tie() 返回&amp;cout。其状态与 basic_ios&lt;char&gt;::init (30.5.5.2) 所需的其他状态相同。

      ostream clog;

      6 对象clog 控制输出到与stderr 对象关联的流缓冲区,在&lt;cstdio&gt; (30.11.1) 中声明。

      讨论...

      cout 写信给stdoutcerrclogstderr

      标准输出 (stdout) 旨在接收来自程序的非错误、非诊断输出,例如可以显示给最终用户或流式传输到某个进一步处理阶段的成功处理的输出。

      标准错误 (stderr) 用于诊断输出,例如指示程序没有或可能没有产生用户可能期望的输出的警告和错误消息。即使输出数据通过管道传送到进一步的处理阶段,该输入也可以显示给最终用户。

      cincerr 绑定到 cout

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

      这与clog 形成鲜明对比——如果你写在那里,它不会被缓冲,也不会与任何东西绑定,所以它会在刷新之前缓冲相当大的日志量。这会产生最高的消息吞吐量,但意味着读取终端或跟踪日志的潜在消费者可能无法快速看到这些消息。

      【讨论】:

        【解决方案7】:

        coutclog 都是缓冲的,但 cerr 是非缓冲的,所有这些都是预定义的对象,它们是类 ostream 的实例。 这三个的基本用途是 cout 用于标准输出,而 clogcerr 用于显示错误。 cerr 未缓冲的主要原因可能是因为假设您在缓冲区中有多个输出并且代码中提到了错误异常,那么您需要立即显示该错误,这可以通过cerr 有效。

        如果我错了,请纠正我。

        【讨论】:

          猜你喜欢
          • 2011-01-16
          • 2020-08-26
          • 1970-01-01
          • 2011-04-16
          • 1970-01-01
          • 1970-01-01
          • 2011-08-26
          • 2011-01-11
          • 2021-11-17
          相关资源
          最近更新 更多