【问题标题】:How to capture output of printf?如何捕获 printf 的输出?
【发布时间】:2012-06-19 22:17:16
【问题描述】:

我正在从funcA 调用函数funcBfuncB 使用多个 printf 语句来输出数据。 有没有办法让我通过funcA 捕获这些数据? 我无法修改funcB

funcB(){
     printf( "%s", "My Name is" );
     printf( "%s", "I like ice cream" );
}

funcA(){
    funcB();
}

【问题讨论】:

  • 如果funcB 不打印它的输出,而是将它返回给funcA 怎么办?从您提供的抽象描述中很难说,更具体。
  • “这是一个 C++ 问题” - 在我看来,它更像是一个 C 问题。如果是 C++,你可以这样做:this.
  • 对我来说,这更像是一个特定于操作系统的问题,正如我在回答中提到的那样。

标签: c++ printf


【解决方案1】:

如果您的程序中没有其他内容使用printf,您可以编写自己的版本并显式链接它。如果函数已经定义,链接器将不会在标准库中查找。您可能可以使用vsprintf 来实现,或者使用一些更安全的版本来检查是否由您的编译器提供。

【讨论】:

    【解决方案2】:

    (此答案是基于this answer的更正版本。)

    这个答案是以 POSIX 为中心的。使用open 为要重定向到的文件创建文件描述符。然后,使用dup2STDOUT_FILENOstdout 改为写入文件。但是,您需要先dupSTDOUT_FILENO,然后再使用另一个dup2 恢复stdout

    fflush(stdout);
    int stdout_fd = dup(STDOUT_FILENO);
    int redir_fd = open(redirected_filename, O_WRONLY);
    dup2(redir_fd, STDOUT_FILENO);
    close(redir_fd);
    funcB();
    fflush(stdout);
    dup2(stdout_fd, STDOUT_FILENO);
    close(stdout_fd);
    

    如果funcB 使用的是std::cout,请使用std::cout.flush() 而不是fflush(stdout)

    如果你想更直接地操作 C++ 流,你可以使用Johnathan Wakely's answer

    【讨论】:

    • 如何将标准输出再次还原到屏幕上?
    • 我在close(stdout_fd); 之后附加了cout << "should go" <<endl; printf("to normal again\n");,但我在屏幕上看不到这个输出,在“redirected_filename.txt”中也没有。
    • @Viesturs 您可能需要调整线路刷新规则,但如果您手动刷新输出应该存在。如果不是,我预计您正在测试的代码会搞砸。
    • 如何进行线路冲洗?
    • @user1902689:谢谢。 R. 的回答对我很有启发。
    【解决方案3】:

    如果你愿意在printf 上玩一个肮脏的游戏,你可以“窃取”它的输出,比如:

    #include <stdio.h>
    #include <stdarg.h>
    
    static char buffer[1024];
    static char *next = buffer;
    
    static void funcB(){
         printf( "%s", "My Name is" );
         printf( "%s", "I like ice cream" );
    }
    
    static void funcA(){
        funcB();
        // Do stuff iwth buffer here
        fprintf(stderr, "stole: %s\n", buffer);
        next=buffer; // reset for later.
    }
    
    int main() {
      funcA();
    }
    
    
    int printf(const char *fmt, ...) {
       va_list argp;
       va_start(argp, fmt);
       const int ret = vsnprintf(next, sizeof buffer-(next-buffer), fmt, argp);
       next += ret;
       va_end(argp);
       return ret;
    }
    

    您可以使用一个标志来指示如何处理您希望 printf 正常工作的实例。 (例如,将其映射到 fprintf 或使用 dlsym()/similar 来查找真正的呼叫)。

    您还可以使用realloc 更明智地管理缓冲区的大小。

    【讨论】:

      【解决方案4】:

      funcB 放入单独的程序中。然后您可以捕获其标准输出,例如通过管道或将其重定向到文件。如何做到这一点通常取决于操作系统,并且超出了 C++ 的范围。

      或者,也许您可​​以将funcA 进程的标准输出重定向到文件,然后调用FuncB,并从文件中检索输出。

      同样,如何做到这一点超出了 C++ 的范畴,并且取决于操作系统。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-29
        • 1970-01-01
        • 2012-05-10
        相关资源
        最近更新 更多