2011-04-26 45 views
1

我发现生成我的程序参数列表的最简单方法是作为字符串的向量。但是,execv需要第二个参数的一个字符数组。让它接受字符串的最简单方法是什么?如何将字符串向量传递给execv

+3

你不能“让它接受”任何它并没有书面接受。但是,您可以将您的输入转换为其理解的格式。 – 2011-04-26 23:59:16

回答

10

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

由于将argv [0]设置为程序名,因此它看起来像将程序名两次传递给execv。 – 2011-04-27 00:08:42

+3

是的,'execv()'是如何工作的。 – wallyk 2011-04-27 00:13:12

+0

我从第一行收到各种错误。 – 2011-04-27 00:14:01

1

的原型execv是:

int execv(const char *path, char *const argv[]); 

这意味着参数列表指针为空终止的C字符串的数组。

您有vector<string>。找出该矢量的大小并制作一个指向char的指针数组。然后循环遍历向量,向量中的每个string都将数组的相应元素设置为指向它。

+0

这种方法唯一的问题是'std :: string'存储的数据通常没有null结束符。在调用'execv()'之前,必须使用'std :: string :: c_str()'或者在向量手册中的每个字符串中包含空终止符。 – Hydranix 2016-10-18 00:40:26

1

你不能改变的是如何execv作品(不容易反正),但你可以用一个工作方式重载函数名,你想让它:

int execv(const string& path, const vector<string>& argv) { 
    vector<const char*> av; 
    for (vector<string>::const_iterator i = argv.begin(); i != argv.end(); ++i) 
     av.push_back(i->c_str()); 
    av.push_back(0); 
    return execv(path.c_str(), &av[0]); 
} 

当然,这可能会导致有些混乱。你最好给它一个除execv()之外的名字。

注意:我只是在我头顶键入这个。它可能不起作用。它可能甚至不能编译;-)

1

前段时间我偶然发现了同样的问题。

我最终建立了参数列表std::basic_string<char const*>。然后,我调用c_str()方法,并对结果进行const_cast<char* const*>execv接受的格式获取列表。

对于组成的参数,我new ed字符串(由普通字符组成的普通字符串;)),拿着它们的c_str(),让它们泄漏。

const_cast需要除去额外const作为给定字符串类型的c_str()方法返回一个char const* const* IIRC。打字,我想我可以使用std::basic_string<char*>,但我想我有一个理由...


我清楚地知道,const -casting和内存泄漏看起来有点粗鲁,的确是不好的做法,但因为execv取代了整个过程,它无论如何都不重要。

0

是的,它可以通过利用矢量使用的内部数组相当干净地完成。最好不要在向量中使用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); 

    int status = execvp(command[0], &command[0]); 
    return 0; 
} 

做一个const_cast会避免“从字符串常量‘字符*’不赞成使用的转换”。字符串文字在C++中被实现为'const char *'。 const_cast是在这里强制转换的最安全的形式,因为它只能删除const并且不会做其他有趣的事情。无论如何,execvp不会编辑这些值。

如果你想避免所有的强制转换,你必须将所有的值复制到'char *'类型并不真正值得复杂化。

但如果你想要的参数个数传递给execv/EXECL是已知的,它更容易在C.写这篇

相关问题