getopt函数笔记

来来来,走过路过不要错过~买一送四啦~~

#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()返回'?',这会使得这种情况不能与无效选项的情况区分开。

猜你喜欢

转载自blog.csdn.net/weixin_40728015/article/details/81223990