- cout apunta a la salida estándar STDOUT (texto de resultado esperado de un programa);
- cerr y clog apuntan a STDERR (salida de errores y cualquier otra porquería).
#include <iostream> using namespace std; int main() { cout << "A\n"; cerr << "B\n"; clog << "C\n"; return 0; }Al ejecutarlo, obtenemos por pantalla las tres líneas:
test.exe [ENTER] A B CPero resulta interesante saber que podemos redireccionar el STDOUT a un archivo y el STDERR a otro. Ejemplo:
test.exe 1>stdout.txt 2>stderr.txt¿Qué demonios es 1 y 2? Los archivos tienen un descriptor que los identifica, 1 es para la STDOUT, y 2 para STDERR. El signo mayor (>) significa que "quiero redireccionar toda la salida de texto que vaya para este descriptor a este archivo". En el anterior ejemplo logramos obtener dos archivos distintos, stdout.txt que contiene una línea (A), y stderr.txt que contiene dos líneas (B y C).
Generalmente, los logs van a un archivo, no a la pantalla. Aunque por defecto clog mande todo a STDERR, resulta útil redireccionar este stream a un archivo propio (por ejemplo, test.log). De esta forma, podemos hacer uso de clog para "loguear" todo lo que nuestro programa hace.
¿Cómo se redirecciona clog? Básicamente los streams de C++ tienen un streambuf asociado, y éste es el realmente encargado de leer y escribir datos (en la pantalla, en un archivo, en un string en memoria, etc.). Por lo tanto, si creamos un fstream y le colocamos su propio streambuf a clog, podemos usar clog como un "alias" del fstream original (clog va a estar compartiendo el mismo streambuf que el fstream). El código resultante es bastante sencillo:
#include <iostream> #include <fstream> using namespace std; int main() { // Creamos un archivo de salida para logging. ofstream test_log; test_log.open("test.log"); // Obtenemos el streambuf actual de clog (esto // lo usaremos luego para restaurar el streambuf // a su valor original, por si las moscas). streambuf* old_rdbuf = clog.rdbuf(); // Reemplazamos el streambuf de clog con el del archivo. // Ahora ambos streams utilizarán el mismo streambuf (es // decir, escriben en el archivo test.log). clog.rdbuf(test_log.rdbuf()); // Hacemos lo mismo que el ejemplo original. cout << "A\n"; cerr << "B\n"; clog << "C\n"; // Restauramos el viejo streambuf de clog. clog.rdbuf(old_rdbuf); // Cerramos el archivo. test_log.close(); return 0; }Y listo, ahora podemos hacer lo mismo que antes:
test.exe 1>stdout.txt 2>stderr.txtCon lo cual obtenemos tres archivos:
- stdout.txt con la línea A.
- stderr.txt con la línea B.
- test.log con la línea C.