简体   繁体   English

如何捕获printf的输出?

[英]How to capture output of printf?

I am calling a function funcB from funcA . 我打电话的功能funcBfuncA funcB uses several printf statements to output data. funcB使用几个printf语句来输出数据。 Is there a way for me to capture that data via funcA ? 有没有办法通过funcA捕获数据? I can not modify funcB . 我无法修改funcB

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

funcA(){
    funcB();
}

(This answer is a corrected version based on this answer .) (这个答案是基于这个答案的更正版本。)

This answer is POSIX centric. 这个答案是以POSIX为中心的。 Use open to create a file descriptor for the file you want to redirect to. 使用open为要重定向到的文件创建文件描述符。 Then, use dup2 to STDOUT_FILENO to change stdout to write to the file instead. 然后,使用dup2STDOUT_FILENO来改变stdout以写入文件。 But, you'll want to dup the STDOUT_FILENO before you do that, so you can restore stdout with another dup2 . 但是,在执行此操作之前,您需要dup STDOUT_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);

If funcB is using std::cout , use std::cout.flush() instead of fflush(stdout) . 如果funcB使用std::cout ,则使用std::cout.flush()而不是fflush(stdout)

If you want to manipulate C++ streams more directly, you can use Johnathan Wakely's answer . 如果您想更直接地操作C ++流,可以使用Johnathan Wakely的答案

If nothing else in your program uses printf , you can write your own version and link it explicitly. 如果您的程序中没有其他内容使用printf ,您可以编写自己的版本并明确链接它。 The linker will not look in the standard library if the function is already defined. 如果已定义该函数,则链接器将不会查找标准库。 You can probably use vsprintf for the implementation, or some safer version with overrun checking if it is supplied by your compiler. 您可以使用vsprintf进行实现,或者使用溢出检查的某些更安全的版本(如果它是由编译器提供的)。

If you're willing to play a dirty game interposing on printf you can 'steal' its output doing something like: 如果你愿意在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;
}

You could use a flag to indicate how to handle the instances where you want printf to work as normal. 您可以使用标志来指示如何处理您希望printf正常工作的实例。 (Eg map it onto fprintf or use dlsym() /similar to find the real call). (例如将其映射到fprintf或使用dlsym() /类似于查找真实调用)。

You could also use realloc to manage the size of the buffer more sensibly. 您还可以使用realloc更明智地管理缓冲区的大小。

Put funcB in a separate program. funcB放在一个单独的程序中。 You can then capture its standard output, eg by piping or by redirecting it to a file. 然后,您可以捕获其标准输出,例如通过管道或将其重定向到文件。 How to do that generally depends on the OS and is outside the realm of C++. 如何做到这一般取决于操作系统,并且超出了C ++的范围。

Alternatively, maybe you can redirect your funcA process' standard output to a file, then call FuncB , and retrieve the output from the file. 或者,您可以将funcA进程的标准输出重定向到文件,然后调用FuncB ,并从文件中检索输出。

Again, how to do that is outside the realm of C++ and depends on the OS. 同样,如何做到这一点超出了C ++的范围,并取决于操作系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM