结合一个小例子来说明关于getopt()函数的一些概念,一定要注意区分和理解我下面说的名词,千万不能混淆了。否则就容易概念不清了。
#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
int ch;
printf("--------------------------\n");
for(i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
printf("--------------------------\n");
printf("\n\n");
printf("optind:%d,opterr:%d\n",optind,opterr);
printf("--------------------------\n");
while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
{
printf("optind: %d\n", optind);
switch (ch)
{
case 'a':
printf("HAVE option: -a\n\n");
break;
case 'b':
printf("HAVE option: -b\n");
printf("The argument of -b is %s\n\n", optarg);
break;
case 'c':
printf("HAVE option: -c\n");
printf("The argument of -c is %s\n\n", optarg);
break;
case 'd':
printf("HAVE option: -d\n");
break;
case 'e':
printf("HAVE option: -e\n");
printf("The argument of -e is %s\n\n", optarg);
break;
case '?':
printf("Unknown option: %c\n",(char)optopt);
break;
}
printf("-----\n");
printf("optarg:%s\n",optarg);
printf("optopt:%c\n",optopt);
printf("----------------------------\n");
}
printf("----------------------------\n");
printf("optind=%d,argv[%d]=%s\n",optind,optind,argv[optind]);
printf("--------------------------\n");
for(i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
printf("--------------------------\n");
return 0;
}
如果执行命令:./main zheng -b "qing er" han -c123 qing
命名包含了选项-b,其参数"qing er";-c,其参数123,程序参数(操作数)zheng,han,qing 和程序名./main
则:
./main zheng -b "qing er" han -c123 qing
argv[0] argv[1] argv[2] argv[3] argv[4] argv[5] argv[6]
argc = 7
main()函数参数:包含程序名,选项,选项参数,程序参数(操作数)
main()函数参数个数argc:包含程序名,选项,选项参数,程序参数(操作数) ,是他们的字符串数之总和。
main()函数参数字符串数组argv[]:包含程序名字符串,选项字符串,选项参数字符串,程序参数(操作数)字符串
选项字符串:"a:b:cd::e",由getopt(argc, argv, "ab:c:de::")函数的第三个参数指定。
选项:分带参和不带参选项 ,执行命令时,选项可有可无,如-b,-c等等。选项后的冒号表示参数,一个冒号就表示这个选项后面必须带有参数,不带参数报错。
getopt() 所设置的全局变量包括:
char *optarg——当前选项参数字串(如果有的话)。不是选项的字串,如上命令的话,它的值先是"qing er",后是123。
int optind——argv的当前索引值(下一个argv)。当getopt()在while循环中使用时,循环结束后,剩下的字串视为操作数,在 argv[optind]至argv[argc-1]中可以找到剩下的那些操作数。
int opterr——opterr非零表示产生的错误要输出到stderr上,初值为1。
int optopt——当发现无效选项字符之时,getopt()函数或返回'?'字符,或返回':'字符,并且optopt包含了所发现的无效选项字符。它还是一个选项,是不在选项字串"a:b:cd::e"中的选项,但不是程序参数(操作数),不是选项参数。
optind:实际上真正的参数是用第二个main()函数的参数开始,也就是argv[1],所以optind的初始值为1;
选项和参数写在一起,他们占用一个main()函数参数字符串argv[n],如上面选项-c,其参数123,写在一起-c123:所以他两占一起占用argv[5]。
最后要说明一下,getopt()会改变argv[]中参数的顺序。经过多次getopt()后,argv[]中的选项和选项的参数会被放置在数组前面,而optind 会指向第一个非选项和参数的位置。
执行getope之前:argv[]的输出:
./main
zheng
-b
qing er
han
-c123
qing
执行getopt后,argv[]的输出:
./main
-b
qing er
-c123
zheng
han
qing
此时optind指向第一个非选项非参数(操作数或叫程序参数)zheng
前面提到过不带参数的选项可以写在一起,所以当getopt()找到-z的时候,发现在optstring 中没有,这时候他就认为h也是一个选项,也就是-h和-z写在一起了,依次类推,直到找到-e,发现optstring中有。
如果这样执行:
./main -zheng -b "qing er" han -c123 qing
则能识别-zheng中的-e选项,但一样不能把han中的a识别为-a选项。