getopt_long函数解析命令行参数
转载:http://blog.csdn.net/hcx25909/article/details/7388750
每一天你都在使用大量的命令行程序,是不是感觉那些命令行参数用起来比较方便,他们都是使用getopt来实现的。
在Linux下使用getopt写程序是一种比较cool的事情,下面来简单的介绍一下getopt的使用。
=== getopt使用 ===
在讨论参数处理之前,我们先明确两个概念:选项、选项参数
gcc -g -o test test.c
我们经常使用上面的命令来编译程序,这里g和o就是选项,其中test就是o的选项参数
下面我们来看一下getopt:
首先是函数声明:
#include <unistd.h>
extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
extern int optreset;
int getopt(int argc, char * const *argv, const char *optstring);
直接看一个例子:
/* getopt.c */
#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
int aflag=, bflag=, cflag=;
int ch;
while ((ch = getopt(argc, argv, "ab:c")) != -)
{
printf("optind: %d\n", optind);
switch (ch) {
case 'a':
printf("HAVE option: -a\n");
aflag = ;
break;
case 'b':
printf("HAVE option: -b\n");
bflag = ;
printf("The argument of -b is %s\n", optarg);
break;
case 'c':
printf("HAVE option: -c");
cflag = ;
break;
case '?':
printf("Unknown option: %c\n",(char)optopt);
break;
}
}
}
通过上面的例子,大家应该可以照猫画虎,就可以在自己的程序中使用getopt函数了。
getopt()每调用一次返回一个选项。
argc 和 argv 很显然就是 main 函数的两个参数。
字符串 optstring 可以包含下列元素:单个字符,字符后面接一个冒号说明后面跟随一个选项参数,字符后面接两个冒号说明后面跟随一个可有可无的选项参数。例如,一个选项字符 "x" 表示选项 "-x" ,选项字符 "x:" 表示选项和其参数 "-x argument",选项字符 "x::" 表示选项 x 的参数是可选的(“::” 是 GNU 增加的,不一定在所有的UNIX 系统下都可以使用)。
getopt()的返回后,如果有选项参数的话 optarg 指向选项参数,并且变量 optind 包含下一个 argv 参数作为对 getopt() 下一次调用的索引。变量 optopt 保存最后一个由 getopt() 返回的已知的选项。
当参数列已经到结尾时getopt()函数返回-1,当遇到一个未知的选项时 getopt 返回'?'。参数列中选项的解释可能会被'--'取消,由于它引起 getopt()给参数处理发送结束信号并返回-1。
很多时候,我们不希望输出任何错误信息,或更希望输出自己定义的错误信息。可以采用以下两种方法来更改getopt()函数的出错信息输出行为:
在调用getopt()之前,将opterr设置为0,这样就可以在getopt()函数发现错误的时候强制它不输出任何消息。
如果optstring参数的第一个字符是冒号,那么getopt()函数就会保持沉默,并根据错误情况返回不同字符,如下:
“无效选项” ―― getopt()返回'?',并且optopt包含了无效选项字符(这是正常的行为)。
“缺少选项参数” ―― getopt()返回':',如果optstring的第一个字符不是冒号,那么getopt()返回'?',这会使得这种情况不能与无效选项的情况区分开。
例如optstring为:a:b::c,表示a带一个参数,b可选,c不带参数
如果输入d,“无效选项“,getopt返回'?'
如果输入的a忘记带参数,“缺少选项参数”,getopt应返':' ;如果不再optstring的第一个字符不是':'的话,那么将会把这个错当成"无效参数",从而getopt返回'?';从而无法区别错误类型
比如:
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -d -b foo
optind: 2
HAVE option: -a
./getopt: invalid option -- d
optind: 3
Unknown option: d
optind: 5
HAVE option: -b
The argument of -b is foo
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt -a -- -c -b foo
optind: 2
HAVE option: -a
getopt 的源代码在下面,getopt 将只会解释到 -a。
变量opterr和optind都被初始化为1。如果想要略去命令行的前几个参数,可以在调用getopt()前将optind设成其他值。
如果不希望getopt()输出出错信息,将全域变量 opterr 设为 0 即可。
是不是使用比较简单啊!
=== getopt_long使用 ===
我敢说,几乎每个人在接触到一个新的命令的时候,第一件干的事情就是 cmd -h 或者是 cmd --help,-h我们都知道是使用getopt来实现的,那么--help是怎么实现的呢?那就是getopt_long了,他可以支持长参数
先看一个例子程序:
#include <stdio.h>
#include <getopt.h> int do_name, do_gf_name;
char *l_opt_arg; static const char *shortopts = "l:ng";
struct option longopts[] = {
{"name", no_argument, NULL, 'n'},
{"gf_name", no_argument, NULL, 'g'},
{"love", required_argument, NULL, 'l'},
{, , , },
}; int main (int argc, char *argv[])
{
int c; while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -)
{
switch (c)
{
case 'n':
printf ("My name is LYR.\n");
break;
case 'g':
printf ("Her name is BX.\n");
break;
case 'l':
l_opt_arg = optarg;
printf ("Our love is %s!\n", l_opt_arg);
break;
}
}
return ;
}
代码中我们使用getopt_long来实现长选项的解析,其中我们使用了一个结构体struct options的数组,struct options longopt[].
struct options的定义如下:
struct option{
const char *name;
int has_arg;
int *flag;
int val;
};
对结构中的各元素解释如下:
const char *name
这是选项名,前面没有短横线。譬如"help"、"verbose"之类。
int has_arg
描述了选项是否有选项参数。如果有,是哪种类型的参数,此时,它的值一定是下表中的一个。
符号常量 数值 含义
no_argument 0 选项没有参数
required_argument 1 选项需要参数
optional_argument 2 选项参数可选
int *flag
如果这个指针为NULL,那么 getopt_long()返回该结构val字段中的数值。如果该指针不为NULL,getopt_long()会使得它所指向的变量中填入val字段中的数值,并且getopt_long()返回0。如果flag不是NULL,但未发现长选项,那么它所指向的变量的数值不变。
int val
这个值是发现了长选项时的返回值,或者flag不是NULL时载入*flag中的值。典型情况下,若flag不是NULL,那么val是个真/假值,譬如1或0;另一方面,如果flag是NULL,那么 val通常是字符常量,若长选项与短选项一致,那么该字符常量应该与optstring中出现的这个选项的参数相同。
每个长选项在长选项表中都有一个单独条目,该条目里需要填入正确的数值。数组中最后的元素的值应该全是0。数组不需要排序,getopt_long()会进行线性搜索。但是,根据长名字来排序会使程序员读起来更容易。
下面,我们看一下程序中的这个结构:
struct option longopts[] = {
{"name", no_argument, NULL, 'n'},
{"gf_name", no_argument, NULL, 'g'},
{"love", required_argument, NULL, 'l'},
{, , , },
};
结构说明了三个常选项,name、gf_name、love三个选项,其中love需要选项;它们分别对应的短选项是n、g、l。
注意:上面结构体数组中的结构体的第三个参数flag都为NULL.
程序运行结果:
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --name
My name is LYR.
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -n
My name is LYR.
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long -l me
Our love is me!
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$ ./getopt_long --love me
Our love is me!
wangyao@fisherman:~/Desktop/Advanced Linux Programming/ALP-listings/Trainning$
=== Reference ===
GNU提供的getopt()函数的特点
http://blog.csdn.net/realduke2000/archive/2007/10/05/1812126.aspx
使用 getopt() 进行命令行处理
http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html
=== Questions ===
1、如何在getopt中指定可选参数
2、能否实现使用一个选项带多个参数,例如 scanner -i 1.1.1.1 2.2.2.2 3.3.3.3
getopt_long函数解析命令行参数的更多相关文章
- linux 中解析命令行参数(getopt_long用法)
linux 中解析命令行参数(getopt_long用法) http://www.educity.cn/linux/518242.html 详细解析命令行的getopt_long()函数 http:/ ...
- C语言中使用库函数解析命令行参数
在编写需要命令行参数的C程序的时候,往往我们需要先解析命令行参数,然后根据这些参数来启动我们的程序. C的库函数中提供了两个函数可以用来帮助我们解析命令行参数:getopt.getopt_long. ...
- Windows下解析命令行参数
linux通常使用GNU C提供的函数getopt.getopt_long.getopt_long_only函数来解析命令行参数. 移植到Windows下 getopt.h #ifndef _GETO ...
- boost之program_options库,解析命令行参数、读取配置文件
一.命令行解析 tprogram_options解析命令行参数示例代码: #include <iostream> using namespace std; #include <boo ...
- optparse模块解析命令行参数的说明及优化
一.关于解析命令行参数的方法 关于“解析命令行参数”的方法我们一般都会用到sys.argv跟optparse模块.关于sys.argv,网上有一篇非常优秀的博客已经介绍的很详细了,大家可以去这里参考: ...
- python解析命令行参数
常常需要解析命令行参数,经常忘记,好烦,总结下来吧. 1.Python 中也可以所用 sys 的 sys.argv 来获取命令行参数: sys.argv 是命令行参数列表 参数个数:len(sys.a ...
- 解析main函数的命令行参数
原创文章,转载请正确注明本文原始URL及作者. 介绍 写C/C++程序,我们常常需要把main函数的参数作为选项来传递.在linux中,解析选项有专门的函数可以用. int getopt(int ar ...
- getopt、getopt_long和getopt_long_only解析命令行参数
一:posix约定: 下面是POSIX标准中关于程序名.参数的约定: 程序名不宜少于2个字符且不多于9个字符: 程序名应只包含小写字母和阿拉伯数字: 选项名应该是单字符或单数字,且以短横 '-' 为前 ...
- C++main函数与命令行参数,退出程序
本文翻译自:https://docs.microsoft.com/en-us/cpp/cpp/main-function-command-line-args?view=vs-2019 (除动态链接库d ...
随机推荐
- PID221 / 烦人的幻灯片☆ x
超详细解释!我都被我自己惊呆了! (这个题目意思我缓冲了很久!一定要读懂题!否则做不出来) 题目不懂就多读呀~ 提交你的代码 查看讨论和题解 题目描述 李教授于今天下午做一个非常重要的演讲.不幸的是他 ...
- 洛谷 P1505 BZOJ 2157 [国家集训队]旅游
bzoj题面 Time limit 10000 ms Memory limit 265216 kB OS Linux 吐槽 又浪费一个下午--区间乘-1之后,最大值和最小值更新有坑.新的最大值是原来最 ...
- 初始化String,System,OutOfMemoryError
对于String, System而言,其初始化过程和 Thread一致.而对于OutOfMemoryError而言,其继承结构如下: 因此对于OutOfMemoryError,会首先将状态改为4,然后 ...
- 深入浅出mysql笔记---1、mysql下载安装
深入浅出mysql笔记---1.mysql下载安装 一.总结 一句话总结: linux下rpm安装即可 1.linux的wget命令作用? 下载文件的工具:比如wget http://cn.wordp ...
- 一、基础篇--1.1Java基础-面向对象的特征
面向对象的特征 封装.继承和多态 https://blog.csdn.net/jianyuerensheng/article/details/51602015 封装: 定义:封装就是将数据或函数等集合 ...
- c++实验10 图的应用实验
大体与上次实验相同,特点为图是邻接表存储结构 --博客后半部分有程序的所有代码-- 1.图邻接表存储结构表示及基本操作算法实现 所加载的库函数或常量定义及类的定义: #include "Se ...
- Unity Ray 射线
射线:射线是3D世界一个向一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射. 用途:射线范围比较广,多用于碰撞检测(如:子弹飞行是否击中目标).角色移动等. Ray是一个结 ...
- 2018.03.29 python-matplotlib 图表生成
'''Matplotlib -> 一个python版的matlab绘图接口,以2D为主,支持python,numpy,pandas基本数据结构,高效图标库''' import numpy as ...
- Windows命令集锦
1.用于私网的IP地址段: 10.0.0.0/8: 10.0.0.0-10.255.255.255 172.16.0.0/12: 172.16.0.0-172.31.255.255 192.168.0 ...
- Delphi中的进制转换
二进制转换 function binToDec(Value: string): integer; var str: string; i: integer; begin Str := UpperCase ...