我正在尝试学习使用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
的,因此只要它存在就没有关系。 最佳答案
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
指定长选项的返回结果的方式。如果标志是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
,则应指向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
即可查看getopt_long
的文档。这对于任何标准C库函数,任何Gnu libc函数,以及通常为您安装了-doc
软件包的任何C库函数都适用。 (强烈建议。)总体而言,在查看Wikipedia之前,应先尝试使用手册页,因为该手册页将是系统上实际安装的库函数版本的文档。函数返回给定数据类型的事实并不意味着它可能返回该数据类型的任何可能值。