Question

Dans ANSI C ++, comment puis-je affecter le flux de cout à un nom de variable? Ce que je veux faire, c’est que si l’utilisateur a spécifié un nom de fichier de sortie, j’envoie la sortie là-bas, sinon, l’envoyer à l’écran. Donc, quelque chose comme:

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;

J'ai aussi essayé de le faire en tant que fonction macro:

#define OUTPUT outFileRequested?outFile:cout

OUTPUT << "whatever" << endl;

Mais cela m'a aussi causé une erreur de compilation.

J'ai supposé que je pouvais utiliser un bloc IF-THEN pour chaque sortie, mais j'aimerais éviter cela si je le pouvais. Des idées?

Était-ce utile?

La solution

Utilisez une référence. Notez que la référence doit être de type std :: ostream , pas std :: ofstream , car std :: cout est un std :: ostream , vous devez donc utiliser le plus petit dénominateur commun.

std::ofstream realOutFile;

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

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

Autres conseils

Je suppose que votre programme se comporte comme un outil standard Unix, à savoir qu’un fichier n’écrit pas sur la sortie standard et qu’un fichier écrit dans ce fichier. Vous pouvez rediriger cout pour écrire dans un autre tampon de flux. Tant que votre redirection est active, tout ce qui est écrit dans cout est écrit de manière transparente dans la destination que vous avez désignée. Une fois que l'objet de redirection est hors de portée, le flux d'origine est placé et la sortie réécrit à l'écran:

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

Maintenant, cout est redirigé vers le fichier tant que le tube est actif dans main. Vous pouvez le rendre plus "prêt pour la production". en le rendant non copiable, car il n'est pas prêt à être copié: si la copie sort du cadre, le flux d'origine sera déjà restauré.

Vous pouvez trouver une explication très détaillée de la procédure à suivre ici: http://groups.google.com/group/ comp.lang.c ++ / msg / 1d941c0f26ea0d81? pli = 1

Espérons que quelqu'un l'écrira plus clairement pour que le débordement de la pile prenne les points ...

Suivre les traces de Adam Rosenfield , mais résoudre le problème d'initialisation de référence avec les opérateurs ternaires et virgules:

bool outFileRequested = false;

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

outFile << "some witty remark";

(Testé dans VS)

Je pense qu'Adam est sur la bonne voie, mais je ne pense pas que vous puissiez attribuer des références - vous devez utiliser un pointeur à la place:

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

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

vous pouvez ensuite définir une référence comme étant la valeur du pointeur, mais elle ne serait pas globale

std::ostream & outFile = *poutFile;

Je ne suis pas sûr que vous puissiez affecter cout à une variable de type ofstream. cout est un objet de type ostream (alors que cin est de type istream) et je ne suis pas sûr que l'un hérite de l'autre. Donc, il serait peut-être préférable de vérifier si un fichier a été attribué / existe et de créer le type de flux approprié.

Cela nous a pris environ deux heures. En gros, une classe externe exécute une suite de tests. J'envoie un délégué pour exécuter les tests, donc pour avoir accès à la sortie, je dois envoyer un flux de sortie. J'imagine que j'aurais pu créer un flux différent par test. En tout cas, je voulais passer dans l’officiel pour pouvoir l’utiliser plus tard.

// 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;
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top