C 使用“getopt”long时理解“option long\u options[]”`

C 使用“getopt”long时理解“option long\u options[]”`,c,parameter-passing,command-line-arguments,getopt,getopt-long,C,Parameter Passing,Command Line Arguments,Getopt,Getopt Long,我正在努力学习使用getopt\u 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) {

我正在努力学习使用
getopt\u 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);
}
#包括/*用于printf*/
#包括/*用于退出*/
#包括/*用于getopt_long;POSIX标准getopt在unistd.h中*/
int main(int argc,字符**argv){
INTC;
整数位数_optind=0;
int aopt=0,bopt=0;
char*copt=0,*dopt=0;
静态结构选项长_选项[]={
{“添加”,1,0,0},
{“追加”,0,0,0},
{“删除”,1,0,0},
{“详细”,0,0,0},
{“create”,1,0,'c'},
{“文件”,1,0,0},
{NULL,0,NULL,0}
};
int option_index=0;
而(c=getopt_long(argc,argv,abc:d:012),,
长选项和选项索引)!=-1){
int这个选项=optind?optind:1;
开关(c){
案例0:
printf(“选项%s”,长选项[选项索引].name);
如果(optarg)
printf(“带有参数%s”,optarg);
printf(“\n”);
打破
案例“0”:
案例“1”:
案例“2”:
if(digital\u optind!=0&&digital\u optind!=this\u optind)
printf(“数字出现在两个不同的argv元素中。\n”);
数字\u optind=此\u选项\u optind;
printf(“选项%c\n”,c);
打破
案例“a”:
printf(“选项a\n”);
aopt=1;
打破
案例“b”:
printf(“选项b\n”);
bopt=1;
打破
案例“c”:
printf(“值为'%s'\n的选项c”,optarg);
copt=optarg;
打破
案例“d”:
printf(“值为“%s”\n的选项d”,optarg);
dopt=optarg;
打破
案例“?”:
打破
违约:
printf(“?getopt返回的字符代码0%o???\n”,c);
}
}
如果(选项D
我不太理解
选项long\u options[]
对象

第一列

我认为
long\u options[]
的第一个“列”应该是用户在命令行中使用的long标志(后面是
--

第二列

我原以为第二列应该只包含
无参数
必需参数
,或
可选参数
,但我看到的是0和1

第三列

我不懂第三栏

第四列和最大标志数

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


我假设
option long_options[]
的最后一行是用于
getopt
返回
-1
的时间,因此只要它存在,就不重要。

结构选项
数组在我摘录的[Note 1]中精确定义:

longopts
是指向在
中声明为

   struct option {
       const char *name;
       int         has_arg;
       int        *flag;
       int         val;
   };
不同字段的含义如下:

name
是长选项的名称

has_arg
为:
无参数
(或0),如果选项不带参数<代码>必需参数(或1),如果选项需要参数;或
可选参数
(或2),如果选项采用可选参数

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

val
是要返回的值,或要加载到
标志所指向的变量中的值

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

因此,您通常会对第二个元素使用符号常量(
has_arg
),但手册页允许您使用0、1或2,可能是为了向后兼容。(维基百科应该使用符号常量IMHO,但这是维基百科和它的编辑器之间的事。)

getopt_long
返回一个
int
,而不是
char
。如果
标志
(第三个)字段为
(或等效为0),则将返回
val
(第四个)字段,该字段可以是符合
int
的任何内容。字符肯定适合
int
,因此您可以返回等效的短选项字符(如手册中所述),但您没有义务这样做
getopt
还返回一个
int
,但由于它总是返回一个选项字符(或错误指示),因此有大量的
int
值它永远不会返回。[注2]

如果第三个字段不是
NULL
,则应指向
int
类型的变量,
getopt_long
将存储<
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();