|
函数原型及相关变量:#include <unistd.h>
int getopt(int argc, char *const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt; 参数解释:
char *optarg
如果选项接受参数的话,那么它就是选项参数
int optind
argv 的当前索引。当 while 循环检测结束时,剩下的操作数在 argv[optind] 至 argv[argc-1] 中能找到( 注意,'argv[argc] == NULL' )
int opterr
当这个变量非零(默认非零)时,getopt() 函数为 ”无效选项“ 和 ”缺少选项参数“ 这两种错误情况输出它自己的错误消息
int optopt
当发现无效字符的时候,getopt() 函数或者返回 ‘?' 字符,或者返回 ':' 字符,并且 optopt 包含了所发现的无效选项字符。
getopt() 函数也使用 main 中的两个参数 argc 和 argv 以及一个选项区别符字符串(option specifier string<optstring>)来告诉 getopt 程序都定义了什么哪些选项以及它们是否关联了值。
optstring 是一个简单的字符列表,每一个代表一个单字符选项。如果一个字符后面跟着一个冒号,那么它表明这个选项后面需要接着一个值。另外,在 bash 中 getopts 命令有着类似的功能。
如 getopt(argc, argv, "if:lr") 中,允许有 4 个简单的选项: -i, -l, -r, -f,其中 -f后面跟着冒号,所以在实际使用中, -f 后面要带着个值.
getopt 返回的结果是 argv 数组中的下一个选项字符(从程序名开始算起的下一个。也就是,每当找到一个有效的选项字母,就会返回这个字母)。重复调用 getopt 就会依次得到每一个选项。getopt 有如下的特性:
1、如果一个选项带有值,那这个 optarg 这个指针变量将指向这个值;
示例代码:
01 #include <stdio.h>
02 #include <unistd.h>
03
04 int main(int argc, char *argv[])
05 {
06 getopt(argc, argv, ":if:");
07
08 printf("%s\n", optarg);
09
10 return 0;
11 } 运行及打印结果:[root@localhost C]# ./getopt-2.exe -f write.c
write.c 注:在 ":if:" 中有两个冒号,对这两个冒号的解释是:
如果 getopt() 中第三个参数的第一个字符是冒号,那么 getopt() 函数就会保持沉默,并根据错误情况返回不同的字符,如下:
“无效选项”
getopt() 函数返回 '?',并且 optopt 包含了无效选项字符。
“缺少选项参数”
getopt() 函数返回 ':'。(如果 optstring 的第一个字符不是冒号,那么 getopt() 函数返回 '?',使得这种情况不能与无效选项的情况区别开来。
因此,将 optstring 的第一个字符设置成冒号是个好主意,因为这样就可以将 “无效选项” 和 “缺少选项参数” 区别开来。但付出的代价是,getopt() 函数沉默了,如此一来,就迫使我们自己要给出出错信息---如用 fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0], optopt); 打印出错信息。例如以下代码:
c:write.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int oc;
char *b_opt_arg;
while ((oc = getopt(argc, argv, ":if:")) != -1) {
switch (oc) {
case 'i':
printf(" i arg\n");
break;
case 'f':
printf("%s\n", optarg);
break;
case ':':
fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0], optopt);
break;
case '?':
fprintf(stderr, "%s: option '-%c' is invalid: ignored\n", argv[0], optopt);
break;
}
}
exit(0);
} 两次错误输出:[root@localhost C]# ./write.exe -f
./write.exe: option '-f' requires an argument
[root@localhost C]# ./write.exe -l
./write.exe: option '-l' is invalid: ignored 2、当不再有选项可以处理时,getopt 返回 -1. 一个特殊的符号是 --,这会引起 getopt 停止对后面选项的扫描。
测试代码一:
01 #include <stdio.h>
02 #include <unistd.h>
03
04 int main(int argc, char *argv[])
05 {
06 int opt;
07
08 opt = getopt(argc, argv, ":ijklmnf:");
09 printf("%d\n",opt);
10
11
12 opt = getopt(argc, argv, ":ijklmnf:");
13 printf("%d\n",opt);
14
15
16 opt = getopt(argc, argv, ":ijklmnf:");
17 printf("%d\n",opt);
18
19
20 return 0;
21 } 运行及其输出结果:[root@localhost C]# ./getopt-2.exe -i -k
105
107
-1
[root@localhost C]# ./getopt-2.exe -i -n
105
110
-1 由上可见,当处理完所有的选项若还想继续处理下一个时,opt 为 -1; 这里输出的整数指其实是参数的ASCII码
遇到 -- 时:
01 #include <stdio.h>
02 #include <unistd.h>
03
04 int main(int argc, char *argv[])
05 {
06 int opt;
07
08 while( (opt = getopt(argc, argv, ":ijklmnf:")) != -1 ){
09
10 printf("%c\n",opt);
11 }
12
13 return 0;
14 }
测试运行输出:[root@localhost C]# ./write-2.exe -j -k -- -f write.c
j
k
[root@localhost C]# ./write-2.exe -j -- -k
j 说明:
符合 POSIX 标准的 getopt() 函数一碰到不以 '-' 开始的命令行参数就停止寻找选项。GNU getopt() 是不一样的:它扫描整个命令行来寻找选项。当调用 GNU getopt() 函数处理命令行的时候,它重新排列 argv 的元素,这样当它重新排列完的时候,所有选项都移动到前面并且那些继续检查 argv[optind] 至 argv[argc-1] 中的剩余参数的代码仍正常工作。不管在什么情况下,碰到特殊参数 '--' 就结束选项的扫描。
3、如果遇到一个未知的选项,getopt 返回 ?,这个未知选项存储在外部变量 optopt 中。
测试代码:
01 #include <stdio.h>
02 #include <unistd.h>
03
04 int main(int argc, char *argv[])
05 {
06 int opt;
07
08 while( (opt = getopt(argc, argv, ":ijklmnf:")) != -1 ){
09
10 printf("%c\n",opt);
11 printf("%c\n",optopt);
12 }
13
14 return 0;
15 } 运行输出:[root@localhost C]# ./getopt-2.exe -z
?
z
4、如果选项要求一个值(如上代码中的 -f 参数),但在使用时没把值给出,getopt 一般返回 ? 号
在第一个字符的前面有冒号,那么如果需要给定值的参数后面没有给出值,那么返回冒号 :
测试代码和 3 中的一样,测试输出:[root@localhost C]# ./getopt-2.exe -f
:
f
如果 3 中的代码参数 ":ijklmnf:" 这里去掉 i 签面的冒号 : ,那么输出:
[root@localhost C]# ./getopt-2.exe -f./getopt-2.exe: option requires an argument -- f
?
f
外部变量 optind 是下一个要处理参数的索引值,getopt 使用它来记录 getopt 已经索引到了哪个值处。程序中一般很少设置到这个变量。如,getopt.exe -i -j 中,首先要处理的参数是 getopt.exe,下一个要处理的参数就是 -i,所以 -i 的索引值为 2 。
测试代码:
01 #include <stdio.h>
02 #include <unistd.h>
03
04 int main(int argc, char *argv[])
05 {
06 int opt;
07
08 while( (opt = getopt(argc, argv, ":ijklmnf:")) != -1 ){
09
10 printf("%c,%d\n",opt,optind);
11
12 }
13
14 return 0;
15 } 运行与输出:[root@localhost C]# ./getopt-2.exe -i -j -m
i,2
j,3
m,4 当所有的选项都被测试都被处理完时, optind 表示在 argv 数组的末尾处(未处理的参数声明都一起放在数组的末尾)里还剩下多少的参数声明(arguments)
示例代码:
01 int main(int argc, char *argv[])
02 {
03 int opt;
04
05 while( (opt = getopt(argc, argv, ":ijklmnf:")) != -1 ){
06
07 printf("%c,%d\n",opt,optind);
08
09 }
10
11 for(; optind < argc; optind++){
12 printf("%d\n");
13 printf("remain in argv-array argument%d: %s\n", optind,argv[optind]);
14 }
15 return 0;
16 } 运行及输出:[root@localhost C]# ./getopt-2.exe -i 'good' -k 'yes' -j 'ok' -l
i,2
k,4
j,6
l,8
5
remain in argv-array argument5: good
6
remain in argv-array argument6: yes
7
remain in argv-array argument7: ok
一些版本的 getopt 在遇到第一个非选项(non-option)参数时会听下来,并返回 -1,同时设定 optind 的值。其它的,如 Linux 提供的那些,可以处理在程序中任何地方出现的选项。注意,在这种情况下,getopt 重写 argv 数组,这样所有的非选项参数从 argv[optind] 开始连续的存放这些选项。对于 GNU 版本的 getopt,这个特性由 POSIXLY_COREECT 环境变量来控制.如果设置, getopt 将在第一个非选项参数处停下来.注意,POSIX 规格指出如果 opterr 变量非0, getopt 将会向 stderr 打印错误信息. |
|