簡體   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