【问题标题】:redirect output of an function printing to console to string将函数打印的输出重定向到控制台到字符串
【发布时间】:2013-10-21 02:52:52
【问题描述】:

假设我们有一个将文本打印到控制台的函数,我们无法控制源,但我们可以调用它。例如

void foo() {
    std::cout<<"hello world"<<std::endl; 
    print_to_console(); // this could be printed from anything
}

是否可以在不改变函数本身的情况下将上述函数的输出重定向到字符串?

我不是在寻找通过终端执行此操作的方法

【问题讨论】:

  • 您是否要求临时重定向std::cout。或函数print_to_console() 的输出暂时仅用于此调用或函数foo()

标签: c++ c++11


【解决方案1】:

是的。这是可以做到的。这是一个小演示:

#include <sstream>
#include <iostream>

void print_to_console() {
    std::cout << "Hello from print_to_console()" << std::endl;
}

void foo(){
  std::cout<<"hello world"<<std::endl; 
  print_to_console(); // this could be printed from anything
}
int main()
{
    std::stringstream ss;

    //change the underlying buffer and save the old buffer
    auto old_buf = std::cout.rdbuf(ss.rdbuf()); 

    foo(); //all the std::cout goes to ss

    std::cout.rdbuf(old_buf); //reset

    std::cout << "<redirected-output>\n" 
              << ss.str() 
              << "</redirected-output>" << std::endl;
}

输出:

<redirected-output>
hello world
Hello from print_to_console()
</redirected-output>

Online Demo

【讨论】:

  • 哇,我完全忘记了你可以这样做。
  • auto *old_buf?需要指针吗? auto 不会丢弃指针。
  • @Praetorian:不。不需要*。我是出于习惯写的:P
  • 但我认为你不应该使用 auto ptr :p
  • 如果他们使用 printf、puts、write 等会发生什么?
【解决方案2】:

@Andre 在我的第一个答案的评论中问:

如果他们使用 printf、puts、write 等会发生什么? ——安德烈·科斯图尔

对于printf,我想出了以下解决方案。它仅适用于 POSIX,因为 fmemopen 仅适用于 POSIX,但您可以使用 temporary 文件来代替 - 如果您想要 portable 解决方案。基本思路是一样的。

#include <cstdio>

void print_to_console() {
    std::printf( "Hello from print_to_console()\n" );
}

void foo(){
  std::printf("hello world\n");
  print_to_console(); // this could be printed from anything
}

int main()
{
    char buffer[1024];
    auto fp = fmemopen(buffer, 1024, "w");
    if ( !fp ) { std::printf("error"); return 0; }

    auto old = stdout;
    stdout = fp;

    foo(); //all the std::printf goes to buffer (using fp);

    std::fclose(fp);
    stdout = old; //reset

    std::printf("<redirected-output>\n%s</redirected-output>", buffer);
}

输出:

<redirected-output>
hello world
Hello from print_to_console()
</redirected-output>

Online Demo.

【讨论】:

  • 不要把扳手扔进去……但这对流和标准输出都有效吗?也许重新打开文件描述符 1 可能适用于这两种情况。 (仍然假设 POSIX)
【解决方案3】:
class buffer
    : public std::streambuf
{
public:
    buffer(std::ostream& os)
        : stream(os), buf(os.rdbuf())
    { }

    ~buffer()
     {
         stream.rdbuf(buf);
     }

private:
    std::ostream& stream;
    std::streambuf* buf;
};

int main()
{
    buffer buf(std::cout);
    std::stringbuf sbuf;

    std::cout.rdbuf(sbuf);

    std::cout << "Hello, World\n";
}

【讨论】:

  • 如果你想让它成为 RAII,为什么不做something like this 让客户端代码更干净。 :-)
猜你喜欢
  • 1970-01-01
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-14
  • 1970-01-01
  • 1970-01-01
  • 2012-03-11
相关资源
最近更新 更多