txt reading outfile open management good c++ cout ofstream

outfile - reading txt c++



Asignación de cout a un nombre de variable (7)

En ANSI C ++, ¿cómo puedo asignar la secuencia de comandos a un nombre de variable? Lo que quiero hacer es que, si el usuario ha especificado un nombre de archivo de salida, envíe la salida allí, de lo contrario, envíela a la pantalla. Entonces algo así como:

ofstream outFile; if (outFileRequested) outFile.open("foo.txt", ios::out); else outFile = cout; // Will not compile because outFile does not have an // assignment operator outFile << "whatever" << endl;

Intenté hacer esto como una función de Macro también:

#define OUTPUT outFileRequested?outFile:cout OUTPUT << "whatever" << endl;

Pero eso también me dio un error de compilación.

Supuse que podría usar un bloque IF-THEN para cada salida, pero me gustaría evitar eso si pudiera. ¿Algunas ideas?


Creo que Adam está en el camino correcto, pero no creo que pueda asignar referencias; en su lugar, necesita usar un puntero:

std::ofstream realOutFile; std::ostream * poutFile; if(outFileRequested) { realOutFile.open("foo.txt", std::ios::out); poutFile = &realOutFile; } else poutFile = &std::cout;

podría definir una referencia para que sea el valor del puntero, pero no sería global

std::ostream & outFile = *poutFile;


No estoy seguro de que pueda asignar cout a una variable de tipo de flujo. cout es un objeto de tipo ostream (mientras que cin es de tipo istream) y no estoy seguro de que uno herede del otro. Por lo tanto, tal vez sea mejor abordar algo para ver si se proporcionó / ​​existe un archivo y crear el tipo de flujo apropiado.



Siguiendo las pistas de Adam Rosenfield , pero arreglando el problema de inicialización de referencia con operadores ternarios y de coma:

bool outFileRequested = false; std::ofstream realOutFile; std::ostream & outFile = outFileRequested ? realOutFile.open("foo.txt", std::ios::out), realOutFile : std::cout; outFile << "some witty remark";

(Probado en VS)


Supongo que su programa se comporta como las herramientas estándar de Unix, que cuando no se da un archivo escribirá en la salida estándar, y cuando se le dé un archivo escribirá en ese archivo. Puedes redirigir cout para escribir en otro buffer de transmisión. Mientras su redireccionamiento esté activo, todo lo escrito para cout se escribe de forma transparente en el destino que usted designó. Una vez que el objeto de redirección sale del alcance, se coloca la secuencia original y la salida volverá a escribirse en la pantalla:

struct CoutRedirect { std::streambuf * old; CoutRedirect():old(0) { // empty } ~CoutRedirect() { if(old != 0) { std::cout.rdbuf(old); } } void redirect(std::streambuf * to) { old = std::cout.rdbuf(to); } } int main() { std::filebuf file; CoutRedirect pipe; if(outFileRequested) { file.open("foo.txt", std::ios_base::out); pipe.redirect(&file); } }

Ahora, cout se redirige al archivo siempre que la tubería esté activa en main. Puede hacerlo más "listo para producción" al hacer que no se pueda copiar, porque no está listo para ser copiado: si la copia sale del alcance, ya restauraría la transmisión original.


Use una referencia. Tenga en cuenta que la referencia debe ser del tipo std::ostream , not std::ofstream , ya que std::cout es std::ostream , por lo que debe usar el mínimo común denominador.

std::ofstream realOutFile; if(outFileRequested) realOutFile.open("foo.txt", std::ios::out); std::ostream & outFile = (outFileRequested ? realOutFile : std::cout);


Esto tomó alrededor de dos horas en llegar. Básicamente, tengo una clase externa ejecutando un conjunto de pruebas. Envié un delegado para ejecutar las pruebas, por lo que para tener acceso a la salida necesito enviar una secuencia de salida. Supongo que podría haber hecho una secuencia diferente por prueba. De todos modos, quería pasar en el flujo para ser utilizado más tarde.

// Main code to create Test Suite Object ofstream debugFile("debug.txt"); TestSuiteObject* myTestSuite = new TestSuiteObject(&debugFile); // Test Suite Object class TestSuiteObject: public Test::Suite { public: TestSuiteObject(std::ofstream* debug) : m_debug(*debug) { m_debug << "some witty remark" << std::endl; TEST_ADD(TestSuiteObject::test1); TEST_ADD(TestSuiteObject::test2); TEST_ADD(TestSuiteObject::test3); } void test1(); void test2(); void test3(); private: std::ofstream& m_debug; };