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

现在,只要管道在 main 中存在,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

我认为亚当走在正确的轨道上,但我认为您不能分配引用-您需要改用指针:

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 回答
0

我不确定您是否可以将 cout 分配给 ofstream 类型的变量。cout 是 ostream 类型的对象(而 cin 是 istream 类型),我不确定一个对象是否继承自另一个对象。因此,也许检查文件是否已给出/存在并创建适当的流类型将是一种更好的方法。

于 2009-01-09T16:23:54.533 回答
0

这花了大约两个小时才得到。基本上,我有一个运行测试套件的外部类。我发送了一个委托来运行测试,所以为了访问输出,我需要发送一个输出流。我想我可以为每个测试做一个不同的流。无论如何,我想传入 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 回答