5

在 C++ 程序中,我想要一个带有必需参数的“long-only”选项。下面是我使用getopt_long()的最小示例,但它不起作用:

#include <getopt.h>
#include <cstdlib>
#include <iostream>
using namespace std;

void help (char ** argv)
{
  cout << "`" << argv[0] << "` experiments with long options." << endl;
}

void parse_args (int argc, char ** argv, int & verbose, int & param)
{
  int c = 0;
  while (1)
  {
    static struct option long_options[] =
      {
        {"help", no_argument, 0, 'h'},
        {"verbose", required_argument, 0, 'v'},
        {"param", required_argument, 0, 0}
      };
    int option_index = 0;
    c = getopt_long (argc, argv, "hv:",
                     long_options, &option_index);
    cout << "c=" << c << endl;
    if (c == -1)
      break;
    switch (c)
    {
    case 0:
      if (long_options[option_index].flag != 0)
        break;
      printf ("option %s", long_options[option_index].name);
      if (optarg)
        printf (" with arg %s", optarg);
      printf ("\n");
      break;
    case 'h':
      help (argv);
      exit (0);
    case 'v':
      verbose = atoi(optarg);
      break;
    case 'param':
      param = atoi(optarg);
      break;
    case '?':
      abort ();
    default:
      abort ();
    }
  }
}

int main (int argc, char ** argv)
{
  int verbose = 0;
  int param = 0;
  parse_args (argc, argv, verbose, param);
  cout << "verbose=" << verbose << " param=" << param << endl;
  return EXIT_SUCCESS;
}

我用这个命令编译它(gcc 版本 4.1.2 20080704 Red Hat 4.1.2-46):

g++ -Wall test.cpp

它告诉我这个:

test.cpp:44:10: warning: character constant too long for its type

结果如下:

$ ./a.out -v 2 --param 3
c=118
c=0
option param with arg 3
c=-1
verbose=2 param=0

我试图让它在ideone上工作,但它甚至无法识别该选项-v

正如 trojanfoe 在他对另一个问题的评论中所指出的那样,应该可以使用“long-only”选项,因为 GNU tar 可以做到这一点。但是,GNU tar 使用argp,我很难理解它的源代码

有人可以给我一个适用于 GNUgetopt_long()或GNU 的最小示例argp()吗?

4

4 回答 4

7

有两个问题:

  1. 根据示例代码(您的链接),结构中定义的最终选项必须是{0,0,0,0}. 我建议将定义更改为

    static struct option long_options[] =
      {
        {"help", no_argument, 0, 'h'},
        {"verbose", required_argument, 0, 'v'},
        {"param", required_argument, 0, 0},
        {0,0,0,0}
      };
    
  2. (更重要的是,)您必须包含实际处理“参数”选项的代码。你在这种'0'情况下这样做:

    case 0:
      if (long_options[option_index].flag != 0)
        break;
      if (strcmp(long_options[option_index].name,"param") == 0)
        param = atoi(optarg);
      break;
    

如您所见,我使用该strcmp函数来比较字符串;为此,您需要#include <cstring>。顺便说一句,您还需要#include <cstdio>使用printf.

有了这些更改,该程序对我来说可以正常工作(在 GCC 4.5.1 上测试)。

于 2012-04-18T16:26:33.813 回答
5

在您的案例陈述中,您正在使用:

case 'param':

这给了你警告,因为编译器需要在那个地方有一个字符。

于 2012-04-18T15:49:47.047 回答
0

事实上,我意识到我应该检查option_indexwhen chas value 的值0,就像这样。这种情况不在 GNU libc 示例中,所以这里是:

switch (c)
{
case 0:
  if (long_options[option_index].flag != 0)
    break;
  if (option_index == 2)
  {
    param = atoi(optarg);
    break;
  }
case 'h':
  help (argv);
  exit (0);
case 'v':
  verbose = atoi(optarg);
  break;
case '?':
  abort ();
default:
  abort ();
}
于 2012-04-18T16:23:17.310 回答
0

另一种解决方案是使用 struct 选项中定义的 'flag' 成员值。

设置您的选项,如下所示:

int param_flag = 0;

{"param", required_argument, &param_flag, 1}

然后;

case 0:
    if (param_flag == 1) {
        do_something;
    }

有关 struct 选项的详细信息,请参阅 man getopt_long。

于 2016-10-26T09:47:10.923 回答