来来来,走过路过不要错过~买一送四啦~~
#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
上一个项目经常接触的getopt函数,今天顺便总结了吧。在介绍这个函数之前,需要先理解这几个概念:
选项:
像gcc -c test.c -o test 这句脚本语句里面,gcc是程序名,c和o这样以 ‘ - ’ 短杠开头的就是选项,而test.c和test分别是c和o的选项后面携带的参数,
此外,关于POSIX关于选项的规定还有:
①特殊参数‘--'指明所有参数都结束了,其后任何参数都认为是操作数。
②多个不需要选项参数的选项,可以合并。(譬如:foo -a -b -c ---->foo -abc)
③选项应该在操作数出现之前出现。
。。。
选项字符串:
"a:b:cd::e"
这就是选项字符串,其数据类型为char const * ,也就是getopt函数的第三个参数需要传的值。
其实"a:b:cd::e"对应的选项就是-a -b -c -d -e ,而中间那些冒号' : '代表选项后面跟随的参数。一个冒号' : '表示这个参数肯定存在,而且选项与参数之间可以有空格,也可以没有空格。两个冒号' :: '表示这个参数可以存在,也可以不存在,但是选项与参数之间一定一定一定不能有空格。
————————————————————————————————————————————————-————————
理解完这两个重要概念之后,就可以开始介绍getopt函数了。
声明如下,
int getopt(int argc, char * const argv[], const char *optstring);
argc和argv可以理解成就是我们main(argc,argv)里面的这俩家伙,optstring就是上面所讲的选项字符串,复习一下,optstring是const char * 型数据,储存在文字常量区哦。
当给定getopt()命令参数的数量 (argc
)、指向这些参数的数组 (argv
) 和选项字串 (optstring
) 后,getopt()
将返回第一个选项,并设置一些全局变量。使用相同的参数再次调用该函数时,它将返回下一个选项,并设置相应的全局变量。如果不再有可识别的选项,将返回 -1
,此任务就完成了。
为了让程序员能够灵活地使用getopt,我们还需要看清楚下面这四个赠品:
extern char *optarg; //用来存放每次getopt函数运行时返回的那一个选项(如果有)
extern int optind; //用来记录下一次getopt运行时的检索位置
extern int opterr; //表示是否将错误信息输出到stderr,为0则不输出到stderr
extern int optopt; //不在选项字符串optstring中的选项
弄清楚这些后,我们可以写一个小小的demo来试试水。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char * argv[]){
for(int i = 0;i<argc; i++){
printf("%s\t",argv[i]);
}
printf("\n");
const char * optstr = ":s:n:a:";
char ch;
printf("optind = %d\n",optind);
printf("*****************************************\n");
while( (ch=getopt(argc,argv,optstr)) != -1){
switch(ch){
case 's':
printf("\noptind = %d\t",optind);
printf("school: %s\n",optarg);
break;
case 'n':
printf("optind = %d\t",optind);
printf("name: %s\n",optarg);
break;
case 'a':
printf("optind = %d\t",optind);
printf("age: %d\n",atoi(optarg));
break;
case '?':
printf("optind = %d\t",optind);
printf("invalid option!!\n");
break;
}
}
printf("\n*****************************************\n");
printf("optind = %d\n",optind);
printf("\n");
for(int i = 0;i<argc; i++){
printf("%s\t",argv[i]);
}
printf("\n");
return 0;
}
编译运行一下
这里拓展一下,当getopt拿到的选项不在optstring中时,会返回'?',而全局变量optopt中包含了无效选项字符。
所以当我们故意输错一个选项的时候,会运行case '?'部分的语句。
如果不需要报错的话,我们可以
①在调用getopt()之前,将opterr设置为0,这样就可以在getopt()函数发现错误的时候强制它不输出任何消息
②如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
a“无效选项” —— getopt()返回'?',并且optopt包含了无效选项字符(这是正常的行为)。
b“缺少选项参数” —— getopt()返回':',如果optstring的第一个字符不是冒号,那么getopt()返回'?',这会使得这种情况不能与无效选项的情况区分开。