【问题标题】:How to pass std::vector<std::string> as char**?如何将 std::vector<std::string> 作为 char** 传递?
【发布时间】:2013-09-21 10:14:15
【问题描述】:

我正在尝试制作char *argv[] 的副本,以便我可以将它们传递给采用char** 的函数。首先,我必须从原始 argv 中删除一些标志:

int main(int argc, char* argv[]) {
    ::MessageBox(0,"Stopped at the entry point",0,0);
    std::string inChannelParam = "--ipc-in-channel";
    std::string outChannelParam = "--ipc-out-channel";

    std::string inChannelName;
    std::string outChannelName;

    std::vector<std::string> argv_copy;
    for(int i=0; i<argc; ++i)  {
        if(inChannelParam == argv[i]) {
            if(++i < argc) {
                inChannelName = argv[i];
                continue;
            }
        } else if(outChannelParam == argv[i]) {
            if(++i < argc) {
                outChannelName = argv[i];
                continue;
            }
        }
        argv_copy.push_back(argv[i]);
    }

    std::vector<std::unique_ptr<char[]> > argv_copy_char;
    for(int i=0;i<argv_copy.size();++i) {
        argv_copy_char.push_back(std::unique_ptr<char[]>(new char[argv_copy[i].size()+1]));
        memcpy(argv_copy_char[i].get(), &argv_copy[i][0], argv_copy[i].size());
        argv_copy_char[i][argv_copy[i].size()] = '\0';
    }

    // what should i put here ?? --------------------vvv
    v8::V8::SetFlagsFromCommandLine(&argc, &(argv_copy_char[0].get()), true);

我尝试了基于字符串和字符 [] 的方法。它给出了编译器错误:

error C2102: '&' requires l-value

使用&amp;(argv_copy_char[0]._Myptr) 会给我运行时错误

if (arg != NULL &amp;&amp; *arg == '-') {flags.cc

函数SetFlagsFromCommandLine的签名是

SetFlagsFromCommandLine (int *argc, char **argv, bool remove_flags).

我该怎么办?

【问题讨论】:

  • 能不能不直接传原argv?以后还需要修改吗?
  • @downvoter 请解释原因。谢谢

标签: c++ arrays pointers vector argument-passing


【解决方案1】:

为什么SetFlagsFromCommandLine 得到一个指向整数的指针?是否需要更改整数?我不明白您为什么要向它传递指针。

问题似乎在一个完全不同的地方,所以你分享的代码没有多大帮助

最后,看看你得到错误所在的那一行。检查:

  1. arg 是什么?定义了吗?
  2. arg 可以为 NULL 吗?
  3. arg 是指针还是数组?

【讨论】:

  • @DCoder,如果它接受char **argv,那么只需传递argv...char **argvchar *argv[] 是写下同一件事的不同方式。
  • @SingerOfTheFall 我必须先删除一些标志。所以需要复印一份。
  • 知道错误是在函数中传递 argc 它应该是删除一些标志后的新参数计数器,即 argc_copy_char 的大小
  • @ASHISHNEGI soo...我的回答对你有帮助吗?
【解决方案2】:

您已经构建并填充了字符串向量:std::vector&lt;std::string&gt; argv_copy; 但是
我不明白你为什么决定使用这个向量来创建另一个包含unique_ptr&lt;char[]&gt; 类型元素的向量:

std::vector<std::unique_ptr<char[]> > argv_copy_char;

还要注意v8::V8::SetFlagsFromCommandLine的原型是:

static void SetFlagsFromCommandLine (int *argc, char **argv, bool remove_flags)

... 在这里暴露向量的内部结构并不是很幸运,因为argv_copy 拥有std::string 类型的对象... 但是API 需要char**,所以你可以做的是动态分配和填充指向这些字符串的临时 C 样式指针数组:

// temporary C-style array
int myArgvSize = argv_copy.size();
char* myArgv[] = new char* [myArgvSize];
for (int i = 0; i < myArgvSize; ++i)
    myArgv[i] = &argv_copy[i][0];

v8::V8::SetFlagsFromCommandLine(&myArgvSize, myArgv, true);

// cleanup:
delete[] myArgv;

请注意,此解决方案依赖于 SetFlagsFromCommandLine 不会修改这些字符串的长度这一事实。

【讨论】:

  • argc 也应该反映 argv_copy.size()
  • 请注意,SetFlagsFromCommandLine 几乎肯定会修改其 argv 参数,因此他必须在调用 argv_copy 后更新它以反映这一点。
【解决方案3】:

SetFlagsFromCommandLine 看起来是一个相当特殊的函数 对我来说,它似乎期望 argcargv 作为 参数,并修改它们(大概是通过删除选项)。 如果可能的话,我会先用argcargv,之后做我的特殊处理。修改 可能以argv 中的指针移位形式发生 down,这意味着任何使用std::vector 的解决方案都会 调用函数后需要一些额外的处理。

如果您无法更改处理顺序(例如,因为 --ipc-in-channel 及其参数可能由 SetFlagsFromCommandLine),那么你可能需要一些东西 像下面这样(在你解析了你的参数之后):

std::vector<char*> tmp;
for ( auto current = argv_copy.begin();
        current != argv_copy.end();
        ++ current ) {
    tmp.push_back( current->empty ? "" : &(*current)[0] );
}
int argc_copy = tmp.size();
SetFlagsFromCommandLine( &argc_copy, &tmp[0] );
if ( argc_copy != argv_copy.size() ) {
    auto dest = argv_copy.begin();
    auto src = tmp.begin();
    while ( dest != argv_copy.end() ) {
        if ( (*src)[0] == '\0' ) {
            if ( *dest != "" ) {
                ++ dest ;
            } else {
                while ( dest != argv_copy.end() && *dest != "") {
                    dest = argv.erase( dest );
                }
            }
        } else {
            if ( !dest->empty() && &(*dest)[0] == *src ) {
                ++ dest;
            } else {
                while( dest != argv_copy.end() 
                        && (dest->empty() || &(*dest)[0] != *src) ) {
                    dest = argv.erase( dest );
                }
            }
        }
    }
    assert( argv_copy.size() == argc_copy );
}

这只是我的想法,可能包含一些 错误,但它可以让您了解如果您需要付出的努力 不能先打电话给SetFlagsFromCommandLine

编辑:

或者,虽然有点痛苦,但你可以 以完全相同的方式处理argcargv SetFlagsFromCommandLine 在内部做,没有放它们 在std::vector:

int dest = 1;
int source = 1;
while ( source != argc ) {
    if ( inChannelParam == argv[source] == 0 && source < argc - 1 ) {
        inChannelName = argv[source + 1];
        source += 2;
    } else if ( outChannelPara == argv[source] == 0 && source < argc - 1 ) {
        outChannelName = argv[source + 1];
        source += 2;
    } else {
        argv[dest] = argv[source];
        ++ dest;
        ++ source;
    }
}
argc = dest;
SetFlagsFromCommandLine( &argc, argv );
std::vector<std::string> argv_copy( argv, argv + argc );

char** 等人打交道并不好玩,但既然你需要 以后这种格式,可能比翻译更痛苦 格式之间多次。

【讨论】:

  • 如果您传递未知参数,使用 SetFlagsFromCommandLine 的 v8 库不会启动。所以我先处理我的,如果他们在场,然后将其余的发送到 SetFlagsFromCommandLine。
  • @ASHISHNEGI 使用 v8 库的示例代码首先调用 SetFlagsFromCommandLine,然后解析任何其他参数。规范并没有真正说明这一点,但我非常怀疑你所说的情况是否如此。您误解了 v8 的文档。
  • FWIW:我愿意在内部打赌,SetFlagsFromCommandLine 与我在上面的第二个示例中所做的非常相似。这是在 C 中处理选项的一种几乎通用的方式。(形式上,它不受 C 标准的支持,但它是通用的,而且我从未听说过它不起作用的实现。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 2011-10-26
  • 1970-01-01
相关资源
最近更新 更多