У чому різниця між cout, cerr, clog of iostream header у c ++? Коли використовувати який?


98

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

Я відвідав цей сайт, який показує невелику програму на cerrі clog, але результати, отримані там, також можна отримати за допомогою cout. Отже, я розгублений щодо точного використання кожного.


6
Кожен з них має потік комп'ютерний впізнавані, stdout, stdin(для cin), і stderrщо він використовує за замовчуванням. Я вважаю, що clogце просто cerrзміна буферизації.
Кріс

Відповіді:


48

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

Як правило, stdoutслід використовувати для фактичного виведення програми, тоді як всю інформацію та повідомлення про помилки слід надрукувати stderr, щоб, якщо користувач перенаправляє вихід у файл, інформаційні повідомлення все ще друкувалися на екрані, а не у вихідному файлі.


131

Як правило, ви використовуєте std::coutдля звичайного виводу, std::cerrпомилок і std::clog"реєстрації" (що може означати все, що ви хочете).

Головна відмінність полягає в тому, що std::cerrвін не буферизується, як інші два.


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


Я читав, що clogтакож виводить на cerr. Тож виходячи з цього, який із них ви оберете? Якщо clogзазвичай це "журналювання", чому я хотів би, щоб воно йшло до потоку помилок? Журнали здаються більше схожими на "звичайні журнали" (вони ж cout), ніж на помилки.
void.pointer

@ void.pointer Як я вже сказав у своїй відповіді, cerrі clogвикористовує стандартний вивід "помилки", але clogбуферизується, що може бути причиною, чому це здається більш схожим cout. Який вибрати для виведення помилок? Гадаю, це залежить від більшої кількості причин, ніж я можу перелічити, і це повинно вирішуватися від випадку до випадку.
Якийсь чувак-програміст

3
що ви маєте на увазі під "буфером"?
проста назва

5
Вивід @simplename не записується безпосередньо, він зберігається в буфері, доки буфер не буде очищений . Вихід у файл або термінал є історично повільним (термінали чи консолі все ще повільні), написання символів за символом неефективне, запис шматка байтів набагато ефективніший.
Якийсь програміст, чувак,

15

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

Небуферований стандартний потік помилок (cerr): cerr це стандартний потік помилок, який використовується для виведення помилок. Це також екземпляр ostreamкласу. Як cerrце небуферізованних тому він використовується , коли необхідно негайно відобразити повідомлення про помилку. Він не має жодного буфера для зберігання повідомлення про помилку та відображення пізніше.

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

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


11

Різниця цих 3 потоків полягає в буферизації.

  1. З cerr вихідний сигнал змивається
    • негайно (оскільки cerr не використовує буфер).
  2. З засміченням вихід змивається
    • після завершення поточної функції.
    • явно викликати функцію flush.
  3. З модом вихід вимивається
    • після виклику будь-яких вихідних потоків (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";
}

10
  • Використовуйте cout для стандартного виводу.
  • Використовуйте cerr, щоб показати помилки.
  • Використовуйте сабо для реєстрації.

6
Неправильно, cerr повільніший за cout через не буфер! Так само, як писати проти printf
陳 力

4

З проекту стандартного документа C ++ 17:

30.4.3 Вузькі об'єкти потоку [Вузькі.потоки.об'єкти]

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якщо ви пишете там, він не буде буферизований і ні до чого не прив’язаний, тому буде буферизувати пристойні розміри журналу перед змиванням. Це дає найвищу пропускну здатність повідомлень, але означає, що повідомлення можуть бути не швидко видимими для потенційного споживача, який читає термінал або зберігає журнал.


1

І cout, і clog буферизуються, але cerr не буферизується, і всі вони є заздалегідь визначеними об'єктами, які є екземплярами класу ostream. Основне використання цих трьох методів cout використовується для стандартного введення, тоді як clog і cerr використовується для відображення помилок. Основним моментом, чому cerr не буферизований, може бути те, що, припустимо, у вас є кілька виходів у буфері, а виняток помилок згадується в коді, тоді вам потрібно негайно відобразити цю помилку, яку cerr може ефективно зробити.

Будь ласка, виправте мене, якщо я помиляюся.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.