Qual è la differenza tra cout, cerr, clog dell'intestazione iostream in c ++? Quando usare quale?


97

Ho provato a ricercare la differenza tra cout, cerre clogsu internet, ma non sono riuscito a trovare una risposta perfetta. Non mi è ancora chiaro quando usare quale. Qualcuno può spiegarmi, attraverso semplici programmi e illustrare una situazione perfetta su quando usare quale?

Ho visitato questo sito che mostra un piccolo programma su cerre clog, ma l'output ottenuto laggiù può essere ottenuto anche usando cout. Quindi, sono confuso sull'uso esatto di ciascuno.


6
Ognuno ha un flusso di computer-riconosciuta, stdout, stdin(per cin), e stderrche utilizza per impostazione predefinita. Credo clogsia solo cerrcon una modifica del buffering.
chris

Risposte:


48

stdoute stderrsono flussi diversi, anche se entrambi fanno riferimento all'output della console per impostazione predefinita. Il reindirizzamento (piping) di uno di essi (ad esempio program.exe >out.txt) non influirebbe sull'altro.

Generalmente, stdoutdovrebbe essere utilizzato per l'effettivo output del programma, mentre tutte le informazioni ei messaggi di errore dovrebbero essere stampati stderr, in modo che se l'utente reindirizza l'output a un file, i messaggi informativi vengono comunque stampati sullo schermo e non sul file di output.


131

Generalmente si usa std::coutper l'output normale, std::cerrper gli errori e std::clogper il "logging" (che può significare qualunque cosa tu voglia che significhi).

La differenza principale è che std::cerrnon è bufferizzata come gli altri due.


In relazione al vecchio C stdoute stderr, std::coutcorrisponde a stdout, mentre std::cerred std::clogentrambi corrispondono a stderr(tranne che std::clogè tamponato).


Ho letto che cloganche le uscite a cerr. Quindi in base a quello, quale scegli? Se clogè normalmente per "registrazione", perché dovrei volerlo andare al flusso di errore? I log sembrano più "normali log" (aka cout) che errori.
void.pointer

@ void.pointer Come ho detto nella mia risposta, entrambi cerre clogusano l'output "error" standard, ma clogsono bufferizzati, il che potrebbe essere il motivo per cui sembra più simile cout. Quale scegliere per l'output di errore? Dipende, immagino, da più motivi di quanti ne possa elencare e deve essere deciso caso per caso.
Un tizio programmatore l'

3
cosa intendi per "tamponato"?
semplice

5
@simplename L'output non viene scritto direttamente, viene archiviato in un buffer finché il buffer non viene scaricato . L'output su un file o un terminale è storicamente lento (i terminali o le console sono ancora lenti), la scrittura carattere per carattere è inefficace, la scrittura di un blocco di byte è molto più efficace.
Un tizio programmatore il

14

Flusso di output standard (cout): cout è l'istanza della ostreamclasse. coutviene utilizzato per produrre output sul dispositivo di output standard che di solito è lo schermo del display. I dati che devono essere visualizzati sullo schermo vengono inseriti nel flusso di output standard ( cout) utilizzando l'operatore di inserimento ( <<).

Flusso di errore standard senza buffer (cerr): cerr è il flusso di errore standard utilizzato per generare gli errori. Questa è anche un'istanza della ostreamclasse. As noncerr è bufferizzato, quindi viene utilizzato quando è necessario visualizzare immediatamente il messaggio di errore. Non ha alcun buffer per memorizzare il messaggio di errore e visualizzarlo successivamente.

Buffered standard error stream (clog): anche questa è un'istanza di ostreamclasse e viene utilizzata per visualizzare gli errori, ma a differenza cerrdell'errore viene prima inserito in un buffer e memorizzato nel buffer fino a quando non è completamente riempito.

ulteriore lettura: basic-input-output-c


11

La differenza di questi 3 flussi è il buffering.

  1. Con cerr, l'output viene scaricato
    • immediatamente (perché cerr non usa il buffer).
  2. Con l'ostruzione, l'uscita si scarica
    • dopo aver terminato la funzione corrente.
    • chiama esplicitamente la funzione flush.
  3. Con cout, l'uscita svuota
    • dopo aver chiamato qualsiasi flusso di output (cout, cerr, clog).
    • dopo aver terminato la funzione corrente.
    • chiama esplicitamente la funzione flush.

Controlla il codice seguente ed esegui DEBUG su 3 righe: f (std :: clog), f (std :: cerr), f (std :: out), quindi apri 3 file di output per vedere cosa è successo. Puoi scambiare queste 3 righe per vedere cosa succederà.

#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
  • Usa cout per lo standard output.
  • Usa cerr per mostrare gli errori.
  • Usa clog per la registrazione.

6
Sbagliato, cerr è più lento di cout a causa del non buffer! Proprio come write vs printf
陳 力

4

Da una bozza di documento standard C ++ 17:

30.4.3 Oggetti Narrow Stream [narrow.stream.objects]

istream cin;

1 L'oggetto cincontrolla l'input da un buffer di flusso associato all'oggetto stdin, dichiarato in <cstdio>(30.11.1).

2 Dopo che l'oggetto cinè stato inizializzato, cin.tie()ritorna &cout. Il suo stato è altrimenti lo stesso richiesto per basic_ios<char>::init(30.5.5.2).

ostream cout;

3 L'oggetto coutcontrolla l'output in un buffer di flusso associato all'oggetto stdout, dichiarato in <cstdio>(30.11.1).

ostream cerr;

4 L'oggetto cerrcontrolla l'output in un buffer di flusso associato all'oggetto stderr, dichiarato in <cstdio>(30.11.1).

5 Dopo che l'oggetto cerrè stato inizializzato, cerr.flags() & unitbufè diverso da zero e cerr.tie()restituisce &cout. Il suo stato è altrimenti lo stesso richiesto per basic_ios<char>::init(30.5.5.2).

ostream clog;

6 L'oggetto clogcontrolla l'output in un buffer di flusso associato all'oggetto stderr, dichiarato in <cstdio>(30.11.1).

Discussione...

coutscrive a stdout; cerre clogastderr

Standard Out ( stdout) ha lo scopo di ricevere un output non di errore e non diagnostico dal programma, come l'output di un'elaborazione riuscita che può essere visualizzato all'utente finale o trasmesso in streaming in una fase di elaborazione successiva.

Standard Error ( stderr) è inteso per l'output diagnostico, come i messaggi di avviso e di errore che indicano che il programma non ha o potrebbe non aver prodotto l'output che l'utente potrebbe aspettarsi. Questo input può essere visualizzato all'utente finale anche se i dati di output vengono reindirizzati a un'ulteriore fase di elaborazione.

cine cerrsono legati acout

Entrambi svuotano coutprima di gestire le operazioni di I / O. Ciò garantisce che i prompt inviati coutsiano visibili prima dei blocchi di programma da cui leggere l'input cine che l'output precedente coutvenga cancellato prima di scrivere un errore cerr, il che mantiene i messaggi in ordine cronologico della loro generazione quando entrambi sono diretti allo stesso terminale / file / eccetera..

Questo contrasta con clog: se scrivi lì, non verrà bufferizzato e non è legato a nulla, quindi bufferizzerà quantità di registrazione di dimensioni decenti prima dello scaricamento. Ciò produce la massima velocità di trasmissione dei messaggi, ma significa che i messaggi potrebbero non essere rapidamente visibili a un potenziale consumatore che legge il terminale o che segue il registro.


1

Sia cout che clog sono bufferizzati ma cerr non è bufferizzato e tutti questi sono oggetti predefiniti che sono istanze della classe ostream. L'uso di base di questi tre sono cout viene utilizzato per l'input standard mentre clog e cerr viene utilizzato per mostrare gli errori. Il punto principale per cui cerr è un-buffer potrebbe essere dovuto al fatto che supponiamo di avere diversi output nel buffer e che un'eccezione di errore sia menzionata nel codice, quindi è necessario visualizzare immediatamente quell'errore che può essere fatto da cerr in modo efficace.

Perfavore, correggimi se sbaglio.


-3

cout viene solitamente utilizzato per visualizzare alcune istruzioni sullo schermo dell'utente. ex-: cout << "Arlene Batada";

produzione:

Arlene Batada


Questo menziona solo cout e non cerca di confrontarlo con cerr o clog. OP sa cosa fa cout.
JPhi1618

Questo non fornisce una risposta alla domanda. Una volta che avrai una reputazione sufficiente, potrai commentare qualsiasi post ; fornire invece risposte che non richiedono chiarimenti da parte del richiedente . - Dalla recensione
kometen

@kometen questo cerca di rispondere alla domanda, anche se è una risposta scritta male. Avrei dovuto votare negativamente, invece, i voti negativi sono più adatti per imprecisioni tecniche.
Cristik
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.