getopt和getopt_long函数的参数解析


  当在做嵌入式开发或网络编程时,通常会因为产品型号不同,或者监听的端口号不同需要对程序进行修改,因此为了提高代码重用性,我们可以在执行程序时出传入相应的命令行参数,减少对源码的修改。在linux 中有提供了三种函数可以对命令行参数进行处理: getopt()、getopt_long()、getopt_long_only()

getopt()函数

#include <unistd.h>  //包含头文件
 
       int getopt(int argc, char * const argv[],
                  const char *optstring); //函数原型
 
       extern char *optarg;  //声明全局变量
       extern int optind, opterr, optopt;

 先从最简单的getopt说起,它只能解析短选项,getopt_long是前者的加强版,用来解决长参数的问题。
 在函数的原型我们可以了解到第一和第二个参数是main函数的argc(函数参数的个数)和argv(函数参数的指针),而第三个参数称为选项字符串:
eg:char *optstring = "ab:c::d";
 在上面optstring所指向的字符串中,单个字符a表示该选项没有参数“-a”,带一个冒号的单个字符b表示有且必须加参数“-b 100/-b100”带两个冒号的单个字符c表示该参数可有可无“-c200”。在optstring上传后getopt会依次检查参数命令行是否指定了-a、-b、-c、-d(多次调用直到返回-1),当检查到相应参数被指定时则getopt会返回相应参数名称。
 全局变量:
optarg指向该选项下传入的值。
optind表示的是下一个将被处理到的参数在argv的下标值。
opterr = 0时在getopt函数遇到错误时将不会将信息输出到标准输出。
通过下面的例子来理解一下getopt函数:

#include<stdio.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
        int opt;
        char *string = "ab:c::d";
        while ((opt = getopt(argc, argv, string))!= -1)
        {
              printf("opt = %c\t\t", opt);
              printf("optarg = %s\t\t",optarg);
              printf("optind = %d\t\t",optind);
              printf("argv[optind-1] = %s\n",argv[optind-1]);
        }
}

 编译运行后其结果如下:

panghu@Ubuntu-14:~/exercise$ ./getopt -a -b 200 -c300 -d
opt = a         optarg = (null)         optind = 2              argv[optind-1] = -a
opt = b         optarg = 200            optind = 4              argv[optind-1] = 200
opt = c         optarg = 300            optind = 5              argv[optind-1] = -c300
opt = d         optarg = (null)         optind = 6              argv[optind-1] = -d

选项c参数可有可无,不带参数也可以:

panghu@Ubuntu-14:~/exercise$ ./getopt -a -b 200 -c -d        
opt = a         optarg = (null)         optind = 2              argv[optind-1] = -a
opt = b         optarg = 200            optind = 4              argv[optind-1] = 200
opt = c         optarg = (null)         optind = 5              argv[optind-1] = -c
opt = d         optarg = (null)         optind = 6              argv[optind-1] = -d

输入选项参数错误时:

panghu@Ubuntu-14:~/exercise$ ./getopt -a 100 -b 200 -c -d
opt = a         optarg = (null)         optind = 2              argv[optind-1] = -a
opt = b         optarg = 200            optind = 5              argv[optind-1] = 200
opt = c         optarg = (null)         optind = 6              argv[optind-1] = -c
opt = d         optarg = (null)         optind = 7              argv[optind-1] = -d

 因为a是默认不带参数的,因此输入参数100导致解析错误。

getopt_long()函数

#include <getopt.h>  //函数头文件
 
       int getopt_long(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);  //函数原型
 

 前面提到说getopt_long函数的优点就是可以处理长参数(长选项参数),他比getopt多了两个参数:
const struct option *longopts:longopts指向的是一个option类型的结构体:

struct option {
               const char *name;  //参数名称
               int         has_arg;  //是否带参数 no_argument(0) 不带参、required_argument(1) 需要带参、
              						//optional_argument(2)参数可有可无
               int        *flag;   //当指针为空时函数返回val,非空时,val被初始化到flag指向的int类型中切返回0
               int         val;	  //指定函数找到选项时的的返回值或flag非空时指定*flag的值
           };

int *longindex:如果longopts非空时,它所指向的变量会存放当前参数符合longopts的第几个元素描述,即longopts下标值。
还是通过下面的例子来理解一下getopt_long函数:

#include<stdio.h>
#include<getopt.h>
int main(int argc, char *argv[])
{
    int opt;
    int digit_optind = 0;
    int option_index = 0;
    char *string = "a::b:c:d";
    static struct option long_options[] =
    {
        {"reqarg", required_argument,NULL, 'r'},
        {"optarg", optional_argument,NULL, 'o'},
        {"noarg",  no_argument      ,NULL,'n'},
        {NULL,     0                ,NULL, 0},
    };
    while((opt =getopt_long_only(argc,argv,string,long_options,&option_index))!= -1)
    {
        printf("opt = %c\t\t", opt);
        printf("optarg = %s\t\t",optarg);
        printf("optind = %d\t\t",optind);
        printf("argv[optind] =%s\t\t", argv[optind]);
        printf("option_index = %d\n",option_index);
    }
}

 编译运行后其结果如下:

panghu@Ubuntu-14:~/exercise$ ./getopt_long --noarg --reqarg 100 --optarg=200
opt = n         optarg = (null)         optind = 2              argv[optind] =--reqarg          option_index = 2
opt = r         optarg = 100            optind = 4              argv[optind] =--optarg=200      option_index = 0
opt = o         optarg = 200            optind = 5              argv[optind] =(null)            option_index = 1

可选选项输入错误:

扫描二维码关注公众号,回复: 9620948 查看本文章
panghu@Ubuntu-14:~/exercise$ ./getopt_long --noarg --reqarg 100 --optarg 200
opt = n         optarg = (null)         optind = 2              argv[optind] =--reqarg          option_index = 2
opt = r         optarg = 100            optind = 4              argv[optind] =--optarg          option_index = 0
opt = o         optarg = (null)         optind = 5              argv[optind] =200               option_index = 1

 同样可选选项输入错误时会导致optarg = (null)导致解析错误。
需要指定参数未给参数:

panghu@Ubuntu-14:~/exercise$ ./getopt_long --noarg --reqarg --optarg=200                                                         
opt = n         optarg = (null)         optind = 2              argv[optind] =--reqarg          option_index = 2
opt = r         optarg = --optarg=200           optind = 4              argv[optind] =(null)            option_index = 0

getopt_long_only() 函数

 #include <getopt.h>
 
       int getopt_long_only(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);

getopt_long_only函数原型参数表与与getopt_long一致,getopt_long_only在遇到长参数时首先会在longops中指向的选项里寻找该长选项-option,如果没有则会拆成-o、-p、-t ···这样的参数在optsring中匹配,而getopt_long会直接拆成短选项在optsring匹配。

参考:https://blog.csdn.net/cashey1991/article/details/7942809

发布了11 篇原创文章 · 获赞 3 · 访问量 302

猜你喜欢

转载自blog.csdn.net/weixin_42647166/article/details/104592443