我正在努力学会使用getopt_long
。从wikipedia开始,我看到代码
#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);
}
我不太了解option long_options[]
对象。
第一栏
我认为long_options[]
的第一个“列”应该是用户在命令行中使用的长标志(跟--
之后的任何内容)。
第二栏
我原以为第二列应该只包含no_argument
,required_arguemnt
或optional_argument
,而不是我看到0和1。
第三栏
我不明白第三栏。
第四列和最大标志数
第四列是在switch语句中使用的唯一标识符。然而,这让我感到困惑,好像唯一标识符只能是单个字符,然后我们只限于所有小写字母(26)+全部大写字母(26)+数字(10)+最终一些特殊字符最多总共超过62个不同的参数。这是getopt
的限制吗?如果我弄错了,那么怎么能指出两个以上的字符来标识getopt_long
的第三个参数中的一个标志(""abc:d:012""
)
我认为option long_options[]
的最后一行是getopt
返回-1
的时间,因此只要它存在就无所谓。
答案 0 :(得分:9)
struct option
数组在man getopt_long
[注释1]中精确定义,我从中摘录:
longopts
是指向struct option
中声明的<getopt.h>
数组的第一个元素的指针struct option { const char *name; int has_arg; int *flag; int val; };
不同领域的含义是:
name
是长选项的名称。
has_arg
是no_argument
(或0),如果该选项不参数;required_argument
(或1)如果选项需要参数;如果选项采用可选参数,则为optional_argument
(或2)。
flag
指定如何为长选项返回结果。如果flag为NULL
,则getopt_long()
会返回val
。 (例如,调用程序可以将val
设置为等效的短选项字符。)否则,getopt_long()
返回0,flag
指向设置为{{1}的变量如果找到该选项,但如果找不到该选项则保持不变。
val
是要返回或加载到val
指向的变量的值。数组的最后一个元素必须用零填充。
因此,您通常会为第二个元素(flag
)使用符号常量,但是联机帮助页允许您使用0,1或2,可能是为了向后兼容。 (维基百科应该使用符号常量,恕我直言,但这是维基百科及其编辑之间的。)
has_arg
会返回getopt_long
,而非int
。如果char
(第三个)字段为flag
(或等效地为0),则将返回NULL
(第四个)字段,该字段可以是适合val
的任何字段{1}}。一个字符当然适合int
,因此您可以返回等效的短选项字符(如联机帮助页中所述),但您没有义务这样做。 int
也返回getopt
,但由于它总是返回一个选项字符(或错误指示),因此会有大量int
值永远不会返回。 [注2]
如果第三个字段不是int
,则应指向NULL
类型的变量,int
将存储getopt_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();
)。这是必需的,以便NULL
知道数组的结束位置。
您可能已在系统上安装了联机帮助页,在这种情况下,只需键入getopt_long
即可查看man getopt_long
的文档。这适用于任何标准C库函数,任何Gnu libc函数,以及通常已安装getopt_long
包的任何C库函数。 (强烈推荐。)总体而言,在查看Wikipedia之前,您应首先尝试使用manpage ,因为该联机帮助页将是您系统上实际安装的库函数版本的文档。
函数返回给定数据类型的事实并不意味着它可能返回该数据类型的任何可能值。