上午在看源码项目 webbench 时,刚开始就被一个似乎挺陌生函数 getopt_long() 给卡住了,说实话这函数没怎么见过,自然不知道这哥们是干什么的。于是乎百度了一番,原来是处理命令行选项参数的,的确,正规点的大型程序一般第一步就是处理命令行参数的,接着才是主干程序。在百度和 man 的帮助下,找到了具体使用方法和解释,二话不说赶紧学习一下,并总结出文档记录一下。

平时在写程序时常常需要对命令行参数进行处理,因为参数少,自己解析就可以搞定;如果命令行个数比较多时,如果按照顺序一个一个定义参数含义很容易造成混乱,而且如果程序只按顺序处理参数的话,一些“可选参数”的功能将很难实现,这个问题在 linux 中用 getopt 等函数可以优雅地解决。

一、查询linux命令手册:

#include<unistd.h>
#include<getopt.h> /*所在头文件 */
int getopt(intargc, char * const argv[], const char *optstring);
int getopt_long(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int*longindex);
int getopt_long_only(int argc, char * const argv[],const char *optstring,
const struct option *longopts, int*longindex);
extern char *optarg; /*系统声明的全局变量 */
extern int optind, opterr, optopt;

先拿最简单的 getopt 函数开刀,getopt_long 只是前者的增强版,功能多点而已。

二、getopt函数

1、定义

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

2、描述

getopt是用来解析命令行选项参数的,但是只能解析短选项: -d ,不能解析长选项:--prefix

3、参数

argc:main()函数传递过来的参数的个数
argv:main()函数传递过来的参数的字符串指针数组
optstring:选项字符串,告知 getopt()可以处理哪个选项以及哪个选项需要参数

4、返回

如果选项成功找到,返回选项字母;如果所有命令行选项都解析完毕,返回 -1;如果遇到选项字符不在 optstring 中,返回字符 '?';如果遇到丢失参数,那么返回值依赖于 optstring 中第一个字符,如果第一个字符是 ':' 则返回':',否则返回'?'并提示出错误信息。

5、下边重点举例说明optstring的格式意义:

char*optstring = “ab:c::”;
单个字符a 表示选项a没有参数 格式:-a即可,不加参数
单字符加冒号b: 表示选项b有且必须加参数 格式:-b 100或-b100,但-b=100错
单字符加2冒号c:: 表示选项c可以有,也可以无 格式:-c200,其它格式错误

上面这个 optstring 在传入之后,getopt 函数将依次检查命令行是否指定了 -a, -b, -c(这需要多次调用 getopt 函数,直到其返回-1),当检查到上面某一个参数被指定时,函数会返回被指定的参数名称(即该字母)

optarg —— 指向当前选项参数(如果有)的指针。
optind —— 再次调用 getopt() 时的下一个 argv指针的索引。
optopt —— 最后一个未知选项。
opterr ­—— 如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。

以上描述的并不生动,下边结合实例来理解:

6、实例:

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

编译上述程序并执行结果:

输入选项及参数正确的情况

dzlab:~/test/test#./opt -a100 -b  -c  -d
opt = a optarg = optind = argv[optind] = -b
opt = b optarg = optind = argv[optind] = -c
opt = c optarg = optind = argv[optind] = -d
opt = d optarg = (null) optind = argv[optind] = (null)

或者这样的选项格式(注意区别):

dzlab:~/test/test#./opt -a100 -b200 -c300 -d
opt = a optarg = optind = argv[optind] = -b200
opt = b optarg = optind = argv[optind] = -c300
opt = c optarg = optind = argv[optind] = -d
opt = d optarg = (null) optind = argv[optind] = (null)

选项a是可选参数,这里不带参数也是正确的

dzlab:~/test/test#./opt -a -b  -c  -d
opt = a optarg = (null) optind = argv[optind] = -b
opt = b optarg = optind = argv[optind] = -c
opt = c optarg = optind = argv[optind] = -d
opt = d optarg = (null) optind = argv[optind] = (null)

输入选项参数错误的情况

dzlab:~/test/test#./opt -a  -b  -c  -d
opt = a optarg = (null) optind = argv[optind] =
opt = b optarg = optind = argv[optind] = -c
opt = c optarg = optind = argv[optind] = -d
opt = d optarg = (null) optind = argv[optind] = (null)

导致解析错误,第一个 optarg = null,实际输入参数 100,由于格式不正确造成的(可选参数格式固定)

参数丢失,也会导致错误,c选项是必须有参数的,不加参数提示错误如下:

dzlab:~/test/test#./opt -a -b  -c
opt = a optarg = (null) optind = argv[optind] = -b
opt = b optarg = optind = argv[optind] = -c
./opt: optionrequires an argument -- 'c'
opt = ? optarg = (null) optind = argv[optind] = (null)

这种情况,optstring 中第一个字母不是':',如果在 optstring 中第一个字母加':',则最后丢失参数的那个选项 opt 返回的是':',不是'?',并且没有提示错误信息,这里不再列出。

命令行选项未定义,-e选项未在optstring中定义,会报错:

dzlab:~/test/test#./opt -a -b  -e
opt = a optarg = (null) optind = argv[optind] = -b
opt = b optarg = optind = argv[optind] = -e
./opt: invalidoption -- 'e'
opt = ? optarg = (null) optind = argv[optind] = (null)

到这里应该已经把getopt函数的功能讲解清楚了吧,下边来说说 getopt_long 函数,getopt_long 函数包含了 getopt 函数的功能,并且还可以指定"长参数"(或者说长选项),与 getopt 函数对比,getopt_long 比其多了两个参数:

三、getopt_long函数

1、定义

int getopt_long(int argc, char * const argv[], const char *optstring,

                                 const struct option *longopts,int *longindex);

2、描述

包含 getopt 功能,增加了解析长选项的功能如:--prefix --help

3、参数

longopts    指明了长参数的名称和属性
longindex 如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值

4、返回

对于短选项,返回值同getopt函数;对于长选项,如果flag是NULL,返回val,否则返回0;对于错误情况返回值同getopt函数
5、struct option
struct option {
const char *name; /* 参数名称 */
int has_arg; /* 指明是否带有参数 */
int *flag; /* flag=NULL时,返回value;不为空时,*flag=val,返回0 */
int val; /* 用于指定函数找到选项的返回值或flag非空时指定*flag的值 */
}; 

6、参数说明:

has_arg  指明是否带参数值,其数值可选:
no_argument 表明长选项不带参数,如:--name, --help
required_argument 表明长选项必须带参数,如:--prefix /root或 --prefix=/root
optional_argument 表明长选项的参数是可选的,如:--help或 –prefix=/root,其它都是错误

接着看一下实例操作会更加深刻地理解:

7、实例:

int main(intargc, char *argv[])
{
int opt;
int digit_optind = ;
int option_index = ;
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, , NULL, },
};
while((opt =getopt_long_only(argc,argv,string,long_options,&option_index))!= -)
{
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);
}
}

编译上述程序并执行结果:

正确输入长选项的情况


dzlab:~/test/test#./long --reqarg  --optarg= --noarg
opt = r optarg = optind = argv[optind] = --optarg= option_index =
opt = o optarg = optind = argv[optind] = --noarg option_index =
opt = n optarg =(null) optind = argv[optind] =(null) option_index =

或者这种方式:

dzlab:~/test/test#./long –reqarg= --optarg= --noarg
opt = r optarg = optind = argv[optind] = --optarg= option_index =
opt = o optarg = optind = argv[optind] = --noarg option_index =
opt = n optarg =(null) optind = argv[optind] =(null) option_index =

可选选项可以不给参数

dzlab:~/test/test#./long --reqarg  --optarg --noarg
opt = r optarg = optind = argv[optind] = --optarg option_index =
opt = o optarg =(null) optind = argv[optind] =--noarg option_index =
opt = n optarg =(null) optind = argv[optind] =(null) option_index =

输入长选项错误的情况

dzlab:~/test/test#./long --reqarg  --optarg  --noarg
opt = r optarg = optind = argv[optind] = --optarg option_index=
opt = o optarg =(null) optind = argv[optind] = option_index =
opt = n optarg =(null) optind = argv[optind] =(null) option_index =

这时,虽然没有报错,但是第二项中 optarg 参数没有正确解析出来(格式应该是 —optarg=200)

必须指定参数的选项,如果不给参数,同样解析错误如下:

dzlab:~/test/test#./long --reqarg --optarg= --noarg
opt = r optarg =--optarg= optind = argv[optind] =--noarg option_index =
opt = n optarg =(null) optind = argv[optind] =(null) option_index =

长选项的举例说明暂且就这么多吧,其它如选项错误、缺参数、格式不正确的情况自己再试验一下。

四、getopt_long_only函数

getopt_long_only 函数与 getopt_long 函数使用相同的参数表,在功能上基本一致,只是 getopt_long 只将 --name 当作长参数,但 getopt_long_only 会将 --name 和 -name 两种选项都当作长参数来匹配。getopt_long_only 如果选项 -name 不能在 longopts 中匹配,但能匹配一个短选项,它就会解析为短选项。

命令行选项解析函数(C语言):getopt()和getopt_long()的更多相关文章

  1. 命令行选项解析函数getopt()

    1.定义: int getopt(int argc, char * const argv[], const char *optstring); 2.描述: getopt是用来解析命令行选项参数的,但是 ...

  2. webbench源码学习-->命令行选项解析函数getopt和getopt_long函数

    对于webbench这个网站压力测试工具网上介绍的很多,有深度详解剖析的,对于背景就不在提了, 听说最多可以模拟3万个并发连接去测试网站的负载能力,这里主要是学习了一下它的源码,做点 笔记. 官方介绍 ...

  3. 9、getopt的用法,被用来解析命令行选项参数

    #include <unistd.h>       extern char *optarg;  //选项的参数指针       extern int optind,   //下一次调用ge ...

  4. getopt:命令行选项、参数处理

    在写shell脚本时经常会用到命令行选项.参数处理方式,如: ./test.sh -f config.conf -v --prefix=/home -f 为短选项,它需要一个参数,即config.co ...

  5. NUnit-Console 命令行选项详解

    本文为 Dennis Gao 原创或翻译技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. NUnit-Console 命令行选项 NUnit-Console 命令行选项列表 指定运行哪 ...

  6. python argparse模块解析命令行选项简单使用

    argparse模块的解析命令行选项简单使用 util.py #!/usr/bin/env python # coding=utf-8 import argparse parser = argpars ...

  7. argparse - 命令行选项与参数解析(转)

    argparse - 命令行选项与参数解析(译)Mar 30, 2013 原文:argparse – Command line option and argument parsing 译者:young ...

  8. 命令行选项 - Mozilla 产品与私有技术 | MDN - Google Chrome

    命令行选项 在本文章中 语法规则 使用命令行选项 示例 用户配置档 -CreateProfile profile_name -CreateProfile "profile_name prof ...

  9. LoadRunner 11安装Micosoft Visual C++ 2005 SP1时提示命令行选项语法错误

    如果安装LoadRunner 11时弹窗提示"Micosoft Visual C++ 2005 SP1 可再发行组件包(X86):'命令行选项语法错误.键入命令 / ? 可获得帮助信息'&q ...

随机推荐

  1. Enum 枚举小结 java **** 最爱那水货

    import java.util.HashMap; import java.util.Map; /** * 收单行 大写首字母 和对应的编码<br/> * * ABC 农业银行<br ...

  2. Cookie——Javascript

    基本的cookie操作有三种:读取.写入.删除. var CookieUtil = { //根据cookie的name获取相应的value.它会在document.cookie字符串中查找cookie ...

  3. Struct2

    1.MVC思想概述 Servlet作为前端控制器,负责接收客户端发送的请求,在Servlet中只包含控制逻辑和简单的前端处理:然后调用后端javabean来完成实际的逻辑处理: 最后转发到相应的jsp ...

  4. python 颜色定义

    1.颜色定义说明格式:\033[显示方式;前景色;背景色m前景色 背景色 颜色---------------------------------------30 40 黑色31 41 红色32 42 ...

  5. Java一步一步构建web系统 在IDEA下用Maven搭建多模块项目

    1.需求 做一个项目会有很多模块,主要是方便复用,通过各个模块之间聚合.模块也可以独立出来,如公用类库,也可以在做其它项目中使用.该文的实例会有两个模块:分别为dallin-web模块,dallin- ...

  6. SQL语句操作数据-------开启旅程路线喽!

    岁月,是一首诗,一首蕴含丰富哲理的诗,岁月是一峰骆驼,驮着无数人的梦想. 一.SQL的简介 SQL的全称是“结构化查询语言”(Structure Query Language),SQL语言是针对数据库 ...

  7. HTML中input标签的alt属性和title属性的比较

    经常用到这两个属性,但是一直没有总结他们的区别.现在我对他们两个的用法做一下总结: 相同点:他们都会飘出一个小浮层,显示文本内容. 不同点: 1.alt只能是元素的属性,而title即可以是元素的属性 ...

  8. JavaScript学习笔记3之 数组 & arguments(参数对象)& 数字和字符串转换 & innerText/innerHTML & 鼠标事件

    一.Array数组 1.数组初始化(Array属于对象类型) /*关于数组的初始化*/ //1.创建 Array 对象--方法1: var arr1=[]; arr1[0]='aa';//给数组元素赋 ...

  9. AloneJs.msgbox() —— 弹出消息框

    一.引用 <link href="https://cdn.suziyun.com/alonejs.min.css" rel="stylesheet" /& ...

  10. 需要记住的几个ASCII码

    --------- A--------- a---------