如何配置stdin从C++字符串读取以测试调用C函数的C++代码?
当然可以!这在测试依赖标准输入的C风格函数时简直是刚需,我给你分享几种实用的方案,你可以根据自己的开发平台选择:
可行方案
方案1:POSIX系统下用fmemopen直接映射内存缓冲区
如果你是在Linux、macOS这类POSIX兼容系统上开发,fmemopen函数可以直接把一段内存(比如你的C++字符串)包装成FILE*类型,替换掉标准输入stdin即可。
示例代码:
#include <cstdio> #include <string> // 模拟第三方C函数 void third_party_c_func() { int num; char msg[50]; scanf("%d %s", &num, msg); printf("Read from input: %d, %s\n", num, msg); } // 你的C++测试函数 void test_my_cpp_func(const std::string& test_input) { // 将字符串包装为内存文件流 FILE* mem_stream = fmemopen(const_cast<char*>(test_input.c_str()), test_input.size(), "r"); if (!mem_stream) { perror("Failed to create memory stream"); return; } // 保存原始stdin,测试完要恢复 FILE* original_stdin = stdin; stdin = mem_stream; // 调用依赖scanf的第三方函数 third_party_c_func(); // 恢复标准输入并清理资源 stdin = original_stdin; fclose(mem_stream); } int main() { // 多个测试用例 test_my_cpp_func("100 test_case_1\n"); test_my_cpp_func("200 hello_world\n"); return 0; }
这个方案的优点是代码简洁,不需要额外的系统调用,缺点是不支持Windows平台,如果需要跨平台得看下面的方案。
方案2:跨平台管道重定向法
这种方法通过创建管道,把测试字符串写入管道的写端,再将标准输入重定向到管道的读端,让scanf从管道读取内容。它能适配绝大多数平台,包括Windows(只是Windows需要用系统原生的管道API)。
POSIX平台示例代码:
#include <cstdio> #include <string> #include <unistd.h> #include <fcntl.h> void third_party_c_func() { int num; scanf("%d", &num); printf("Read number: %d\n", num); } void test_my_cpp_func(const std::string& test_input) { int pipe_fds[2]; if (pipe(pipe_fds) == -1) { perror("Failed to create pipe"); return; } // 保存原始stdin的文件描述符 int original_stdin = dup(STDIN_FILENO); if (original_stdin == -1) { perror("Failed to duplicate stdin"); close(pipe_fds[0]); close(pipe_fds[1]); return; } // 将stdin重定向到管道的读端 if (dup2(pipe_fds[0], STDIN_FILENO) == -1) { perror("Failed to redirect stdin"); close(pipe_fds[0]); close(pipe_fds[1]); close(original_stdin); return; } // 关闭管道读端(已经重定向到stdin,不需要保留) close(pipe_fds[0]); // 向管道写端写入测试输入 ssize_t bytes_written = write(pipe_fds[1], test_input.c_str(), test_input.size()); if (bytes_written != static_cast<ssize_t>(test_input.size())) { perror("Failed to write to pipe"); } // 关闭写端,让scanf知道输入结束 close(pipe_fds[1]); // 执行测试 third_party_c_func(); // 恢复原始stdin dup2(original_stdin, STDIN_FILENO); close(original_stdin); } int main() { test_my_cpp_func("300\n"); test_my_cpp_func("400\n"); return 0; }
Windows平台适配提示:
Windows下需要用CreatePipe创建管道,用WriteFile写入测试字符串,再通过SetStdHandle重定向标准输入,核心逻辑和POSIX版本一致,只是API不同。
批量测试的小技巧
把测试逻辑封装成像上面的test_my_cpp_func这样的函数,你就可以轻松循环执行多个测试用例,每个用例传入不同的C++字符串即可,完全不需要手动输入,自动化测试非常方便。
内容的提问来源于stack exchange,提问作者lrleon
相关产品推荐
相关产品推荐

