c++ 如何将字符串向量传递给execv

soat7uwm  于 2023-05-20  发布在  其他
关注(0)|答案(6)|浏览(248)

我发现构建程序参数列表的最简单方法是将其作为字符串向量。但是,execv需要第二个参数的字符数组。最简单的方法是什么?

qybjjes1

qybjjes11#

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);
dfty9e19

dfty9e192#

是的,通过利用vector使用的内部数组,可以非常干净地完成它。最好不要在vector中使用C++字符串,以及const_cast字符串字面量和string.c_str()char*
这是可行的,因为标准保证了其元素是连续存储的(参见https://stackoverflow.com/a/2923290/383983)。

#include <unistd.h>
#include <vector>

using std::vector;

int main() {
  vector<const char*> command;

  // do a push_back for the command, then each of the arguments
  command.push_back("echo");
  command.push_back("testing");
  command.push_back("1");
  command.push_back("2");
  command.push_back("3");

  // push NULL to the end of the vector (execvp expects NULL as last element)
  command.push_back(NULL);

  // pass the vector's internal array to execvp
  execvp(command[0], const_cast<char* const*>(command.data()));
  return 1;
}

代码改编自:如何将向量传递给execvp
执行const_cast以避免“从字符串常量到'char *'的不推荐转换”。字符串文字在C++中实现为const char*const_cast是这里最安全的强制转换形式,因为它只删除const,不会做任何其他有趣的事情。execvp()无论如何都不会编辑这些值。
如果你想避免所有的强制转换,你必须通过将所有的值复制到char*类型来复杂化这段代码,这并不值得。
虽然如果要传递给execv/execl的参数数量是已知的,但用C编写会更容易。

dhxwm5r4

dhxwm5r43#

execv的原型是:

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

这意味着参数列表是一个指向以null终止的c字符串的指针数组。
vector<string>求出该向量的大小,并创建一个指向char的指针数组。然后循环遍历向量,并为向量中的每个string设置数组的相应元素指向它。

2sbarzqh

2sbarzqh4#

不久前我也遇到了同样的问题。
我最终在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取代了整个过程,无论如何都不会有问题。

1hdlvixo

1hdlvixo5#

你不能改变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()的名字。
NB:我只是在我的头顶上打了这个。它可能不起作用。它甚至可能无法编译;- )

5rgfhyps

5rgfhyps6#

这就是我最后做的:

  1. std::vectorstd::string来获取我需要的所有参数。
    1.在execv之前创建std::vector<const char >,为所有参数保留足够的空间。
    1.使用std::transform转换第二个向量。
    1.使用const_cast<char
    const*>(vec.data())将其提供给execv;
    变换过程:
std::transform(stringsVec.cbegin(), stringsVec.cend(), charsVec.begin(),
    [](const std::string &arg)
{
    return arg.c_str();
});

这基本上是@ericcurtin和@Ferruccio答案的组合。

相关问题