我有很多用C编写的第三方函数,希望从stdin
到scanf()
输入。我用C ++编写了其他函数来调用c函数。现在,我正在准备测试,我想用C ++字符串编写输入测试用例。
所以我的问题是,有没有办法表达stdin
应该从C ++字符串而不是标准输入读取?如果我实现了这一点,那么我可以编写几个测试用例,其输入是c ++字符串,而我的C ++函数,它们调用c函数,期望它们从stdin
输入,将被透明地调用。
答案 0 :(得分:0)
我不确定这是多么可移植,但至少在Linux上使用gcc-6.3,你可以重新分配stdin
指向不同的流,然后scanf()会透明地使用,就好像它仍然是从终端读取。如果要从预先存在的字符串中读取,可以使用fmemopen()之类的内容打开该新流,这应该可以在POSIX系统上使用。这允许您从内存块创建FILE*
,例如std::string
的内容。
作为示例,以下代码将scanf()
来自字符串"String with 3.14159 * 2"
的五个值,就好像它们是从终端输入的一样:
#include <cstdio>
#include <iostream>
#include <string>
#include <unistd.h>
int main(int argc, char *argv[])
{ const std::string input("String with 3.14159 * 2");
char s0[16], s1[16], s2[8];
double pi = 3;
int two = -2;
{ FILE *old_stdin = stdin;
FILE* strm = fmemopen((void*)input.c_str(), input.size(), "r");
stdin = strm;
scanf("%s %s %lf %s %d", s0, s1, &pi, s2, &two);
std::cout << "s0=\"" << s0 << "\" s1=\"" << s1 << "\""
<< " pi=" << pi << " s2=\"" << s2 << "\""
<< " two=" << two << std::endl;
stdin = old_stdin;
fclose(strm);
}
scanf("%12s", s0);
std::cout << "Stdin: \"" << s0 << "\"" << std::endl;
return 0;
}
这会产生以下输出:
s0="String" s1="with" pi=3.14159 s2="*" two=2
在将stdin
恢复到正常行为之前,其中第二个scanf()
等待来自终端的输入。
尝试使用dup2()
(使用here)的类似方法很有吸引力,但似乎通过对{返回的值调用fileno()
返回文件描述符{1}}无效(在我的系统上为-1)。