【问题标题】:How do I use getopt_long to parse multiple arguments?如何使用 getopt_long 解析多个参数?
【发布时间】:2012-02-07 05:08:27
【问题描述】:
#include <iostream>
#include <getopt.h>

#define no_argument 0
#define required_argument 1 
#define optional_argument 2


int main(int argc, char * argv[])
{
  std::cout << "Hello" << std::endl;

  const struct option longopts[] =
  {
    {"version",   no_argument,        0, 'v'},
    {"help",      no_argument,        0, 'h'},
    {"stuff",     required_argument,  0, 's'},
    {0,0,0,0},
  };

  int index;
  int iarg=0;

  //turn off getopt error message
  opterr=1; 

  while(iarg != -1)
  {
    iarg = getopt_long(argc, argv, "s:vh", longopts, &index);

    switch (iarg)
    {
      case 'h':
        std::cout << "You hit help" << std::endl;
        break;

      case 'v':
        std::cout << "You hit version" << std::endl;
        break;

      case 's':
        std::cout << "You hit stuff" << std::endl;

        if(optarg)
          std::cout << "Your argument(s): " << optarg << std::endl;

        break;
    }
  }

  std::cout << "GoodBye!" << std::endl;

  return 0; 
}

期望的输出:

./a.out --stuff someArg1 someArg2

Hello
You hit stuff
Your agument(s): someArg1 someArg2
GoodBye!

【问题讨论】:

  • 它只捕获 1 个参数:实际输出 Hello You hit stuff Your argument(s): someArg1 GoodBye!

标签: c++ parsing command-line-arguments getopt-long


【解决方案1】:

getopt 在处理完所有 option 参数后返回 -1。 --stuff 被识别为带有参数的选项,在本例中为 someArg1someArg2 arg 不以 --- 开头,因此它不是选项。默认情况下,这将被置换到argv 的末尾。 getopt 返回 -1 后,所有非选项 args 将在 argvoptindargc-1

while (iarg != -1) {
    iarg = getopt_long(argc, argv, "s:vh", longopts, &index);
    // ...
}

for (int i = optind; i < argc; i++) {
    cout << "non-option arg: " << argv[i] << std::endl;
}

如果您在optstring 的开头添加一个-getopt 将返回1(不是'1')并将optarg 指向非选项参数:

while (iarg != -1) {
    iarg = getopt_long(argc, argv, "-s:vh", longopts, &index);

    switch (iarg)
    {
      // ...
      case 1:
        std::cout << "You hit a non-option arg:" << optarg << std::endl;
        break;
    }
}

【讨论】:

    【解决方案2】:

    ./a.out --stuff someArg1 someArg2 行中,shell 将三个参数解释为a.out。您希望 shell 将“someArg1 someArg2”解释为一个参数 - 所以将这些词放在引号中:

    ./a.out --stuff "someArg1 someArg2"
    

    【讨论】:

      【解决方案3】:

      我在 windows 上工作,所以我必须从 this excellent source 编译 getopt 和 getopt_long

      我修改了 getopt_long.c(如下)以容纳两个输入参数。我没有为多个参数的更一般情况而烦恼,因为这需要比我有时间/需要的更多(和更清洁)的返工。第二个参数放置在另一个全局变量“optarg2”中。

      如果您不需要从源代码编译 getopt,上面 Frank 的回答更优雅。

      extern char * optarg2
      .
      .
      .
      int getopt_long(nargc, nargv, options, long_options, index) 
      {
      .
      .
      .
      if (long_options[match].has_arg == required_argument ||
                  long_options[match].has_arg == optional_argument ||
                  long_options[match].has_arg == two_req_arguments) {
                  if (has_equal)
                      optarg = has_equal;
                  else
                      optarg = nargv[optind++];
                  if (long_options[match].has_arg == two_req_arguments) {
                      optarg2 = nargv[optind++];
                  }
              }
              if ((long_options[match].has_arg == required_argument ||
                   long_options[match].has_arg == two_req_arguments)
                  && (optarg == NULL)) {
                  /*
                   * Missing argument, leading :
                   * indicates no error should be generated
                   */
                  if ((opterr) && (*options != ':'))
                      (void)fprintf(stderr,
                        "%s: option requires an argument -- %s\n",
                        __progname(nargv[0]), current_argv);
                  return (BADARG);
              }
              if ((long_options[match].has_arg == two_req_arguments)
                  && (optarg2 == NULL)) {
                  /*
                   * Missing 2nd argument, leading :
                   * indicates no error should be generated
                   */
                  if ((opterr) && (*options != ':'))
                      (void)fprintf(stderr,
                        "%s: option requires 2nd argument -- %s\n",
                        __progname(nargv[0]), current_argv);
                  return (BADARG);
              }
      

      您还需要在 getopt.h 中为“two_required_args”或“multiple_args”添加一个您认为合适的定义。

      编辑:我不擅长降价

      【讨论】:

        【解决方案4】:

        optarg 指向 "someArg1" 并且 argv[optind] 是 "someArg2" 如果它存在并且不是一个选项。您可以简单地使用它,然后通过增加 optind 来使用它。

        case 's':
            std::cout << "You hit stuff" << std::endl;
        
            if (optind < argc && argv[optind][0] != '-') {
               std::cout << "Your argument(s): " << optarg << argv[optind] << std::endl;
               optind++;
            } else {
                printusage();
            }
            break;
        

        请注意,这可以用于任意数量的参数:

        case 's':
            std::cout << "You hit stuff." << std::endl;
            std::cout << "Your arguments:" std::endl << optarg << std::endl;
        
            while (optind < argc && argv[optind][0] != '-') {
               std::cout << argv[optind] << std::endl;
               optind++;
            } 
            break;
        

        【讨论】:

        • 你应该指定标签
        猜你喜欢
        • 2015-04-30
        • 2016-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-26
        • 2021-10-25
        • 2015-08-03
        相关资源
        最近更新 更多