Frage

Wie kann ich in ANSI C ++ dem Cout -Stream einem variablen Namen zuweisen? Ich möchte, wenn der Benutzer einen Ausgabedateinamen angegeben hat, sende ich dort aus der Ausgabe. Andernfalls sende ich ihn auf den Bildschirm. Also so etwas wie:

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;

Ich habe dies auch als Makrofunktion versucht:

#define OUTPUT outFileRequested?outFile:cout

OUTPUT << "whatever" << endl;

Aber das gab mir auch einen Compiler -Fehler.

Ich nahm an, ich könnte entweder einen wenn-dann-Block für jede Ausgabe verwenden, aber ich möchte das vermeiden, wenn ich könnte. Irgendwelche Ideen?

War es hilfreich?

Lösung

Verwenden Sie eine Referenz. Beachten Sie, dass die Referenz vom Typ sein muss std::ostream, nicht std::ofstream, seit std::cout ist ein std::ostream, Sie müssen also den am wenigsten gebräuchlichen Nenner verwenden.

std::ofstream realOutFile;

if(outFileRequested)
    realOutFile.open("foo.txt", std::ios::out);

std::ostream & outFile = (outFileRequested ? realOutFile : std::cout);

Andere Tipps

Ich gehe davon aus, dass sich Ihr Programm wie Standard -UNIX -Tools verhält, wenn keine Datei an die Standardausgabe geschrieben wird und wenn eine Datei in diese Datei geschrieben wird. Sie können umleiten cout in einen anderen Stream -Puffer schreiben. Solange Ihre Umleitung lebt, wird alles, was auf Cout geschrieben wurde, transparent an das von Ihnen festgelegte Ziel geschrieben. Sobald das Umleitungsobjekt aus dem Umfang ausgeht, wird der ursprüngliche Stream ausgegeben und die Ausgabe wird erneut auf den Bildschirm geschrieben:

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);
    }
}

Jetzt wird Cout in die Datei umgeleitet, solange die Pfeife im Main lebt. Sie können es "Produktion bereit" machen, indem Sie es nicht schöpferbar machen, da es nicht bereit ist, kopiert zu werden: Wenn die Kopie aus dem Umfang ausgeht, wird der ursprüngliche Stream bereits wiederhergestellt.

Sie finden eine sehr detaillierte Erklärung, wie dies hier zu tun ist:http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81?pli=1

Hoffentlich schreibt jemand dies klarer auf, damit Stack Overflow die Punkte nimmt ...

Folgen Adam Rosenfield's Tracks, aber das Problem der Referenzinitialisierung mit ternären und Comma -Operatoren behoben:

bool outFileRequested = false;

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

outFile << "some witty remark";

(Getestet in vs)

Ich denke, Adam ist auf dem richtigen Weg, aber ich glaube nicht, dass Sie Referenzen zuweisen können - Sie müssen stattdessen einen Zeiger verwenden:

std::ofstream realOutFile;
std::ostream * poutFile;

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

Sie könnten dann einen Verweis als den Wert des Zeigers definieren, aber er wäre nicht global

std::ostream & outFile = *poutFile;

Ich bin mir nicht sicher, ob Sie eine Variable von Stream Cout zuweisen können. Cout ist ein Objekt vom Typ ostream (während CIN vom Typ iStream ist) und ich bin mir nicht sicher, ob einer von der anderen erbt. Vielleicht ist etwas, das überprüft wird, ob eine Datei angegeben/existiert, und das Erstellen des entsprechenden Stream -Typs wäre ein besserer Ansatz.

Dies dauerte ungefähr zwei Stunden. Grundsätzlich habe ich eine externe Klasse, die eine Testsuite ausführt. Ich sende einen Delegierten ein, um die Tests auszuführen. Um Zugriff auf die Ausgabe zu haben, muss ich einen Ausgabestream senden. Ich glaube, ich hätte einen anderen Strom pro Test machen können. Wie auch immer, ich wollte im Ofstream weitergeben, um später verwendet zu werden.

// 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;
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top