getopt()函数

  • Post author:
  • Post category:其他




前言

本文讲述源码中常见的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



版权声明:本文为weixin_60208935原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。