getopt的不解析可选参数参数getopt的不解析可选参数参数(getopt does not p

2019-05-13 23:42发布

在C中,getopt_long不解析可选参数以命令行参数的参数。

当我运行该程序,可选的参数无法识别像下面运行的例子。

$ ./respond --praise John
Kudos to John
$ ./respond --blame John
You suck !
$ ./respond --blame
You suck !

下面是测试代码。

#include <stdio.h>
#include <getopt.h>

int main(int argc, char ** argv )
{
    int getopt_ret, option_index;
    static struct option long_options[] = {
               {"praise",  required_argument, 0, 'p'},
               {"blame",  optional_argument, 0, 'b'},
               {0, 0, 0, 0}       };
    while (1) {
        getopt_ret = getopt_long( argc, argv, "p:b::",
                                  long_options,  &option_index);
        if (getopt_ret == -1) break;

        switch(getopt_ret)
        {
            case 0: break;
            case 'p':
                printf("Kudos to %s\n", optarg); break;
            case 'b':
                printf("You suck ");
                if (optarg)
                    printf (", %s!\n", optarg);
                else
                    printf ("!\n", optarg);
                break;
            case '?':
                printf("Unknown option\n"); break;
        }
    } 
    return 0;
}

Answer 1:

虽然glibc的文档或getopt的手册页中未提到,可选参数长风格的命令行参数要求“等号”(=)。 空格分隔从参数可选参数不起作用。

一个示例运行与测试代码:

 $ ./respond --praise John Kudos to John $ ./respond --praise=John Kudos to John $ ./respond --blame John You suck ! $ ./respond --blame=John You suck , John! 


Answer 2:

该名男子页肯定不会记录非常好,但源代码可以帮助一点点。

简单地说:你应该做类似下面的(虽然这可能有点过分迂腐):

if(   !optarg
   && optind < argc // make sure optind is valid
   && NULL != argv[optind] // make sure it's not a null string
   && '\0' != argv[optind][0] // ... or an empty string
   && '-' != argv[optind][0] // ... or another option
  ) {
  // update optind so the next getopt_long invocation skips argv[optind]
  my_optarg = argv[optind++];
}
/* ... */

从前面的_getopt_internal的评论中:

...

如果getopt找到另一个选项字符,它返回该字符, 更新optindnextchar以便在下次调用getopt可以恢复使用下列选项字符或ARGV元件的扫描。

如果没有更多的期权特征, getopt返回-1。 然后optind处于第一ARGV元件的ARGV索引不是一个选项。 (该ARGV元素已经被置换,使那些不选择现在最后来了。) <-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted

...

如果在一个OPTSTRING炭后面跟着冒号,这意味着它想要的精氨酸,所以在同样ARGV元件下面的文本,或以下ARGV-元素的文本,在返回optarg 。 两个冒号表示希望有一个可选的ARG的选项; 如果在当前ARGV元素的文本,则返回在optarg否则optarg设置为零

...

...虽然你要做的字里行间读点书。 下面你想要做什么:

#include <stdio.h>
#include <getopt.h>

int main(int argc, char* argv[] ) {
  int getopt_ret;
  int option_index;
  static struct option long_options[] = {
      {"praise",  required_argument, 0, 'p'}
    , {"blame",  optional_argument, 0, 'b'}
    , {0, 0, 0, 0}
  };

  while( -1 != ( getopt_ret = getopt_long(  argc
                                          , argv
                                          , "p:b::"
                                          , long_options
                                          , &option_index) ) ) {
    const char *tmp_optarg = optarg;
    switch( getopt_ret ) {
      case 0: break;
      case 1:
        // handle non-option arguments here if you put a `-`
        // at the beginning of getopt_long's 3rd argument
        break;
      case 'p':
        printf("Kudos to %s\n", optarg); break;
      case 'b':
        if(   !optarg
           && NULL != argv[optindex]
           && '-' != argv[optindex][0] ) {
          // This is what makes it work; if `optarg` isn't set
          // and argv[optindex] doesn't look like another option,
          // then assume it's our parameter and overtly modify optindex
          // to compensate.
          //
          // I'm not terribly fond of how this is done in the getopt
          // API, but if you look at the man page it documents the
          // existence of `optarg`, `optindex`, etc, and they're
          // not marked const -- implying they expect and intend you
          // to modify them if needed.
          tmp_optarg = argv[optindex++];
        }
        printf( "You suck" );
        if (tmp_optarg) {
          printf (", %s!\n", tmp_optarg);
        } else {
          printf ("!\n");
        }
        break;
      case '?':
        printf("Unknown option\n");
        break;
      default:
        printf( "Unknown: getopt_ret == %d\n", getopt_ret );
        break;
    }
  }
  return 0;
}


Answer 3:

我也遇到了同样的问题,来到了这里。 然后,我意识到这一点。 你没有太多的“optional_argument”的使用情况。 如果需要一个选项,从程序逻辑检查,如果一个选项是可选的,那么你不需要做任何事情,因为getopt的级别的所有选项都是可选的,他们是不是强制性的,所以有“optional_argument”没有用的情况。 希望这可以帮助。

PS:在上面的例子中,我认为正确的选项是--praise --praise名“名” --blame --blame名“名”



Answer 4:

如果你写旁边的参数的变量没有空格字符既不等于也适用。 例如:

$ ./respond --blameJohn
You suck John!


文章来源: getopt does not parse optional arguments to parameters