我发现构建程序参数列表的最简单方法是作为字符串向量。但是,execv期望第二个参数的字符数组。让它接受字符串向量的最简单方法是什么?
答案 0 :(得分:13)
execv()
只接受一个字符串指针数组。没有办法让它接受任何其他东西。它是一个标准接口,可以从每种托管语言调用,而不仅仅是C ++。
我已经测试了这个:
std::vector<string> vector;
const char *programname = "abc";
const char **argv = new const char* [vector.size()+2]; // extra room for program name and sentinel
argv [0] = programname; // by convention, argv[0] is program name
for (int j = 0; j < vector.size()+1; ++j) // copy args
argv [j+1] = vector[j] .c_str();
argv [vector.size()+1] = NULL; // end of arguments sentinel is NULL
execv (programname, (char **)argv);
答案 1 :(得分:2)
execv
的原型是:
int execv(const char *path, char *const argv[]);
这意味着参数列表是一个指向以null结尾的c字符串的指针数组。
你有vector<string>
。找出该向量的大小,并创建一个指向char的指针数组。然后循环遍历向量,并为向量中的每个string
设置数组的相应元素以指向它。
答案 2 :(得分:1)
你不能改变execv的工作方式(不管怎么说都不容易),但你可以用你想要的方式重载函数名称:
int execv(const string& path, const vector<string>& argv) {
vector<const char*> av;
for (const string& a : argv) {
av.push_back(a.c_str());
av.push_back(0);
return execv(path.c_str(), &av[0]);
}
当然,这可能会引起一些混乱。除了execv()之外,你最好给它一个名字。
注意:我只是把它打成了我的头顶。它可能无法正常工作。它甚至可能无法编译; - )
答案 3 :(得分:1)
我刚才偶然发现了同样的问题。
我最终在std::basic_string<char const*>
中构建了参数列表。然后我调用了c_str()
方法并对结果执行了const_cast<char* const*>
,以execv
接受的格式获取列表。
对于复合参数,我new
ed字符串(由普通字符组成的普通字符串;)),取出c_str()
并让它们泄漏。
由于给定字符串类型的const_cast
方法返回const
iirc,因此删除其他c_str()
时需要char const* const*
。输入这个,我想我可以使用std::basic_string<char*>
,但我想我有理由......
我很清楚const
- 投射和内存泄漏看起来有点粗鲁,确实是不好的做法,但是因为execv
取代整个过程无论如何都无关紧要。
答案 4 :(得分:1)
是的,通过利用矢量使用的内部数组,它可以非常干净地完成。最好不要在向量中使用C ++字符串,并且const_cast字符串文字和string.c_str()用于char *。
这样可行,因为标准保证其元素是连续存储的(参见https://stackoverflow.com/a/2923290/383983)
#include <vector>
using std::vector;
int main() {
vector<char*> commandVector;
// do a push_back for the command, then each of the arguments
commandVector.push_back(const_cast<char*>("echo"));
commandVector.push_back(const_cast<char*>("testing"));
commandVector.push_back(const_cast<char*>("1"));
commandVector.push_back(const_cast<char*>("2"));
commandVector.push_back(const_cast<char*>("3"));
// push NULL to the end of the vector (execvp expects NULL as last element)
commandVector.push_back(NULL);
const int status = execvp(command[0], &command[0]);
return 0;
}
执行const_cast以避免“已弃用从字符串常量转换为'char *'”。字符串文字在C ++中实现为'const char *'。 const_cast是这里最安全的转换形式,因为它只删除了const而且没有做任何其他有趣的事情。 execvp无论如何都不会编辑这些值。
如果你想避免所有强制转换,你必须通过将所有值复制到'char *'类型来使这段代码复杂化。
虽然如果知道要传递给execv / execl的参数个数,但在C中写这个更容易。