0.几个重要的全局变量与短选项和长选项的概念:
extern char *optarg;
extern int optind, opterr, optopt;
1.全局变量解释:
optarg:如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无参数时,optarg为NULL。
optind:argv数组中下一次需要处理的元素的下标,系统默认初始化此值为1.0是没有意义的,argv[0]为程序名,在解析命令行参数中是没有意义的。getopt正常解析完毕后,optind设置为argv数组中第一个不是选项的元素的下标(一般为0)。
opterr:存储错误选项字符.
2.GNU/Linux的命令行选项有两种类型:短选项和长选项,前者以 '-' 作为前导符,后者以 '--' 作为前导符。-n
表示是一个不带参数的短选项。--n
表示是一个不带参数的长选项。现在有一个带有参数的短选项比如说-w foo
,那么它和长选项--foo
是等价的。
1.getopt函数:短选项解析函数
函数声明:
#include
int getopt(int argc, char * const argv, const char *optstring);
函数参数:
1.argc:主函数传递过来的实参
2.argv:主函数传递过来的实参
3.optstring:一个包含选项字符的字符串。一组短选项组成的字符串
函数调用结果
1.该函数每解析完一个选项,就返回该选项字符。选项字符解析完毕后,调用getopt函数将会返回-1,然后optind设置为argv数组中第一个不是选项的元素的下标。
2.当调用getopt函数检测到错误时(比如说检测到的选项字符不在optstring实参中),默认情况下函数返回'?'。为什么说是默认呢?因为如果通过optstring实参指明选项带参数,而实际命令行没有参数时,getopt返回':'
而不是'?'
关于optstring,还有几点说明:
1.如果选项带参数,该选项后接冒号,比如optstring这个实参值为"a:b",指示a带参数,b没有参数;
2.如果选项带可选参数,该选项后接两个冒号,比如"a::b",表明a可能有参数,也可能没有;
3.如果optstring的开头字符为':',表明如果指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'(默认情况下返回'?'
,和无法识别的参数返回一样);
4.如果optstring的开头字符为'+',表明一但遇到一个非选项参数,马上停止扫描,随后的部分当作参数来解释;
5.如果optstring的开头字符为'-',表明如果遇到无选项参数,则把它当作选项1(不是字符'1')的参数
示例:(来源于man文档)
#include
3 #include
4 #include
5
6 int
7 main(int argc, char *argv[])
8 {
9 int flags, opt;
10 int nsecs, tfnd;
11
12 nsecs = 0;
13 tfnd = 0;
14 flags = 0;
15 //因为短选项解析完毕后getopt函数返回-1,所以作为循环退出的条件
16 //optstring这个实参的值为"nt:",意思是说n这个选项不带参数,t这个选项带有一个参数
17 while ((opt = getopt(argc, argv, "nt:")) != -1) {
18 switch (opt) {
19 case 'n':
20 flags = 1;
21 break;
22 case 't':
23 nsecs = atoi(optarg);
24 tfnd = 1;
25 break;
26 default: /* '?' */
27 fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
28 argv[0]);
29 exit(EXIT_FAILURE);
30 }
31 }
32
33 printf("flags=%d; tfnd=%d; nsecs=%d; optind=%d,argc=%d\n",
34 flags, tfnd, nsecs, optind,argc);
35 //optind这个全局变量默认初始化为1,不指定命令行参数argc就为1
36 if (optind >= argc) {
37 fprintf(stderr, "Expected argument after options\n");
38 exit(EXIT_FAILURE);
39 }
40 //如果函数解析完毕,那么optind的值重置为argv数组中第一个不是选项的元素的下标
41 //比如说./a.out -n 5 -t 100这样
42 printf("name argument = %s\n", argv[optind]);
43
44 /* Other code omitted */
45
46 exit(EXIT_SUCCESS);
47 }
运行示例:
zhihua@zy:~/sysFuncPrac$ ./a.out -n 5 -t 100
flags=1; tfnd=1; nsecs=100; optind=4,argc=5
name argument = 5
3.getopt_long函数:解析长选项或者短选项函数
函数声明:
#include //for option struct
int getopt_long(int argc, char * const argv[],
const char *optstring,
const struct option *longopts, int *longindex);
函数参数:
longops:指向一个option结构体数组的第一个元素。
longindex:getopt_long的最后一个参数longindex在函数返回时指向被搜索到的选项在longopts数组中的下标。
关于option struct如下:
struct option {
//长选项名
const char *name;
//has_arg:如果选项不带有参数则实参可以是no_argument,即为0;
//如果选项要求一个参数,则实参可以是required_argument,即为1;
//如果选项可以有一个可选参数,也可以不用,则实参可以是optional_argument,即为2.
int has_arg;
//flag:如果flag为null,则getopt_long函数返回val的值;flag
//不为null,则指向一个变量,变量的值为val,并且函数返回0.
int *flag;
//val:getopt_long函数返回的值;或者是flag指向的变量的值
int val;
};
注意在初始化option struct时:The last element of the array has to be filled with zeros.
函数返回值:
1.如果flag这个实参为null,那么这个函数返回val的值。这样短选项字符解析和长选项解析搭建了桥梁。
2.如果flag这个实参不为null,那么这个函数返回0
3.选项字符解析完毕后,调用getopt_long函数将会返回-1
4.当调用getopt_long函数检测到错误时(比如说检测到的选项字符不在longops实参中),默认情况下函数返回'?'
示例:(来源于man 文档)
1 #include /* for printf */
2 #include /* for exit */
3
4 #include /*for option struct */
5
6 int main(int argc, char **argv) {
7 int c;
8 int digit_optind = 0;
9
10 while (1) {
11 int this_option_optind = optind ? optind : 1;
12 int option_index = 0;
13 static struct option long_options[] = {
14 {"add", required_argument, 0, 0 },
15 {"append", no_argument, 0, 0 },
16 {"delete", required_argument, 0, 0 },
17 {"verbose", no_argument, 0, 0 },
18 {"create", required_argument, 0, 'c'},
19 {"file", required_argument, 0, 0 },
20 {0, 0, 0, 0 } //option结构体数组的最后一个元素必须以0填充
21 };
22
23 //第三个实参表明这个函数也支持短选项
24 c = getopt_long(argc, argv, "abc:d:012",
25 long_options, &option_index);
26 if (c == -1) //当解析完毕后或者并未指定命令行参数才跳出循环
27 break;
28
29 switch (c) {
30 case 0:
31 //option_index存有当前匹配到的选项在option结构体数组中的下标
32 printf("option %s", long_options[option_index].name);
33 //optarg:如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无
34 //参数时,optarg为NULL。
35 if (optarg)
36 printf(" with arg %s", optarg);
37 printf("\n");
38 break;
39
40 case '0':
41 case '1':
42 case '2':
43 if (digit_optind != 0 && digit_optind != this_option_optind)
44 printf("digits occur in two different argv-elements.\n");
23 //第三个实参表明这个函数也支持短选项
24 c = getopt_long(argc, argv, "abc:d:012",
25 long_options, &option_index);
26 if (c == -1) //当解析完毕后或者并未指定命令行参数才跳出循环
27 break;
28
29 switch (c) {
30 case 0:
31 //option_index存有当前匹配到的选项在option结构体数组中的下标
32 printf("option %s", long_options[option_index].name);
33 //optarg:如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无
34 //参数时,optarg为NULL。
35 if (optarg)
36 printf(" with arg %s", optarg);
37 printf("\n");
38 break;
39
40 case '0':
41 case '1':
42 case '2':
43 if (digit_optind != 0 && digit_optind != this_option_optind)
44 printf("digits occur in two different argv-elements.\n");
45 digit_optind = this_option_optind;
46 printf("option %c\n", c);
47 break;
48
49 case 'a':
50 printf("option a\n");
51 break;
52
53 case 'b':
54 printf("option b\n");
55 break;
56
57 case 'c':
58 printf("option c with value '%s'\n", optarg);
59 break;
60
61 case 'd':
62 printf("option d with value '%s'\n", optarg);
63 break;
64
65 case '?':
66 break;
67
68 default:
69 printf("?? getopt returned character code 0%o ??\n", c);
70 }
71 }
72
73 if (optind < argc) {
74 printf("non-option ARGV-elements: ");
75 while (optind < argc)
76 printf("%s ", argv[optind++]);
77 printf("\n");
78 }
79
80 exit(EXIT_SUCCESS);
81 }
运行示例如下:
zhihua@zy:~/sysFuncPrac$ ./a.out --append --add 100 -d 200 -2
option append
option add with arg 100
option d with value '200'
option 2
zhihua@zy:~/sysFuncPrac$ ./a.out --create
./a.out: option '--create' requires an argument
zhihua@zy:~/sysFuncPrac$ ./a.out --create 300 -c
option c with value '300'
./a.out: option requires an argument -- 'c'
4.getopt_long_only函数:
getopt_long_only类似于getopt_long,但是它把'-'
开头的选项当作长选项来处理。如果该选项与长选项不匹配,而与短选项匹配,则可以作为短选项解析。