getopt_long
, getopt_long_only
– 命令行解析函数,支持长选项解析
【说明】 getopt_long
/getopt_long_only
是 getopt
的泛集,getopt
是 getopt_long
的一个子集,getopt
支持的所有特性,getopt_long
都支持,包括错误打印、argv
元素顺序调整等;getopt_long
相比 getopt
增加了长选项的解析,具体如下:
1、形如:
cmd [--create][--file]
//对长选项的解析;
2、形如:cmd [--create a_argument][-file b_argument]
//对长选项及长选项的参数解析;
3、形如:cmd [--create [a_argument]]
//选项create的参数也是可选的情况解析
getopt_long_only
与getopt_long
的区别在于:getopt_long
仅仅只能将 “–” 开始的选项视为长选项,但getopt_long_only
将"-“开头选项也会视为长选项,当长选项列表均不满足时,且短选项满足时,”-" 才会解析为短选项;
原型:
#define _GNU_SOURCE
#include <getopt.h>
extern char *optarg;
extern int optind, opterr, optopt;
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);
描述:
1、注意相比
getopt
,使用getopt_long
需要加头文件<getopt.h>
;
2、getopt_long
除了会接受长选项,其他概念和getopt
是一样的;
3、如果使用getopt_long
想只接受短选项,设置longopts
为NULL
即可;如果只想接受长选项,相应地设置optstring
为NULL
即可;
4、长选项名是可以使用缩写方式,比如:选项有--file
/--create
,那么输入--c
/--cr
/--cre
等均会被正确识别为create
选项;
5、对于带参数的长选项格式是:--arg=param
或--arg param
;
6、longopts
是指向struct option
数组的第一个元素的指针,struct option
定义在<getopt.h>
中;
7、longindex
如果非NULL
,则是返回识别到struct option
数组中元素的位置指针;
struct option的说明:
/*
name: 长选项名
has_arg: 是否带参数或可选参数,这个值在getopt.h中有宏定义,如下:
# define no_argument 0
# define required_argument 1
# define optional_argument 2
flag: 确定函数返回值的情况,如果flag==NULL,则识别选项后返回val(常用的如:设置val为长命令的短命令字符);否则,识别后getopt_long返回0,flag指向一个设置到val的变量;
val: 设置为返回值,或者是flag指向的变量;这里要注意不要写-1到val,否则其作用是getopt_long返回-1,然后停止解析选项;
[注意] longopts的最后一个元素必须是全0填充,否则会报段错误
*/
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
返回值:
1、如果识别短选项,同
getopt
一样返回短选项字符;
2、如果识别长选项,根据flag
的设置返回不同的内容,一般flag
都设置为NULL
,返回val
;
3、如果发生错误,如:未识别选项或者必须加参数的选项丢失参数,返回 ‘?’,如果在optstring
中设置了第一个字符为 ‘:’,丢失参数返回 ‘:’,这个同getopt
返回时一样的;
4、当缩写长选项引起歧义时或者不需要的选项强加了参数,都会返回 ‘?’;
5、返回 -1 表示选项处理全部结束;
6、如果在输入的argv[]
中包含了独立的 “–” 字符串,同getopt
一样,解析到这里返回 -1,停止选项的解析;
测试实例:
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
int main(int argc, char **argv)
{
extern char *optarg;
extern int optind, opterr, optopt;
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind= optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", required_argument, NULL, 0},
{"append", no_argument, NULL, 0},
{"delete", required_argument, NULL, 0},
{"verbose", no_argument, NULL, 0},
{"create", required_argument, NULL, 'c'},
{"file", required_argument, NULL, 0},
{0, 0, 0, 0},
};
c = getopt_long(argc, argv, ":abc:d:012", long_options, &option_index);
if (c == -1)
break;
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");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value \"%s\"\n", optarg);
break;
case 'd':
printf ("option d with value \"%s\"\n", 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);
}
运行自行操作测试