用 std::vector<std::string> 替换命令行参数 int argc 和 char** argv

Foa*_*oad 3 c++ stdvector argv command-line-arguments argc

下面这篇文章,我在那里找到了一个临时的解决方法我的其他问题,我想知道我是否可以更换int argc, char** argv一个std::vector<std::string>变量/对象。

考虑假想的代码:

#include <iostream>
#include <CloseLibrary>

void someFunction(int argc, char** argv){
    for (int i = 0; i < argc; ++i) {
        std::cout << argv[i] << std::endl;
    }
}

int myFunc(int argc, char** argv){
    someFunction(argc, argv);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

其中CloseLibrary是一个封闭的库,我无法访问源代码,而该someFunction库中的函数需要int argc, char** argv命令行参数。但出于某种原因char**,我的代码中不能有双指针。

在这篇文章中,我提出了类似我需要的东西,但我不知道如何使用它。我可以这样写代码吗:

#include <iostream>
#include <CloseLibrary>
#include <vector>

void someFunction(int argc, char** argv){
    for (int i = 0; i < argc; ++i) {
        std::cout << argv[i] << std::endl;
    }
}

int myFunc("args", [](std::vector<std::string> args){
    std::vector<char *> cstrs;
    cstrs.reserve(args.size());
    for (auto &s : args) cstrs.push_back(const_cast<char *>(s.c_str()));
    someFunction(cstrs.size(), cstrs.data());

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者也许有更规范的方法来做到这一点?如果您能帮助我找到正确的方法并理解解决方案,我将不胜感激。提前感谢您的帮助。

PS1。char* argv[]方法在函数体中没问题,但在输入中没问题。我不知道为什么 pybind11 这样做!

PS2。 在 pybind11 gitter 上,有人建议这样做:

void run(const std::vector<std::string>& args) {
    for(auto&& e : args) std::cout << e << '\n';
}
Run Code Online (Sandbox Code Playgroud)

PS3。还建议在 pybind11 Gitter 上:

char** argv = new char*[vec.size()]; // just like malloc(sizeof(char*)*vec.size());
for (int i = 0; i < vec.size(), i++) {
    argv[i] = new char[vec[i].size()];
    memcpy(argv[i], vec[i].data(), vec[i].size()); // or strcpy
}
Run Code Online (Sandbox Code Playgroud)

And*_*dré 8

您可以使用从给定范围初始化向量的构造函数,其中argv参数充当起始迭代器并argv+argc充当结束迭代器。

例如,我通常以以下方式开始我的主要功能:

int main( int argc, char* argv[] )
{
    std::vector< std::string > args( argv, argv + argc );

    for ( auto s : args )
    {
        std::cout << s << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这还将捕获第一个参数 (argv[0]),该参数通常(但不一定)在启动时保存应用程序的名称。

在您的情况下,您想做相反的事情,char*从 std::vector<std::string>构建一个连续的数组。我会做这样的事情:

std::vector< char* > rargs( args.size(), 0 ); // Initialize N nullptrs.
for ( int i=0; i<args.size(); ++i )
{
    std::strcpy( rargs[i], args[i].c_str() ); // One-by-one strcpy them 
}
Run Code Online (Sandbox Code Playgroud)

然后你可以将它们传递给一个接受 argc, argv 作为的函数

someFunction( rargs.size(), rargs.data() );
Run Code Online (Sandbox Code Playgroud)

  • @ArthurTacca:实际上,“char*[]”“降级”为“char**”。您将*总是*传递一个指针,并且*永远不会*传递一个数组。这种区别很重要,因为在被调用的函数中,您无法使用“sizeof”确定数组的长度(因为您看到的是指针,而不是数组)。这就是为什么标准*双重*确保您正确理解“argv”——“argc”告诉您它的大小*并且*它以零结尾。 (2认同)