获取用C/C++打印的最后一个字符串

Get the last string printed in C/C++

本文关键字:最后一个 字符串 打印 C++ 获取      更新时间:2023-10-16

我正在尝试使用谷歌测试创建一个测试程序。问题是,我正在测试的函数返回void并打印结果。我想把最后一个字符串打印到控制台中,这样我就可以测试输出了。该字符串可以包括CCD_ 1。

所以我有一个功能:

void f_sequence(char sequenceStr[])
{
//logic...
if(condotion1)
printf("somthing1");
else if(condotion2)
printf("somthing2")
(...)
}

然后测试仪:

TEST(TesterGroup, TesterName)
{
f_sequence("input");
EXPECT_EQ("somthing1", /*how do i get the output?*/);
}

有可能吗?

我测试的函数在c中,而测试函数本身(测试人员(在c++中。使用CCD_ 2打印输出。我无法更改函数本身。我使用的是CLion最新版本。

将标准输出重定向到缓冲区。

在Coliru上直播

#include <stdio.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int stdoutSave;
char outputBuffer[BUFFER_SIZE];
void replaceStdout()
{
fflush(stdout); //clean everything first
stdoutSave = dup(STDOUT_FILENO); //save the stdout state
freopen("NUL", "a", stdout); //redirect stdout to null pointer
setvbuf(stdout, outputBuffer, _IOFBF, 1024); //set buffer to stdout
}
void restoreStdout()
{
freopen("NUL", "a", stdout); //redirect stdout to null again
dup2(stdoutSave, STDOUT_FILENO); //restore the previous state of stdout
setvbuf(stdout, NULL, _IONBF, BUFFER_SIZE); //disable buffer to print to screen instantly
}
void printHelloWorld()
{
printf("hellon");
printf("world");
}
int main()
{
replaceStdout();
printHelloWorld();
restoreStdout();
// Use outputBuffer to test EXPECT_EQ("somthing1", outputBuffer);
printf("Fetched output: (%s)", outputBuffer);
return 0;
}

参考文献:http://kaskavalci.com/redirecting-stdout-to-array-and-restoring-it-back-in-c/

我不知道是否可以获得上次打印的内容,但如果在调用测试函数之前控制环境,则可以重定向标准输出的位置,从而将其写入文件,然后进行检查。

看看这个被国际海事组织忽视的老答案。这里修改了它的示例:

FILE *fp_old = stdout;  // preserve the original stdout
stdout = fopen("/path/to/file/you/want.txt","w");  // redirect stdout to anywhere you can open
// CALL YOUR FUNCTION UNDER TEST HERE
fclose(stdout);  // Close the file with the output contents
stdout=fp_old;  // restore stdout to normal
// Re-open the file from above, and read it to make sure it contains what you expect.

两种方式:

如果您使用的是POSIX兼容系统,您可以使用>将程序的输出重定向到一个文件,然后稍后从该文件中读取以确认输出是正确的。

另一种方式是这样的:

freopen("output.txt", "w", stdout);
f_sequence();
freopen("/dev/tty", "w", stdout);

用于POSIX兼容系统。在其他平台上,您需要将"/dev/tty"更改为其他内容。我不知道有什么完全便携的方法可以做到这一点。

然后从output.txt中读取。上面的代码段所做的是更改stdout的内容,以便它打印到一个文件中,而不是普通的stdout。

一个解决方案:您可以编写一个单独的程序来执行函数,在单元测试中,您可以将该程序作为子进程执行并检查输出。这可以用std::system来完成,但要非常小心,不要向它传递任何非常量输入。即使在单元测试中,你也不希望出现shell注入漏洞。存在避免在子流程中使用shell的系统特定功能。

另一种解决方案,至少在POSIX上是可能的:用文件描述符替换标准的out/err流,然后读取文件。

Googletest特有的:似乎有testing::internal::CaptureStdout,它似乎实现了替换标准流的想法。但正如名称空间所暗示的,这不是官方的API,因此可能会在未来发生变化。

API调用(n0(有一个解决方案(在C中(,这里有源代码,当在程序中调用时,会创建一个单独的进程,并通过管道连接到stdinstdout,从中接受命令并通过自动调整大小的缓冲区返回响应。概念与popen(...)相似。

一个简单的用例:

char *buf = NULL;
/// test cmd_rsp
buf = calloc(BUF_SIZE, 1);
if(!buf)return 0;
if (!cmd_rsp("dir /s", &buf, BUF_SIZE))//note the first argument can be any legal command that 
//can be sent via the CMD prompt in windows, 
//including a custom executable
{
printf("%s", buf);
}
else
{
printf("failed to send command.n");
}
free(buf);