我有很多用C编写的第三方函数,它们希望通过scanf()从stdin获得输入。我已经用C++编写了其他调用c函数的函数。现在,我正在准备测试,我想用C++字符串编写输入测试用例。
所以我的问题是,是否有一种方式来表示stdin应该从C++字符串读取,而不是从标准输入中读取?如果我做到了这一点,那么我就可以编写几个输入为c++字符串的测试用例,并且我的C++函数将被透明地调用,这些函数调用c函数需要来自stdin的输入。
发布于 2018-04-06 18:18:05
我不确定这有多容易移植,但至少在Linux上的gcc-6.3中,你可以重新分配stdin指向不同的流,然后scanf()就会透明地使用它,就像它仍然在从终端读取一样。如果您想从一个预先存在的字符串中读取数据,可以使用类似于fmemopen()的方式打开新的流,这在POSIX系统上应该是可用的。这允许您从内存块(例如std::string的内容)创建FILE*。
作为示例,下面的代码将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一样)尝试类似的方法是很有诱惑力的,但是对fmemopen()返回的值调用fileno()返回的文件描述符似乎是无效的(在我的系统上是-1 )。
https://stackoverflow.com/questions/49674407
复制相似问题