该函数位于头文件<unistd.h>中,函数的原型为int getopt(int argc,char * argv[],const char* optstring);
看到该函数的前两个参数,我们可以立刻联想到main()函数,虽然有时候main()函数的前两个参数会省略,但如果我们需要通过命令行传参的话,就得用上它两了;
在正式介绍getopt()函数之前,我们还得说下与它有关的四个参数:
extern char* optarg; //该参数指向选项的参数 比如:a.out -a "c++" ,optarg指向的就是"c++"
extern int optind; //该参数指向下一次检索的位置
extern int opterr; //该参数表示是否将错误消息输出到stderr,为0时表示不输出,初始值为1
extern int optopt; //该参数表示不在选项字符串optstring中的选项
首先,我们看个选项字符串的例子,并给出其中的规则:
"ab:c:d::e",该选项字符串对应到命令行的就是
main.out -a -b b_argument -c c_argument -d [d_argument] -e
或者 main.out -a -bb_argument -cc_argument -d [d_argument] -e
通过上述的命令行我们可以看出,选项后面没有冒号的是不用接任何参数,即它对应的参数为null;选项后面有冒号的必须接参数,否则会报错,但是选项和参数可以连在一起;选项后面有两个冒号的,后面可接可不接参数,但是如果接参数的话,则选项和参数之间一定要有空格.
这里得补充一个小知识点,就是如果字符与之对应的整型是相等,至于打印到终端的形式,取决于我们怎么看,%c,就是字符,%d,就是整型。
下面,通过实例进行更加详细的讲解;
实验环境为linux,用的编译器为g++,文件名为test.cpp。
#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
int ch;
printf("optind:%d,opterr:%d\n\n",optind,opterr);
while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
{
printf("optind: %d\n", optind);
switch (ch)
{
case 'a':
printf("HAVE option: -a\n\n");
printf("The argument of -a is %s\n\n",optarg);
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\n",(char)optopt);
printf("The arguement of unknown option is %s\n\n",optarg);
break;
}
}
首先,编译源文件,g++ test.cpp
默认输出为 a.out
执行如下命令: ./a.out -a "a_argument " -b "b_argument" -cc_argument -e "e_argument" -f"f_argumetn"-z
输出如下:
optind:1,opterr:1
optind: 2
HAVE option: -a
The argument of -a is (null)
optind: 5
HAVE option: -b
The argument of -b is b_argument
optind: 6
HAVE option: -c
The argument of -c is c_argument
./a.out: invalid option -- 'e'
optind: 7
Unknown option: e
The arguement of unknown option is (null)
optind: 9
Have option: -f
The argument of -f is f_argument
./a.out: invalid option -- 'z'
optind: 10
Unknown option: z
The arguement of unknown option is (null)
结果分析:首先,optind和opterr的初始值都为1,命令行的第一个参数为可执行文件本身,而optind会指向选项的位置,会跳过第一个参数,所以初始值为1,opterr的默认初始值就为1;进入while循环,optind指向选项 -a ,但从命令行,可以看出该选项后面是不接参数的,即便该选项后面接的是形如参数的样式,其对应的参数也为空;当getopt()返回'a'时,此时的optind会指向下一个检索位置,于是它的值就变为2,但我们知道argv[2]是参数,不是选项,于是getopt()函数会寻找下一个选项,于是找到了 -b 选项,这个后面是必须接参数的,那么其参数就为"b_argument",此时optind指向的位置为5,即 -c,该选项后面必须接参数,即为"c_argument",此时,optind更新为6,指向了选项 -e,从optstring选项字符串中可以看到,其后面接两个冒号(::),从代码的运行结果可以看到其对应的参数也为null,(这里和我在网上查找的资料有出入,好几份资料都显示,对于两个冒号的选项,其后如果接参数的话,不能含有空格,否则会报错);然后继续寻找下一个选项,找到了选项 -f ,其与后面的参数之间没有空格,于是后面的参数就为其参数;紧接着,继续寻找下一个参数,这时找到了-z ,但该参数并没有出现了选项字符串中,于是就有了后面的错误提示,注意,此时getopt()函数返回的是字符问号'?';此时后面已经没有选项,于是函数返回-1,循环结束。
以下部分直接从参考资料中搬过来了。
最后,有个小知识要说明下,getopt()函数会改变argv[]中参数的顺序,经过多次调用该函数,argv[]中的选项和选项的参数会被放置在前,并且optind会指向非选项的位置,通过例子可以更加直观的理解。
#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
printf("--------------------------\n");
for(i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
printf("--------------------------\n");
//int aflag=0, bflag=0, cflag=0;
int ch;
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("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");
}
命令行:./main zheng -b "qing er" han -c123 qing
输出结果为:
--------------------------
./main
zheng
-b
qing er
han
-c123
qing
--------------------------
optind:1,opterr:1
--------------------------
optind: 4
HAVE option: -b
The argument of -b is qing er
optind: 6
HAVE option: -c
The argument of -c is 123
----------------------------
optind=4,argv[4]=zheng
--------------------------
./main
-b
qing er
-c123
zheng
han
qing
--------------------------
可以看到最开始argv[]内容为:
./main
zheng
-b
qing er
han
-c123
qing
在执行了多次getopt后变成了
./main
-b
qing er
-c123
zheng
han
qing
我们看到,被getopt挑出的选项和对应的参数都按顺序放在了数组的前面,而那些既不是选项又不是参数的会按顺序放在后面。而此时optind为4,即指向第一个非选项也非选项的参数,zheng。
写的有些乱,也是作为资料供自己参考,如果哪里写的不好,还请指出!!
来源: http://www.cnblogs.com/qingergege/p/5914218.html