Was ist der Unterschied zwischen cout, cerr, clog des iostream-Headers in c ++? Wann welches verwenden?

97

Ich habe versucht , den Unterschied zwischen der Erforschung cout, cerrund clogim Internet, konnte aber nicht eine perfekte Antwort finden. Mir ist immer noch nicht klar, wann ich welche verwenden soll. Kann mir jemand durch einfache Programme erklären und eine perfekte Situation veranschaulichen, wann welches zu verwenden ist?

Ich habe diese Seite besucht, die ein kleines Programm auf cerrund zeigt clog, aber die dort erhaltene Ausgabe kann auch mit erhalten werden cout. Ich bin also verwirrt über die genaue Verwendung jedes Einzelnen.

Arlene Batada
quelle
6
Jedes hat einen computer erkannt Strom stdout, stdin(z cin), und stderrdass sie standardmäßig verwendet. Ich glaube clognur cerrmit einer Pufferänderung.
Chris

Antworten:

48

stdoutund stderrsind unterschiedliche Streams, obwohl beide standardmäßig auf die Konsolenausgabe verweisen. Das Umleiten (Verrohren) eines von ihnen (z. B. program.exe >out.txt) würde den anderen nicht beeinflussen.

Im Allgemeinen stdoutsollte für die eigentliche Programmausgabe verwendet werden, während alle Informationen und Fehlermeldungen gedruckt werden sollten stderr, damit, wenn der Benutzer die Ausgabe in eine Datei umleitet, Informationsmeldungen weiterhin auf dem Bildschirm und nicht in der Ausgabedatei gedruckt werden.

riv
quelle
131

Im Allgemeinen verwenden Sie std::coutfür die normale Ausgabe, std::cerrfür Fehler und std::clogfür die "Protokollierung" (was bedeuten kann, was immer Sie wollen).

Der Hauptunterschied besteht darin, dass std::cerrnicht wie die beiden anderen gepuffert wird.


In Bezug auf das alte C stdoutund stderr, std::coutentspricht stdout, während std::cerrund std::clogbeide entsprechen stderr(außer das std::clogist gepuffert).

Ein Programmierer
quelle
Ich habe gelesen, dass clogauch ausgegeben wird cerr. Also, basierend darauf, welches wählst du? Wenn dies clognormalerweise für die "Protokollierung" vorgesehen ist, warum sollte das in den Fehlerstrom aufgenommen werden? Protokolle scheinen eher "normale Protokolle" (auch bekannt coutals "Fehler" zu sein.
void.pointer
@ void.pointer Wie ich in meiner Antwort sagte, beide cerrund clogverwendet die Standardausgabe "Fehler", ist aber cloggepuffert, was möglicherweise der Grund dafür ist cout. Welches für die Fehlerausgabe auswählen? Kommt wohl auf mehr Gründe an, als ich auflisten kann und es muss von Fall zu Fall entschieden werden.
Einige Programmierer Typ
2
Was meinst du mit "gepuffert"?
simplename
4
@simplename Die Ausgabe wird nicht direkt geschrieben, sondern in einem Puffer gespeichert, bis der Puffer geleert wird . Die Ausgabe in eine Datei oder ein Terminal ist historisch langsam (Terminals oder Konsolen sind immer noch langsam), das Schreiben von Zeichen für Zeichen ist ineffektiv, das Schreiben eines Teils von Bytes ist viel effektiver.
Einige Programmierer Typ
14

Standardausgabestream (cout): cout ist die Instanz der ostreamKlasse. coutwird verwendet, um eine Ausgabe auf dem Standardausgabegerät zu erzeugen, bei dem es sich normalerweise um den Bildschirm handelt. Die Daten, die auf dem Bildschirm angezeigt werden müssen, werden coutmit dem Einfügeoperator ( <<) in den Standardausgabestream ( ) eingefügt .

Ungepufferter Standardfehlerstrom (cerr): cerr ist der Standardfehlerstrom, der zur Ausgabe der Fehler verwendet wird. Dies ist auch eine Instanz der ostreamKlasse. Da cerres ungepuffert ist, wird es verwendet, wenn die Fehlermeldung sofort angezeigt werden muss. Es gibt keinen Puffer zum Speichern der Fehlermeldung und späteren Anzeige.

Gepufferter Standardfehlerstrom (Clog): Dies ist auch eine Instanz der ostreamKlasse und wird zum Anzeigen von Fehlern verwendet. Im Gegensatz cerrzum Fehler wird dieser Fehler jedoch zuerst in einen Puffer eingefügt und im Puffer gespeichert, bis er nicht vollständig gefüllt ist.

weiterführende Literatur: Basic-Input-Output-c

Roottraveller
quelle
11

Der Unterschied dieser 3 Streams ist die Pufferung.

  1. Mit cerr wird der Ausgang gespült
    • sofort (weil cerr keinen Puffer verwendet).
  2. Bei Verstopfung wird der Ausgang gespült
    • nachdem Sie Ihre aktuelle Funktion beendet haben.
    • Rufen Sie die Funktion Flush explizit auf.
  3. Mit cout wird der Ausgang gespült
    • nachdem Sie einen Ausgabestream (cout, cerr, clog) aufgerufen haben.
    • nachdem Sie Ihre aktuelle Funktion beendet haben.
    • Rufen Sie die Funktion Flush explizit auf.

Überprüfen Sie den folgenden Code und führen Sie DEBUG in drei Zeilen aus: f (std :: clog), f (std :: cerr), f (std :: out). Öffnen Sie dann 3 Ausgabedateien, um zu sehen, was passiert ist. Sie können diese 3 Zeilen austauschen, um zu sehen, was passieren wird.

#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";
}
Duc-Viet Ha
quelle
10
  • Verwenden Sie cout für die Standardausgabe.
  • Verwenden Sie cerr , um Fehler anzuzeigen .
  • Verwenden Sie Clog für die Protokollierung.
David Vargas
quelle
6
Falsch, cerr ist langsamer als cout, weil es keinen Puffer gibt! Genau wie schreiben vs printf
陳 力
4

Aus einem Entwurf eines C ++ 17-Standarddokuments:

30.4.3 Objekte mit schmalen Streams [Objekte mit schmalen Streams]

istream cin;

1 Das Objekt cinsteuert die Eingabe aus einem Stream-Puffer stdin, der dem in <cstdio>(30.11.1) deklarierten Objekt zugeordnet ist .

2 Nach der cinInitialisierung des Objekts wird cin.tie()zurückgegeben &cout. Sein Zustand ist ansonsten der gleiche wie für basic_ios<char>::init(30.5.5.2) erforderlich .

ostream cout;

3 Das Objekt coutsteuert die Ausgabe in einen Stream-Puffer stdout, der dem in <cstdio>(30.11.1) deklarierten Objekt zugeordnet ist .

ostream cerr;

4 Das Objekt cerrsteuert die Ausgabe in einen Stream-Puffer stderr, der dem in <cstdio>(30.11.1) deklarierten Objekt zugeordnet ist .

5 Nachdem das Objekt cerrinitialisiert wurde, cerr.flags() & unitbufist es ungleich Null und cerr.tie()kehrt zurück &cout. Sein Zustand ist ansonsten der gleiche wie für basic_ios<char>::init(30.5.5.2) erforderlich .

ostream clog;

6 Das Objekt clogsteuert die Ausgabe in einen Stream-Puffer stderr, der dem in <cstdio>(30.11.1) deklarierten Objekt zugeordnet ist .

Diskussion...

coutschreibt an stdout; cerrund clogzustderr

Standard Out ( stdout) soll fehlerfreie, nicht diagnostische Ausgaben vom Programm empfangen, z. B. Ausgaben von erfolgreicher Verarbeitung, die dem Endbenutzer angezeigt oder in eine weitere Verarbeitungsstufe gestreamt werden können.

Standard Error ( stderr) ist für die Diagnoseausgabe vorgesehen, z. B. Warn- und Fehlermeldungen, die darauf hinweisen, dass das Programm die vom Benutzer erwartete Ausgabe nicht oder möglicherweise nicht erzeugt hat. Diese Eingabe kann dem Endbenutzer auch dann angezeigt werden, wenn die Ausgabedaten an eine weitere Verarbeitungsstufe weitergeleitet werden.

cinund cerrsind gebunden ancout

Beide werden gespült, coutbevor E / A-Vorgänge selbst ausgeführt werden. Dadurch wird sichergestellt, dass die an gesendeten coutEingabeaufforderungen sichtbar sind, bevor das Programm die Eingaben blockiert cin, und dass die frühere Ausgabe an coutgeleert wird, bevor ein Fehler durchgeschrieben cerrwird. Dadurch werden die Nachrichten in chronologischer Reihenfolge ihrer Generierung gehalten, wenn beide an dasselbe Terminal / dieselbe Datei / gesendet werden etc..

Dies steht im Gegensatz zu clog: Wenn Sie dort schreiben, wird es nicht gepuffert und ist an nichts gebunden, sodass vor dem Leeren ausreichend große Protokollierungsmengen gepuffert werden. Dies ergibt den höchsten Nachrichtendurchsatz, bedeutet jedoch, dass die Nachrichten für einen potenziellen Verbraucher, der das Terminal liest oder das Protokoll verfolgt, möglicherweise nicht schnell sichtbar sind.

Tony Delroy
quelle
1

Sowohl cout und Clog werden gepuffert aber cerr ist un-buffered und alle diese Objekte sind vordefiniert , die Instanzen der Klasse ostream sind. Die grundlegende Verwendung dieser drei sind cout für Standardeingabe verwendet , während Clog und cerr für zeigt Fehler verwendet wird. Der Hauptgrund, warum cerr nicht gepuffert ist, kann sein, dass Sie mehrere Ausgänge im Puffer haben und eine Fehlerausnahme im Code erwähnt wird. Dann müssen Sie diesen Fehler sofort anzeigen, was von cerr effektiv ausgeführt werden kann.

Bitte korrigieren Sie mich, wenn ich falsch liege.

Kashif Faraz Shamsi
quelle
-3

cout wird normalerweise verwendet, um einige Anweisungen auf dem Benutzerbildschirm anzuzeigen. ex-: cout << "Arlene Batada";

Ausgabe:

Arlene Batada

Devendra singh
quelle
Dies erwähnt nur cout und versucht nicht, es mit cerr oder clog zu vergleichen. OP weiß, was Cout macht.
JPhi1618
Dies gibt keine Antwort auf die Frage. Sobald Sie einen ausreichenden Ruf haben, können Sie jeden Beitrag kommentieren . Geben Sie stattdessen Antworten, die nicht vom Fragesteller geklärt werden müssen . - Von der Überprüfung
kometen
@kometen dies versucht die Frage zu beantworten, auch wenn es eine schlecht geschriebene Antwort ist. Sollte es stattdessen abgelehnt werden, sind Abstimmungen eher für technische Ungenauigkeiten geeignet.
Cristik