一。理论
在 “-a a_arg -b b_arg -c”中,
选项:-a,-b,-c
参数:a_arg,b_arg
调用形式:
getopt(argc, argv,":ab::c")
找了一遍以后返回-1,因此最后总是会返回-1的。
a: 选项a后面有参数,可以用一个或者多个空格隔开,也可以不用空格,紧跟着a。即 【-a a_arg】 或者 【-aa_arg】
b:: b后面可以不跟参数,此时b后面用空格;也可以跟参数,此时参数要紧跟b。 即 【 -b 】 或者 【-bb_arg】
开头有“:”时,处理更为只能,能够区分无效选项和选项后面没有参数这两种情况。
getopt函数可以有效处理main函数的输入参数。
以下这段话摘自网络:
getopt()每调用一次返回一个选项。
argc 和 argv 很显然就是 main 函数的两个参数。
字符串 optstring 可以包含下列元素:单个字符,字符后面接一个冒号说明后面跟随一个选项参数,字符后面接两个冒号说明后面跟随一个可有可无的选项参数。例如,一个选项字符 "x" 表示选项 "-x" ,选项字符 "x:" 表示选项和其参数 "-x argument",选项字符 "x::" 表示选项 x 的参数是可选的(“::” 是 GNU 增加的,不一定在所有的UNIX 系统下都可以使用)。
getopt()的返回后,如果有选项参数的话 optarg 指向选项参数,并且变量 optind 包含下一个 argv 参数作为对 getopt() 下一次调用的索引。变量 optopt 保存最后一个由 getopt() 返回的已知的选项。
当参数列已经到结尾时getopt()函数返回-1,当遇到一个未知的选项时 getopt 返回'?'。参数列中选项的解释可能会被'--'取消,由于它引起 getopt()给参数处理发送结束信号并返回-1。
很多时候,我们不希望输出任何错误信息,或更希望输出自己定义的错误信息。可以采用以下两种方法来更改getopt()函数的出错信息输出行为:
在调用getopt()之前,将opterr设置为0,这样就可以在getopt()函数发现错误的时候强制它不输出任何消息。
如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
“无效选项” ―― getopt()返回'?',并且optopt包含了无效选项字符(这是正常的行为)。
“缺少选项参数” ―― getopt()返回':',如果optstring的第一个字符不是冒号,那么getopt()返回'?',这会使得这种情况不能与无效选项的情况区分开。
例如optstring为:a:b::c,表示a带一个参数,b可选,c不带参数
如果输入d,“无效选项“,getopt返回'?'
如果输入的a忘记带参数,“缺少选项参数”,getopt应返':' ;如果不再optstring的第一个字符不是':'的话,那么将会把这个错当成"无效参数",从而getopt返回'?';从而无法区别错误类型
ref:
http://www.cnitblog.com/zouzheng/archive/2007/04/02/25034.aspx
二,验证
【1】代码1
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int c;
char *optstr = ":a:b::cd:e:";
while( (c=getopt(argc, argv, optstr) )!= -1 )
{
switch (c)
{
case 'a':
printf("Yes: -a %s\n", optarg); break;
case 'b':
printf("Yes: -b %s\n", optarg); break;
case 'c':
printf("Yes: -c %s\n", optarg); break;
case 'd':
printf("Yes: -d %s\n", optarg); break;
case 'e':
printf("Yes: -e %s\n", optarg); break;
case '?':
printf("无效选项: -%c\n", optopt); break;
case ':':
printf("选项缺少参数: -%c\n", optopt); break;
default:break;
}
}
printf("剩下的选项: %d, %s\n", optind, argv[optind]);
printf("参数的重排列:\n");
for(c=1; c<argc; c++)
{
printf("%d : %s\n", c, argv[c]);
}
return 0;
}
运行:
administrator@ubuntu:~/test/sys_v$ ./a -a a_arg -bb_arg -c c_arg -g -d
Yes: -a a_arg
Yes: -b b_arg
Yes: -c (null)
无效选项: -g
选项缺少参数: -d
剩下的选项: 7, c_arg
参数的重排列:
1 : -a
2 : a_arg
3 : -bb_arg
4 : -c
5 : -g
6 : -d
7 : c_arg
administrator@ubuntu:~/test/sys_v$
(1)选项a需要参数,于是找到了参数a_arg
(2)选项b可以有参数也可以没有,后面的东西紧跟着b,于是找到了参数b_arg
(3)选项c没有参数,直接输出。
(4)-g参数不存在,于是识别为无效选项。
(5)-d选项后面应该有参数的,这里没有参数,所以提示缺少参数。这里-d放到了最后,如果放在前面,他就会把紧跟着的东西作为其参数。
(6)还有无人认领的参数c_arg,在重排列阶段,无人认领的参数被放到最后。
三 修改
3.1
将-bb_arg改为-b b_arg,将-g -d改为-d -g。则
(1)-b后面为空格,视为无参数,从而b_arg参数无人认领;
(2)-g被当作-d的参数。
administrator@ubuntu:~/test/sys_v$ ./a -a a_arg -b b_arg -c c_arg -g -d
Yes: -a a_arg
Yes: -b (null)
Yes: -c (null)
无效选项: -g
选项缺少参数: -d
剩下的选项: 7, b_arg
参数的重排列:
1 : -a
2 : a_arg
3 : -b
4 : -c
5 : -g
6 : -d
7 : b_arg
8 : c_arg
administrator@ubuntu:~/test/sys_v$ ./a -a a_arg -b b_arg -c c_arg -d -g
Yes: -a a_arg
Yes: -b (null)
Yes: -c (null)
Yes: -d -g
剩下的选项: 7, b_arg
参数的重排列:
1 : -a
2 : a_arg
3 : -b
4 : -c
5 : -d
6 : -g
7 : b_arg
8 : c_arg
3.2
char *optstr = ":a:b::cd:e:";
改为 char *optstr = "a:b::cd:e:"; 去掉了前面的冒号。这样的话,
选项缺参数或者无效选项都会返回?,无法区分开,这两者都会提示错误。
administrator@ubuntu:~/test/sys_v$ ./a -a a_arg -bb_arg -c c_arg -g -d
Yes: -a a_arg
Yes: -b b_arg
Yes: -c (null)
./a: invalid option -- 'g'
无效选项: -g
./a: option requires an argument -- 'd'
无效选项: -d
剩下的选项: 7, c_arg
参数的重排列:
1 : -a
2 : a_arg
3 : -bb_arg
4 : -c
5 : -g
6 : -d
7 : c_arg
如果不想要错误,可以在调用getopt之前执行 opterr=0;去除。
int c;
opterr=0;
char *optstr = "a:b::cd:e:";
执行:administrator@ubuntu:~/test/sys_v$ ./a -a a_arg -bb_arg -c c_arg -g -d
Yes: -a a_arg
Yes: -b b_arg
Yes: -c (null)
无效选项: -g
无效选项: -d
剩下的选项: 7, c_arg
参数的重排列:
1 : -a
2 : a_arg
3 : -bb_arg
4 : -c
5 : -g
6 : -d
7 : c_arg