14

ANSI C++ では、cout ストリームを変数名に割り当てるにはどうすればよいですか? 私がやりたいことは、ユーザーが出力ファイル名を指定した場合はそこに出力を送信し、そうでない場合は画面に送信することです。次のようなものです:

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;

これをマクロ関数としても試しました:

#define OUTPUT outFileRequested?outFile:cout

OUTPUT << "whatever" << endl;

しかし、それによってコンパイルエラーも発生しました。

すべての出力に IF-THEN ブロックを使用できると思っていましたが、できればそれは避けたいと思います。何か案は?

4

7 に答える 7

37

参照を使用します。はであるため、参照はタイプstd::ostreamではなくタイプstd::ofstreamである必要があることに注意してください。したがって、最小公分母を使用する必要があります。std::coutstd::ostream

std::ofstream realOutFile;

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

std::ostream & outFile = (outFileRequested ? realOutFile : std::cout);
于 2009-01-09T16:12:46.303 に答える
8

私はあなたのプログラムが標準の UNIX ツールのように動作すると仮定します。つまり、ファイルが指定されていない場合は標準出力に書き込み、ファイルが指定されている場合はそのファイルに書き込みます。リダイレクトcoutして、別のストリーム バッファに書き込むことができます。リダイレクトが有効である限り、cout に書き込まれたものはすべて、指定した宛先に透過的に書き込まれます。リダイレクト オブジェクトがスコープ外になると、元のストリームが置かれ、出力が再び画面に書き込まれます。

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

現在、パイプがメインで有効である限り、cout はファイルにリダイレクトされます。コピーする準備ができていないため、コピー不可にすることで、より「本番対応」にすることができます。コピーが範囲外になると、元のストリームが既に復元されます。

于 2009-01-09T17:35:41.360 に答える
3

これを行う方法の非常に詳細な説明は、http: //groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81? pli= 1 にあります。

スタックオーバーフローがポイントを取るために、誰かがこれをより明確に書いてくれることを願っています...

于 2009-01-09T16:11:51.827 に答える
1

Adam Rosenfieldのトラックに従いますが、三項演算子とコンマ演算子を使用した参照初期化の問題を修正します。

bool outFileRequested = false;

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

outFile << "some witty remark";

(VSでテスト済み)

于 2009-01-09T16:47:51.007 に答える
0

ストリームのタイプの変数にcoutを割り当てることができるかどうかはわかりません。coutはostreamタイプのオブジェクトであり(cinはistreamタイプです)、一方が他方から継承するかどうかはわかりません。したがって、ファイルが指定されているかどうかを確認し、適切なストリームタイプを作成することがより良いアプローチになるかもしれません。

于 2009-01-09T16:23:54.533 に答える
0

これを取得するのに約2時間かかりました。基本的に、テストスイートを実行する外部クラスがあります。テストを実行するデリゲートを送信するので、出力にアクセスするには、出力ストリームで送信する必要があります。テストごとに別のストリームを実行できたと思います。とにかく、後で使用するために ofstream を渡したかったのです。

// 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;
};
于 2010-09-10T22:54:22.040 に答える
0

Adam は正しい軌道に乗っていると思いますが、参照を割り当てることはできないと思います。代わりにポインターを使用する必要があります。

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

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

その後、ポインターの値になるように参照を定義できますが、それはグローバルではありません

std::ostream & outFile = *poutFile;
于 2009-01-09T16:21:22.087 に答える