使用long_options解析具有任意数量的required_arguments的选项

时间:2018-11-26 17:08:13

标签: c++ getopt

我正在尝试使用 long_options [] 来解析从终端输入到C ++程序的不同选项。我的选项结构如下:

static struct option long_options[] = {
  // *name, has_arg, *flag, val
  {"help",      no_argument,        0,  'h'},
  {"debug",     no_argument,        0,  0},
  {"seed",      required_argument,  0,  's'},
  ...
}

然后,我将使用 getopt_long 读取参数,如下所示:

while (true) {

    int option_index (0);
    int c = getopt_long (argc, argv, "hs:t:iT:N:M:m:V:l:w:P:rR:b:d:a:", long_options, &option_index);
    if (c == -1) break;

    switch (c) {

        case 'h':
        print_help ();

        case 's':
        parameters.seed = atoi(optarg);
        break;

        case 0:
        if (long_options[option_index].flag != 0) break;
        else if (strcmp(long_options[option_index].name, "debug") == 0) parameters.debug = true;
        ...
        break;
    }
}

参数被传递给 optarg ,据我了解,其类型为char *或std :: string,如上所示。

当我想到一种设置带有两个或多个所需数量的参数的选项参数时,问题就来了。例如,我想设置一个选项,该选项允许用户方便地定义分发参数。我希望可以在终端上按如下方式调用它:

./program --distribution mean sd
./program --distribution mean sd n

但是,似乎 long_options 默认情况下只希望每个选项包含一个参数,因此上述示例中的 sd 应该被解析为单独的选项参数。

如何更改此默认行为?谢谢!

2 个答案:

答案 0 :(得分:2)

You can't,而且这样做并非常规。

要使您的应用程序具有非常规的命令行参数结构,您必须编写自己的解析器。

一种解决方法是要求您的用户使用一个参数发送多个单词:

./program --distribution 'mean sd n'

尽管您仍然需要自己解析此多字字符串。

Boost.ProgramOptions比旧的getopt灵活一些,没有过多地偏离命令行参数的“标准”实践,但是确定它是否满足您的要求需要进行研究。 / p>

答案 1 :(得分:1)

Optarg仅应视为输入。

也就是说,它是原始argv成员之一的原始指针。

最后,所有剩余的未使用参数在argv中重新组合,以供您用作输入文件名,但是,当然,您将失去它们在参数中的顺序。

如果在开始时制作自己的argv副本,则可以轻松找到getopt指示的optarg,并进行自己的解析,接受每个参数,直到下一个“-”为止。 Getopt会将那些附加参数设置为“未使用”。

如果您还想接受任何未使用的参数,则需要对argv进行更多过滤,以丢弃用完的其他选项。

这很麻烦,但是相对安全。