2009-01-09 221 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; 
};