В чем разница между cout, cerr, clog заголовка iostream в С++? Когда какой использовать?

Я попытался изучить разницу между cout, cerr и clog в Интернете, но не смог найти идеального ответа. Я до сих пор не понимаю, когда что использовать. Может ли кто-нибудь объяснить мне с помощью простых программ и проиллюстрировать идеальную ситуацию, когда какую из них использовать?

Я посетил этот сайт, на котором показана небольшая программа на cerr и clog, но результат, полученный через там же можно получить с помощью cout. Итак, я запутался в точном использовании каждого из них.


person Arlene Batada    schedule 27.05.2013    source источник
comment
У каждого есть распознаваемый компьютером поток stdout, stdin (для cin) и stderr, который он использует по умолчанию. Я считаю, что clog - это просто cerr с изменением буферизации.   -  person chris    schedule 27.05.2013


Ответы (7)


stdout и stderr — это разные потоки, хотя по умолчанию они оба относятся к выводу консоли. Перенаправление (перенаправление) одного из них (например, program.exe >out.txt) не повлияет на другое.

Как правило, stdout следует использовать для фактического вывода программы, а всю информацию и сообщения об ошибках следует печатать в stderr, чтобы, если пользователь перенаправляет вывод в файл, информационные сообщения по-прежнему выводились на экран, а не в выходной файл.

person riv    schedule 27.05.2013

Обычно вы используете std::cout для нормального вывода, std::cerr для ошибок и std::clog для "логирования" (что может означать все, что вы хотите).

Основное отличие состоит в том, что std::cerr не буферизуется, как два других.


По отношению к старым C stdout и stderr, std::cout соответствует stdout, а std::cerr и std::clog оба соответствуют stderr (за исключением того, что std::clog находится в буфере).

person Community    schedule 27.05.2013
comment
Я читал, что clog также выводит cerr. Итак, исходя из этого, какой из них вы выбираете? Если clog обычно используется для ведения журнала, почему я хочу, чтобы это пошло в поток ошибок? Журналы больше похожи на обычные журналы (также известные как cout), чем на ошибки. - person void.pointer; 11.08.2017
comment
@void.pointer Как я уже сказал в своем ответе, и cerr, и clog используют стандартный вывод ошибок, но clog буферизуется, поэтому он больше похож на cout. Какой из них выбрать для вывода ошибок? Зависит, я думаю, от большего количества причин, чем я могу перечислить, и это нужно решать от случая к случаю. - person Some programmer dude; 11.08.2017
comment
что вы подразумеваете под буферизацией? - person simplename; 04.04.2018
comment
@simplename Вывод не записывается напрямую, он сохраняется в буфере до тех пор, пока буфер не будет сброшен. Вывод в файл или терминал исторически медленный (терминалы или консоли по-прежнему медленные), запись посимвольно неэффективна, запись порции байтов гораздо эффективнее. - person Some programmer dude; 04.04.2018

Стандартный поток вывода (cout): cout — это экземпляр класса ostream. cout используется для вывода на стандартное устройство вывода, которым обычно является экран дисплея. Данные, необходимые для отображения на экране, вставляются в стандартный поток вывода (cout) с помощью оператора вставки (<<).

Небуферизованный стандартный поток ошибок (cerr): cerr – это стандартный поток ошибок, который используется для вывода ошибок. Это также экземпляр класса ostream. Поскольку cerr не буферизуется, он используется, когда нам нужно немедленно отобразить сообщение об ошибке. У него нет буфера для хранения сообщения об ошибке и последующего отображения.

Буферизованный стандартный поток ошибок (clog): это также экземпляр класса ostream и используется для отображения ошибок, но в отличие от cerr ошибка сначала вставляется в буфер и сохраняется в буфер, пока он не будет полностью заполнен.

дальнейшее чтение: basic-input-output-c

person roottraveller    schedule 12.09.2017
comment
until it is not fully filled. -- разве здесь не должно быть until it IS fully filled? - person Gabriel Staples; 23.10.2020

Разница этих 3-х потоков заключается в буферизации.

  1. With cerr, the output flushs
    • immediately (because cerr does not use buffer).
  2. With clog, the output flushs
    • after you finish your current function.
    • явно вызвать функцию flush.
  3. With cout, the output flushs
    • after you have call to any output streams (cout, cerr, clog).
    • после того, как вы закончите свою текущую функцию.
    • явно вызвать функцию flush.

Пожалуйста, проверьте следующий код и запустите DEBUG через 3 строки: 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";
}
person Duc-Viet Ha    schedule 01.11.2017

  • Используйте cout для стандартного вывода.
  • Используйте cerr для отображения ошибок.
  • Используйте clog для ведения журнала.
person David Vargas    schedule 07.06.2015
comment
Неправильно, cerr медленнее, чем cout из-за отсутствия буфера! Так же, как запись против printf - person 陳 力; 19.05.2018

Из проекта стандартного документа С++ 17:

30.4.3 Объекты узкого потока [narrow.stream.objects]

istream cin;

1 Объект cin управляет вводом из буфера потока, связанного с объектом stdin, объявленным в <cstdio> (30.11.1).

2 После инициализации объекта cin cin.tie() возвращает &cout. В остальном его состояние такое же, как требуется для basic_ios<char>::init (30.5.5.2).

ostream cout;

3 Объект cout управляет выводом в буфер потока, связанный с объектом stdout, объявленным в <cstdio> (30.11.1).

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;

6 Объект clog управляет выводом в буфер потока, связанный с объектом stderr, объявленным в <cstdio> (30.11.1).

Обсуждение...

cout пишет stdout; cerr и clog до stderr

Стандартный выход (stdout) предназначен для получения безошибочного, недиагностического вывода из программы, например, вывода успешной обработки, который может быть отображен конечному пользователю или передан на какой-либо последующий этап обработки.

Стандартная ошибка (stderr) предназначена для диагностических выходных данных, таких как предупреждения и сообщения об ошибках, которые указывают, что программа не вывела или могла не выдать ожидаемые пользователем выходные данные. Этот ввод может отображаться для конечного пользователя, даже если выходные данные передаются на дальнейшую стадию обработки.

cin и cerr привязаны к cout

Они оба очищают cout перед тем, как самостоятельно обрабатывать операции ввода-вывода. Это гарантирует, что подсказки, отправленные на cout, видны до того, как программа заблокирует чтение ввода из cin, и что более ранний вывод в cout сбрасывается перед записью ошибки через cerr, что сохраняет сообщения в хронологическом порядке их создания, когда оба направлены на один и тот же терминал/файл/и т.д..

Это контрастирует с clog - если вы пишете туда, он не будет буферизоваться и ни к чему не привязан, поэтому он будет буферизовать приличное количество журналов перед сбросом. Это дает самую высокую пропускную способность сообщений, но означает, что сообщения могут быть не видны быстро потенциальному потребителю, читающему терминал или следящему за журналом.

person Tony Delroy    schedule 26.02.2018

И cout, и clog буферизуются, но cerr не буферизуется, и все они являются предопределенными объектами, которые являются экземплярами класса ostream. Основное использование этих трех: cout используется для стандартного ввода, тогда как clog и cerr используются для отображения ошибок. Основная причина, по которой cerr не буферизуется, может заключаться в том, что предположим, что у вас есть несколько выходных данных в буфере, а в коде упоминается исключение ошибки, тогда вам нужно немедленно отобразить эту ошибку, что можно сделать с помощью cerr эффективно.

Пожалуйста, поправьте меня, если я ошибаюсь.

person Kashif Faraz Shamsi    schedule 10.08.2017