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); }
运行自行操作测试