Pregunta

En ANSI C ++, ¿cómo puedo asignar la secuencia cout a un nombre de variable? Lo que quiero hacer es, si el usuario ha especificado un nombre de archivo de salida, envío la salida allí, de lo contrario, lo envío a la pantalla. Entonces algo 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 también como una función Macro:

#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 evitarlo si pudiera. ¿Algunas ideas?

¿Fue útil?

Solución

Use una referencia. Tenga en cuenta que la referencia debe ser de tipo std :: ostream , no std :: ofstream , ya que std :: cout es un std :: ostream , por lo que debe utilizar 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);

Otros consejos

Supongo que su programa se comporta como herramientas estándar de Unix, que cuando no se le da un archivo, se escribirá en la salida estándar, y cuando se le dé un archivo, se escribirá en ese archivo. Puede redirigir cout para escribir en otro búfer de flujo. Mientras su redirección esté activa, todo lo escrito en cout se escribe de forma transparente en el destino que usted designó. Una vez que el objeto de redirección sale del alcance, la secuencia original se coloca y la salida volverá a escribir 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é viva en main. Puede hacerlo más "producción lista" haciéndolo no copiable, porque no está listo para ser copiado: si la copia queda fuera de alcance, ya restauraría la secuencia original.

Puede encontrar una explicación muy detallada de cómo hacer esto aquí: http://groups.google.com/group/ comp.lang.c ++ / msg / 1d941c0f26ea0d81? pli = 1

Esperemos que alguien escriba esto más claramente para que el desbordamiento de la pila tome los puntos ...

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)

Creo que Adam está en el camino correcto, pero no creo que pueda asignar referencias; en su lugar, debe 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. Entonces, tal vez sea mejor verificar algo para ver si se proporcionó / ??existe un archivo y crear el tipo de flujo apropiado.

Esto tardó aproximadamente dos horas en llegar. Básicamente, tengo una clase externa que ejecuta un conjunto de pruebas. Envío 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 transmisión diferente por prueba. De todos modos, quería pasar en la corriente 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;
};
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top