2009-01-09 220 views
13

在ANSI C++中,如何將變量名賦給變量名?我想要做的是,如果用戶指定了輸出文件名,我在那裏發送輸出,否則發送到屏幕。因此,像:將變量名賦值給變量名

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塊,但是如果可以的話,我想避免這種情況。有任何想法嗎?

回答

34

使用的參考。請注意,參考號必須是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); 
+1

這是一個非常優雅的解決方案。謝謝! – user12576 2009-01-09 17:30:38

0

我認爲亞當在正確的軌道上,但我不認爲你可以指定參考 - 你需要使用,而不是一個指針:

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; 
+0

應該總是比使用指針更喜歡使用引用。它可以通過引用完成。看到上面的固定代碼。 – 2009-01-09 17:03:58

+1

當然,你不能使用一個全局變量和一個引用b/c,你將無法初始化到正確的值。 – KenE 2009-01-09 19:02:33

0

我不確定您可以將cout分配給類型爲流的變量。 cout是ostream類型的對象(而cin是istream類型的),我不確定它是從另一個繼承的。所以,也許檢查一下文件是否被賦予/存在,並創建適當的流類型將是一個更好的方法。

1

亞當羅森菲爾德的軌道,但固定的參考初始化問題與三元和逗號運營商:

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測試)

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是隻要管是活在主重定向到文件中。您可以通過將其設置爲不可複製的方式使其更「生產就緒」,因爲它尚未準備好進行復制:如果副本超出範圍,則會恢復原始流。

+0

我認爲這個結構應該是一個單例。 – 2009-01-09 18:36:24

0

這花了大約兩個小時才能得到。基本上,我有一個運行測試套件的外部類。我發送委託來運行測試,因此爲了訪問輸出,我需要發送一個輸出流。我想我可以在每個測試中做一個不同的流。無論如何,我想通過流入以後使用。

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