使用`getopt_long`时理解`option long_options []`

Rem*_*i.b 2 c parameter-passing getopt getopt-long command-line-arguments

我正在努力学会使用getopt_long.从维基百科,我看到代码

#include <stdio.h>     /* for printf */
#include <stdlib.h>    /* for exit */
#include <getopt.h>    /* for getopt_long; POSIX standard getopt is in unistd.h */
int main (int argc, char **argv) {
    int c;
    int digit_optind = 0;
    int aopt = 0, bopt = 0;
    char *copt = 0, *dopt = 0;
    static struct option long_options[] = {
        {"add", 1, 0, 0},
        {"append", 0, 0, 0},
        {"delete", 1, 0, 0},
        {"verbose", 0, 0, 0},
        {"create", 1, 0, 'c'},
        {"file", 1, 0, 0},
        {NULL, 0, NULL, 0}
    };
    int option_index = 0;
    while ((c = getopt_long(argc, argv, "abc:d:012",
                 long_options, &option_index)) != -1) {
        int this_option_optind = optind ? optind : 1;
        switch (c) {
        case 0:
            printf ("option %s", long_options[option_index].name);
            if (optarg)
                printf (" with arg %s", optarg);
            printf ("\n");
            break;
        case '0':
        case '1':
        case '2':
            if (digit_optind != 0 && digit_optind != this_option_optind)
              printf ("digits occur in two different argv-elements.\n");
            digit_optind = this_option_optind;
            printf ("option %c\n", c);
            break;
        case 'a':
            printf ("option a\n");
            aopt = 1;
            break;
        case 'b':
            printf ("option b\n");
            bopt = 1;
            break;
        case 'c':
            printf ("option c with value '%s'\n", optarg);
            copt = optarg;
            break;
        case 'd':
            printf ("option d with value '%s'\n", optarg);
            dopt = optarg;
            break;
        case '?':
            break;
        default:
            printf ("?? getopt returned character code 0%o ??\n", c);
        }
    }
    if (optind < argc) {
        printf ("non-option ARGV-elements: ");
        while (optind < argc)
            printf ("%s ", argv[optind++]);
        printf ("\n");
    }
    exit (0);
}
Run Code Online (Sandbox Code Playgroud)

我不太了解这个option long_options[]对象.

第一栏

我认为第一个"列" long_options[]应该是--用户在命令行中使用的长标志(无论如何).

第二栏

我本来以为第二栏应该只包含no_argument,required_arguemntoptional_argument但不是我看到0和1.

第三栏

我不明白第三栏.

第四列和最大标志数

第四列是在switch语句中使用的唯一标识符.然而,这让我感到困惑,好像唯一标识符只能是单个字符,然后我们只限于所有小写字母(26)+全部大写字母(26)+数字(10)+最终一些特殊字符最多总共超过62个不同的参数.这是一个限制getopt吗?如果我弄错了,那么怎么能指出两个以上的字符来识别getopt_long(""abc:d:012"")的第三个参数中的一个标志

我想最后一行option long_options[]是什么时候getopt返回-1,因此只要它存在就没关系.

ric*_*ici 9

struct option阵列在精确限定的man getopt_long[注1]从中我摘录:

longopts是指向as 中struct option声明的数组的第一个元素的指针<getopt.h>

   struct option {
       const char *name;
       int         has_arg;
       int        *flag;
       int         val;
   };
Run Code Online (Sandbox Code Playgroud)

不同领域的含义是:

name 是长选项的名称.

has_arg是:( no_argument 或0)如果选项不参数; required_argument(或1)如果选项需要参数; 或optional_argument(或2)如果选项采用可选参数.

flag 指定如何为long选项返回结果.如果是NULL,则getopt_long()返回val.(例如,调用程序可以设置val为等效的短选项字符.)否则,getopt_long()返回0,并flag指向一个变量,val如果找到该选项则设置为该变量,但如果找不到该选项则保持不变.

val 是要返回的值,还是要加载到指向的变量中的值flag.

数组的最后一个元素必须用零填充.

因此,您通常会为第二个元素(has_arg)使用符号常量,但是联机帮助页允许您使用0,1或2,可能是为了向后兼容.(维基百科应该使用符号常量,恕我直言,但这是在维基百科和它的编辑之间.)

getopt_long返回一个int,而不是一个char.如果flag(第三个)字段是NULL(或等效地,0),那么val将返回(第四个)字段,并且该字段可以是适合于的任何字段int.一个字符当然适合一个int,所以你可以返回等效的短选项字符(如联机帮助页中所述),但你没有义务这样做.getopt也会返回一个int,但由于它总是返回一个选项字符(或一个错误指示),因此有大量的int值永远不会返回.[笔记2]

如果第三字段不是NULL,则有望指向类型的变量intgetopt_long将存储val的值.例如,这可以用于布尔标志:

enum FROBNICATE { FROB_UNSET = -1, FROB_NO = 0, FROB_YES = 1 };
/* ... */

/* This is conceptually an enum, but `getopt_long` expects an int */
int frob_flag = FROB_UNSET;

struct option long_opts = {
  /* ... */
  {"frobnicate", no_argument, &frob_flag, FROB_YES},
  {"unfrobnicated", no_argument, &frob_flag, FROB_NO},
  /* ... */
  {NULL, 0, NULL, 0}
};

/* Loop over arguments with getopt_long;
   In the switch statement, you can ignore the returned value
   0 because the action has been fully realized by setting the
   value of a flag variable.
 */

if (frob_flag == FROB_UNSET)
  frob_flag = get_default_frobnication();
Run Code Online (Sandbox Code Playgroud)

如联机帮助页所示,数组中的最后一个条目必须全为零(或NULL指针成员).这是必需的,以便getopt_long知道数组的结束位置.

笔记

  1. 您可能已在系统上安装了联机帮助页,在这种情况下,您只需键入man getopt_long即可查看文档getopt_long.这适用于任何标准C库函数,任何Gnu libc函数,以及通常已安装-doc软件包的任何C库函数.(强烈推荐.)总的来说,在查看Wikipedia之前,您应首先尝试使用联机帮助页,因为该联机帮助页将是您系统上实际安装的库函数版本的文档.

  2. 函数返回给定数据类型的事实并不意味着它可能返回该数据类型的任何可能值.