¿Cuál es la diferencia entre cout, cerr, clog of iostream header en c ++? ¿Cuándo usar cuál?

100

He intentado investigar la diferencia entre cout, cerry clogen Internet, pero no pude encontrar una respuesta perfecta. Todavía no tengo claro cuándo usar cuál. ¿Alguien puede explicarme, a través de programas sencillos, e ilustrar una situación perfecta sobre cuándo usar cuál?

Visité este sitio que muestra un pequeño programa en cerry clog, pero el resultado obtenido allí también se puede obtener usando cout. Entonces, estoy confundido sobre el uso exacto de cada uno.

Arlene Batada
fuente
6
Cada uno tiene una secuencia reconocida por ordenador, stdout, stdin(para cin), y stderrque se usa por defecto. Creo que cloges solo cerrcon un cambio de búfer.
chris

Respuestas:

49

stdouty stderrson transmisiones diferentes, aunque ambas se refieren a la salida de la consola de forma predeterminada. Redirigir (canalizar) uno de ellos (p. Ej.program.exe >out.txt ) no afectaría al otro.

Generalmente, stdoutdebe usarse para la salida real del programa, mientras que toda la información y los mensajes de error deben imprimirse stderr, de modo que si el usuario redirige la salida a un archivo, los mensajes de información aún se imprimen en la pantalla y no en el archivo de salida.

riv
fuente
132

Generalmente se usa std::coutpara resultados normales, std::cerrpara errores y std::clogpara "registro" (que puede significar lo que quiera que signifique).

La principal diferencia es que std::cerrno tiene búfer como los otros dos.


En relación con la antigua C stdouty stderr, std::coutcorresponde a stdout, mientras std::cerry std::clogambos corresponden a stderr(excepto que std::clogestá almacenado en búfer).

Algún tipo programador
fuente
He leído que clogtambién se envía a cerr. Entonces, en base a eso, ¿cuál eliges? Si cloges normalmente para "registro", ¿por qué querría que vaya al flujo de errores? Los registros parecen más "registros normales" (también conocidos como cout) que errores.
void.pointer
@ void.pointer Como dije en mi respuesta, ambos cerry clogusan la salida estándar de "error", pero clogestán almacenados en búfer, lo que podría ser la razón por la que parece más cout. ¿Cuál elegir para la salida de error? Depende, supongo, de más razones de las que puedo enumerar y tiene que decidirse de un caso a otro.
Un tipo programador
3
¿Qué quiere decir con "almacenado"?
simplename
5
@simplename La salida no se escribe directamente, se almacena en un búfer hasta que se vacía el búfer . La salida a un archivo o terminal es históricamente lenta (los terminales o consolas siguen siendo lentos), escribir carácter por carácter es ineficaz, escribir una porción de bytes es mucho más efectivo.
Algún tipo programador
15

Flujo de salida estándar (cout): cout es la instancia de la ostreamclase. coutse utiliza para producir salida en el dispositivo de salida estándar que suele ser la pantalla de visualización. Los datos necesarios para mostrarse en la pantalla se insertan en el flujo de salida estándar ( cout) usando el operador de inserción (<< ).

Secuencia de error estándar sin búfer (cerr): cerr es la secuencia de error estándar que se utiliza para generar los errores. Esta también es una instancia de la ostreamclase. Como cerrestá sin búfer , se usa cuando necesitamos mostrar el mensaje de error inmediatamente. No tiene ningún búfer para almacenar el mensaje de error y mostrarlo más tarde.

Flujo de error estándar almacenado en búfer (obstrucción): también es una instancia de ostreamclase y se utiliza para mostrar errores, pero a diferencia cerrdel error, primero se inserta en un búfer almacenado en búfer y se almacena en el búfer hasta que no se llena por completo.

lectura adicional: basic-input-output-c

roottraveller
fuente
11

La diferencia de estos 3 flujos es el almacenamiento en búfer.

  1. Con cerr, la salida se descarga
    • inmediatamente (porque cerr no usa búfer).
  2. Con obstrucción, la salida fluye
    • después de terminar su función actual.
    • llamar explícitamente a la función flush.
  3. Con cout, la salida fluye
    • después de haber llamado a cualquier flujo de salida (cout, cerr, clog).
    • después de terminar su función actual.
    • llamar explícitamente a la función flush.

Verifique el siguiente código y ejecute DEBUG a través de 3 líneas: f (std :: clog), f (std :: cerr), f (std :: out), luego abra 3 archivos de salida para ver qué sucedió. Puede intercambiar estas 3 líneas para ver qué sucede.

#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
fuente
10
  • Utilice cout para la salida estándar.
  • Utilice cerr para mostrar errores.
  • Utilice una obstrucción para la tala.
David Vargas
fuente
6
¡Incorrecto, cerr es más lento que cout debido a que no tiene búfer! Como escribir vs printf
4

De un borrador de documento estándar C ++ 17:

30.4.3 Objetos de corriente estrecha [narrow.stream.objects]

istream cin;

1 El objeto cincontrola la entrada de un búfer de flujo asociado con el objeto stdin, declarado en <cstdio>(30.11.1).

2 Una vez cininicializado el objeto , cin.tie()vuelve &cout. Por lo demás, su estado es el mismo que el requerido para basic_ios<char>::init(30.5.5.2).

ostream cout;

3 El objeto coutcontrola la salida a un búfer de flujo asociado con el objeto stdout, declarado en <cstdio>(30.11.1).

ostream cerr;

4 El objeto cerrcontrola la salida a un búfer de flujo asociado con el objeto stderr, declarado en <cstdio>(30.11.1).

5 Una vez cerrinicializado el objeto , cerr.flags() & unitbufes distinto de cero y cerr.tie()vuelve &cout. Por lo demás, su estado es el mismo que el requerido para basic_ios<char>::init(30.5.5.2).

ostream clog;

6 El objeto clogcontrola la salida a un búfer de flujo asociado con el objeto stderr, declarado en <cstdio>(30.11.1).

Discusión...

coutescribe a stdout; cerry clogparastderr

Salida estándar (stdout ) está destinado a recibir resultados sin errores ni diagnósticos del programa, como los resultados de un procesamiento exitoso que pueden mostrarse al usuario final o transmitirse a alguna etapa de procesamiento adicional.

Error estándar ( stderr) está destinado a la salida de diagnóstico, como los mensajes de advertencia y error que indican que el programa no ha producido o puede que no haya producido la salida que el usuario podría esperar. Esta entrada se puede mostrar al usuario final incluso si los datos de salida se canalizan a una etapa de procesamiento adicional.

ciny cerrestán atados acout

Ambos se lavan coutantes de manejar las operaciones de E / S ellos mismos. Esto asegura que las solicitudes enviadas a coutsean visibles antes de que los bloques de programa para leer la entrada cin, y que la salida anterior coutse vacíe antes de escribir un error cerr, lo que mantiene los mensajes en orden cronológico de su generación cuando ambos se dirigen al mismo terminal / archivo / etc ..

Esto contrasta con clog: si escribe allí, no se almacenará en búfer y no estará vinculado a nada, por lo que almacenará en búfer cantidades decentes de registro antes de descargar. Esto produce el mayor rendimiento de mensajes, pero significa que los mensajes pueden no ser visibles rápidamente para un consumidor potencial que lee el terminal o sigue el registro.

Tony Delroy
fuente
1

Tanto cout y zuecos se almacenan temporalmente, pero cerr es un-tamponada y todos estos son objetos que son instancias de ostream clase predefinida. El uso básico de estos tres son cout se utiliza para la entrada estándar mientras que zueco y cerr se utiliza para mostrar errores. El punto principal por el que cerr no está almacenado en búfer es porque suponga que tiene varias salidas en el búfer y se menciona una excepción de error en el código, entonces debe mostrar ese error de inmediato, lo que cerr puede hacer de manera efectiva.

Por favor, corríjame si estoy equivocado.

Kashif Faraz Shamsi
fuente