前言

在linux下学习开源代码Webbench,遇到get_long等函数的用法,一时有点懵,故想深入了解这类命令行解析函数,并记此博文。

1、getopt

getopt主要用来处理短命令行选项,例如 ./test -v 中的 -v 就是一个短选项。使用该函数需引入头文件<unistd.h>,下面是该函数定义:

int getopt (int ___argc, char *const *___argv, const char *__shortopts);

其中___argc和___argv是main函数中传递的参数个数和内容,__shortopts用来指定可以处理哪些选项,以下为__shortopts的示例:

"a:bc"

该示例表明该程序可以接受3个选项:-a  -b  -c ,其中a后面的 :表示该选项后面跟一个参数,即如 -a text 的形式,选项后面跟的参数会被保存到optarg变量中。下面是一个使用的示例:

#include <stdio.h>
#include <unistd.h>

void use_getopt(int argc,char **argv){

  int ch;
  ){
    switch(ch){
    case 'a':
      printf("option a: %s\n",optarg);
      break;
    case 'b':
      printf("option b: \n");
      break;
    case '?':
      printf("unknown option \n");
      break;
    default:
      printf("default");
    }
  }
}

int main(int argc,char **argv){

  use_getopt(argc,argv);
  ;
}

执行 ./test -a aa -b -c 输出结果如下:

option a: aa
option b:
./test: invalid option -- 'c'
unknown option 

2、getopt_long

getopt_long支持长选项的命令行解析,所谓长选项即诸如 --help 的形式,使用该函数需要引入头文件<getopt.h>,下面是getopt_long和getopt_long_only的函数原型:

#include <getopt.h>

int getopt_long (int ___argc,
                 char *const *___argv,
                 const char *__shortopts,
                 const struct option *__longopts,
                 int *__longind);

int getopt_long_only (int ___argc,
                      char *const *___argv,
                      const char *__shortopts,
                      const struct option *__longopts,
                      int *__longind);

其中___argc,___argv, __shortopts 和 getopt 中的含义一样,下面解释 __longopts 和 __longind.

__longopts指向一个 struct option 的数组,下面是option的定义:

struct option
{
  const char *name;
  int has_arg;
  int *flag;
  int val;
};
  • name — 长选项的名称,例如 help
  • has_arg — 是否带参数,0不带参数,1必须带参数,2参数可选
  • flag — 指定长选项如何返回结果,如果flag为NULL, getopt_long()会返回val. 如果flag不为NULL,getopt_long会返回0,并且将val的值存储到flag中
  • val — 将要被getopt_long返回或者存储到flag指向的变量中的值

下面是一个使用示例:

 struct option opts[] = {
    {, NULL, 'v'},
    {, NULL, 'n'},
    {, NULL, 'h'}
  };

以上{"version", 0, NULL, 'v'}, version 即为长选项的名称, 即按如下形式 --version,,0 表示该选项后面不带参数,NULL 表示直接将v返回(字符v在ascii码中对应的数值), 即在使用getopt_long遍历到该条选项时,getopt_long 返回值为字符v对应的ascii码值。

__longind表示长选项在__longopts中的位置,例如上面的例子中,version对应的__longind为0,name对应的__longind为1,help对应的__longind为2,该项主要用于调试,一般设为NULL即可。

下面是一个使用示例:

void use_getopt_long(int argc,char **argv){

  const char *optstring = "vn:h";
  int c;
  struct option opts[] = {
    {, NULL, 'v'},
    {, NULL, 'n'},
    {, NULL, 'h'}
  };

  ){
    switch(c){
    case 'n':
      printf("name is %s\n",optarg);
      break;
    case 'v':
      printf("verson is 0.0.1\n");
      break;
    case 'h':
      printf("this is help\n");
      break;
    case '?':
      printf("unknown option\n");
      break;
    :
      printf("the return val is 0\n");
      break;
    default:
      printf("default");
    }
  }
}

运行程序 ./test --name evenleo --version --help --haha ,结果如下:

name is evenleo
verson is 0.0.1
this is help
./test: unrecognized option '--haha'
unknown option

当然也可以使用短选项 ./test -n evenleo -v -h,结果如下:

name is evenleo
verson is 0.0.1
this is help

将上面的程序进行修改,将struct option中的flag和__longind设为具体值

void use_getopt_long2(int argc, char *argv[]) {

  const char *optstring = "vn:h";
  int c;
  , f_n = -, f_h = -, opt_index = -;
  struct option opts[] = {
    {, &f_v, 'v'},
    {, &f_n, 'n'},
    {, &f_h, 'h'}
  };

  ) {
    switch(c) {
    case 'n':
      printf("name is %s\n", optarg);
      break;
    case 'v':
      printf("version is 0.0.1\n");
      break;
    case 'h':
      printf("this is help\n");
      break;
    case '?':
      printf("unknown option\n");
      break;
     :
      printf("f_v is %d \n", f_v);
      printf("f_n is %d \n", f_n);
      printf("f_h is %d \n", f_h);
      break;
    default:
      printf("------\n");
    }
    printf("opt_index is %d\n\n", opt_index);
  }
}

运行 ./test -name evenleo -version -help,结果如下:

f_v is -1
f_n is 110
f_h is -1
opt_index is 1

f_v is 118
f_n is 110
f_h is -1
opt_index is 0

f_v is 118
f_n is 110
f_h is 104
opt_index is 2

以上结果可以看出,当给flag指定具体的指针后,getopt_long会返回0,并且val的值赋给了flag指向的变量,下面我们用短选项执行一下程序,运行 ./test -n evenleo -v -h ,结果如下:

name is evenleo
opt_index is -1

version is 0.0.1
opt_index is -1

this is help
opt_index is -1

可以看出使用短选项时getopt_long相当于getopt,flag和__longind不起作用。

3、getopt_long和getopt_long_only区别

下面解释一下 getopt_long 和 getopt_long_only的区别,用use_getopt_long函数 ,运行 ./test -name evenleo -verson -help,结果如下:

name is ame
verson is 0.0.1
./test: invalid option -- 'e'
unknown option
./test: invalid option -- 'r'
unknown option
./test: invalid option -- 's'
unknown option
./test: invalid option -- 'i'
unknown option
./test: invalid option -- 'o'
unknown option
name is -help

可以看出使用短选项标识符 - 指向长选项时,程序还是会按短选项来处理,即一个字符一个字符的解析。下面将函数use_getopt_long做一些更改,即将getopt_long改为getopt_long_only,如下:

void use_getopt_long3(int argc,char **argv){

  const char *optstring = "vn:h";
  int c;
  struct option opts[] = {
    {, NULL, 'v'},
    {, NULL, 'n'},
    {, NULL, 'h'}
  };

  ){
    switch(c){
    case 'n':
      printf("name is %s\n",optarg);
      break;
    case 'v':
      printf("verson is 0.0.1\n");
      break;
    case 'h':
      printf("this is help\n");
      break;
    case '?':
      printf("unknown option\n");
      break;
    :
      printf("the return val is 0\n");
      break;
    default:
      printf("default");
    }
  }
}

再运行 ./test -name evenleo -version -help,结果如下:

name is evenleo
verson is 0.0.1
this is help

即使用 getopt_long_only 时, - 和 -- 都可以作用于长选项, 而使用 getopt_long 时,只有 -- 可以作用于长选项.

文章大部分内容参考http://blog.zhangjikai.com/2016/03/05/%E3%80%90C%E3%80%91%E8%A7%A3%E6%9E%90%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0--getopt%E5%92%8Cgetopt_long/

【C】命令行参数解析——getopt、getopt_long及getopt_long_only的更多相关文章

  1. Python命令行参数解析模块getopt使用实例

    Python命令行参数解析模块getopt使用实例 这篇文章主要介绍了Python命令行参数解析模块getopt使用实例,本文讲解了使用语法格式.短选项参数实例.长选项参数实例等内容,需要的朋友可以参 ...

  2. python命令行参数解析模块argparse和docopt

    http://blog.csdn.net/pipisorry/article/details/53046471 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的o ...

  3. shell 命令行参数(getopt和getopts)

    getopt 命令 使用getopt命令,可以解析任何命令行选项和参数,但是用法比较复杂.getopt的命令用法如下: $ getopt --help 用法: getopt optstring par ...

  4. [转]Python 命令行参数和getopt模块详解

    FROM : http://www.tuicool.com/articles/jaqQvq 有时候我们需要写一些脚本处理一些任务,这时候往往需要提供一些命令行参数,根据不同参数进行不同的处理,在Pyt ...

  5. Python 命令行参数和getopt模块详解

    有时候我们需要写一些脚本处理一些任务,这时候往往需要提供一些命令行参数,根据不同参数进行不同的处理,在Python里,命令行的参数和C语言很类似(因为标准Python是用C语言实现的).在C语言里,m ...

  6. gflags命令行参数解析

    gflags库是google开源的命令行参数解析工具. 安装 官方没有提供二进制库,但是Debian/Ubuntu平台本身提供了二进制库,可以直接git clone https://github.co ...

  7. [Go] 命令行参数解析包(flag 包)使用详解

    Go 的 flag 包可以解析命令行的参数. 一.命令行语法 命令行语法主要有以下几种形式: cmd -flag       // 只支持bool类型 cmd -flag=xxx cmd -flag ...

  8. $命令行参数解析模块argparse的用法

    argparse是python内置的命令行参数解析模块,可以用来为程序配置功能丰富的命令行参数,方便使用,本文总结一下其基本用法. 测试脚本 把以下脚本存在argtest.py文件中: # codin ...

  9. Google开源命令行参数解析库gflags

    Google开源命令行参数解析库gflags http://blog.csdn.net/lming_08/article/details/25072899 CMDLINE的解析 http://blog ...

随机推荐

  1. 分析 JUnit 框架源代码

    本文转载至http://www.ibm.com/developerworks/cn/java/j-lo-junit-src/ 分析 JUnit 框架源代码 理解 JUnit 测试框架实现原理和设计模式 ...

  2. codevs 2977 二叉堆练习1x

    时间限制: 10 s 空间限制: 32000 KB 题目等级 : 白银 Silver       题目描述 Description 已知一个二叉树,判断它是否为二叉堆(小根堆) 输入描述 Input ...

  3. 『HGOI 20190917』Lefkaritika 题解 (DP)

    题目概述 一个$n \times m$的整点集.其中$q$个点被m被设置为不能访问. 问这个点集中含有多少个不同的正方形,满足不包含任何一个不能访问的点. 对于$50\%$的数据满足$1 \leq n ...

  4. matplotlib(二):折线图

    import numpy as np import matplotlib.pyplot as plt import matplotlib.dates as mdates # 解决中文显示问题 plt. ...

  5. 2019icpc南京网络赛 A 主席树

    题意 给一个\(n\times n\)的螺旋矩阵,给出其中的\(m\)个点的值分别为各个点上数字的数位之和,给出\(q\)个询问,每次询问从\((x1,y1)\)到\((x2,y2)\)的子矩阵的和. ...

  6. jQuery事件之一次性事件

    语法: $(selector).one(type, data, callback) 作用: (1)为每一个匹配元素的特定事件(比如click)绑定一个一次性的事件处理函数. (2)每个对象上,这个事件 ...

  7. JVM之Java类加载机制

    什么是类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这既是虚拟机的类加载机制 类的生命周期 生命周期简述 ...

  8. Oracle DBCA工具检测不到ASM磁盘组

    本例环境: 操作系统OEL 6.5 数据库版本:11.2.0.4 问题:DBCA建库的时候,检测不到ASM磁盘组 因素一:可能是在授权的时候执行了 chown –R 775 /u01/app等修改权限 ...

  9. 八十三:redis之redis的字符串、过期时间、列表操作

    字符串操作 设置值 set key value 设置有空格的值,加引号 set username 'hello world' 获取值 get key 删除值:del key 清除所有内容:flusha ...

  10. 六十七:flask上下文之Local线程隔离对象

    Local对象在flask中,类似于request对象,其实是绑定到了werkzeug.local.Local对象上,这样即使是同一个对象,在多线程中都是隔离的,类似的对象还有session以及g对象 ...