繁体   English   中英

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

[英]Get the last string printed in C/C++

我正在尝试使用 googletest 创建测试仪。 问题是我正在测试的函数返回 void 并打印结果。 我想将最后一个字符串打印到控制台中,以便我可以测试输出。 字符串可能包括\\n

所以我有这个功能:

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 中,而 Test 函数本身(测试器)在 c++ 中。 使用printf打印输出。 我无法更改功能本身。 我正在使用 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("hello\n");
    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/

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

请参阅 IMO 被忽略的旧答案 来自它的示例在此处修改:

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 上是可能的:用文件描述符替换标准输出/错误流,然后读取文件。

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

有一个 API 调用 ( cmd_rsp ) 的解决方案(在C带有源代码here ,当在您的程序中调用时,它会创建一个单独的进程,并通过管道连接到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);

暂无
暂无

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

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