getopt()函数

前言

  本文讲述源码中常见的getopt函数,并为本专栏的RPC项目用到时做准备。

getopt介绍

   getopt()函数是用来分析命令行参数的,参数argc和argv分别代表参数个数和内容,跟main()函数的命令行参数是一样的。optstring这个字符串的讲究就比较多了,分析命令行参数的时候就是根据这个字符串来的,将在下面进行介绍。

int getopt(int argc, char * const argv[], const char *optstring);

   getopt()会对 argv 中的条目进行顺序处理,其中第一个条目被忽略(对应执行的命令本身的字符串),之后对于 argv 数组中的每一个条目,getopt 将其中使用 '-' 开头的字符串视为参数项( option element ),参数项中除开始的 ‘-’ 字符外的所有字符被视为参数字符。

getopt的返回值

  getopt函数运用一次只会查询一次,会有中间变量来存储当前的位置的所以循环调用直到返回值为-1代表着结束,参数能正确的按照要求顺序读出。
  getopt正常调用时,会返回对应的合法参数字符对应的ASC码值.当遇到不合法的参数字符时(不包含在 optstring 中),会返回 ‘?’.当所有的命令行条目被解析完成后,getopt 返回 -1。
下面先来个简单的小测试:

#include <iostream>
#include <unistd.h> //需包含的头文件
using namespace std;

int main(int argc, char *argv[]) {
    int ret;
    ret=getopt(argc,argv,"iabc");
    while(ret!=-1){
        cout<<char(ret)<<endl;
        ret=getopt(argc,argv,"iabc");
    }
    return 0;
}

结果:
在这里插入图片描述
  简单来看就是只要参数符合我这个字符串里面的字符的,全都调用正常,能得到起对应的asc码值。如果参数是这样的呢?
在这里插入图片描述
  ( getopt 会维持对应的访问位置的记录,使得下一次对 getopt 的调用会继续上一次的返回位置进行参数的解析)这种情况需要避免,好在这个函数提供了不一样的参数给我们使用。

optstring参数

  • 1.单个字符,表示选项。(如上面测试的那样。)
  • 2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。(这是头文件定义的,不需要我们再来定义的,属于全局变量)
  • 3 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。
  • 4.当 optstring 字符串使用字符 ‘+’ 开始时, getopt 会在遇到第一个非合法参数项时结束.而当 optstring 字符串使用 ‘-’ 开始时,所有的非参数项的 argv 数组中的条目均被视为字符值为 1 的参数项的参数,也就是被视为 -1 test 形式的调用,getopt 返回值为 1,而 optarg 指向字符串 test.
  • 5.当 getopt 遇到解析问题时,如遇到非法的参数字符或者某个需要参数的命令行项没有参数时,默认会通过 stderr 输出错误信息,并将返回值设置为 '?' 。若在 optstring 中可能存在的 ‘+’ 和 ‘-’ 之后加入 ‘:’,如这样变为 "-:i:a::bc" (注意新加入的 ‘:’ 的位置),则 getopt 不会显式的通过 stderr 输出错误信息,同时在遇到解析错误时,若错误原因为非法参数字符,则 getopt 返回 ‘:’,而若原因为参数项缺少对应的参数,则 getopt 返回 ‘?’.

测试内容

接一个冒号的情况:

#include <iostream>
#include <unistd.h>
using namespace std;

int main(int argc, char *argv[]) {
    int ret;
    ret=getopt(argc,argv,"i:abc");
    while(ret!=-1){
        cout<<char(ret)<<endl;
        if(optarg!=NULL)printf("%s\n",optarg);
        ret=getopt(argc,argv,"i:abc");
    }
    return 0;
}

在这里插入图片描述

接两个冒号的情况:

#include <iostream>
#include <unistd.h>
using namespace std;

int main(int argc, char *argv[]) {
    int ret;
    ret=getopt(argc,argv,"i:a::bc");
    while(ret!=-1){
        cout<<char(ret)<<endl;
        if(optarg!=NULL)printf("%s\n",optarg);
        ret=getopt(argc,argv,"i:a::bc");
    }
    return 0;
}

在这里插入图片描述
开头有个’-':

#include <iostream>
#include <unistd.h>
using namespace std;

int main(int argc, char *argv[]) {
    int ret;
    ret=getopt(argc,argv,"-i:a::bc");
    while(ret!=-1){
        cout<<ret<<endl;
        if(optarg!=NULL)printf("%s\n",optarg);
        ret=getopt(argc,argv,"-i:a::bc");
    }
    return 0;
}

在这里插入图片描述
默认出错:
在这里插入图片描述
在这里插入图片描述
  63为'?'的asc码值。

头文件的相关内容

#include <unistd.h>
       extern char *optarg;  //选项的参数指针
       extern int optind,   //下一次调用getopt的时,从optind存储的位置处重新开始检查选项。 
       extern int opterr,  //当opterr=0时,getopt不向stderr输出错误信息。
       extern int optopt;  //当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt中,getopt返回'?’、
       int getopt(int argc, char * const argv[], const char *optstring);

测试代码

#include <iostream>
#include <unistd.h>
using namespace std;

int main(int argc, char *argv[]) {
    int ret;
    ret=getopt(argc,argv,"iabc");
    while(ret!=-1){
        cout<<char(ret)<<endl;
        cout<<optind<<endl;
        if(optarg!=NULL)printf("%s\n",optarg);
        ret=getopt(argc,argv,"-i:a::bc");
    }
    return 0;
}

在这里插入图片描述

参考

https://blog.csdn.net/kunikida/article/details/8922754
https://www.cnblogs.com/yhjoker/p/13873739.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值