在实际编程当中,本身编写代码处理命令行参数是比较麻烦且易出错的。通常咱们会直接使用getopt()
和getopt_long()
函数,下文将介绍具体的使用方法。html
getopt()
用于处理”单字母“选项,如-a
, -t
等。函数声明以下:web
#include <unistd.h> int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg; extern int optind, opterr, optopt;
对于前两个参数argc
和grgv[]
,通常直接使用main()
传递进来的数值。用过C语言的同窗应该比较熟悉,简单复习一下。shell
#include <stdlib.h> #include <stdio.h> int main(int argc, char const *argv[]) { //在C99标准推出以前,变量不能在for()声明,为了兼容性,这里提早声明"i" int i; printf("argc = %d\n", argc); if (argc > 1) { for (i = 0; i < argc; ++i) { printf("argv[%d] = %s\n", i, argv[i]); } } return 0; }
argc
: argument count, 记录了命令行参数的个数(包括命令自己)编程
argv
: argument vector, 记录了命令行参数的具体内容数组
$ ./test 1 2 3 argc = 4 argv[0] = ./test argv[1] = 1 argv[2] = 2 argv[3] = 3
optstring
: 做为getopt()
的第三个参数,用于规定合法选项(option)以及选项是否带参数(argument)。通常为合法选项字母构成的字符串,若是字母后面带上冒号:
就说明该选项必须有参数。如"ht:"
说明有两个选项-h
和-t
且后者(-t
)必须带有参数(如-t 60
)。函数
option character
: 通常状况下,getopt()
读取到合法选项,就返回该选项(一个字母)。-1
:结束标志。while ( (opt = getopt(argc, argv, "ab:") ) != -1) {...}
?
: 通常状况下,遇到非法选项或者参数缺失都会返回?
。若是须要区分这两种错误,能够在optstring
的开头加上:
,如:ht:
, 这样参数缺失就返回:
,非法选项就返回?
。:
:在optstring
参数开头第一个字符为:
时,遇到参数缺失返回:
。参考下方代码(摘自Linux Programming by Example)可帮助理解int oc; /* option character */ char *b_opt_arg; while ((oc = getopt(argc, argv, ":ab:")) != -1) { switch (oc) { case 'a': /* handle -a, set a flag, whatever */ break; case 'b': /* handle -b, get arg value from optarg */ b_opt_arg = optarg; break; case ':': /* missing option argument 参数缺失*/ fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0], optopt); break; case '?': default: /* invalid option 非法选项*/ fprintf(stderr, "%s: option '-%c' is invalid: ignored\n", argv[0], optopt); break; } }
optind
(option index): 数组下标,指向下一个未处理的参数。经过例子(摘自stackoverflow)能更好理解:#include <stdio.h> #include <string.h> #include <unistd.h> int main(int argc, char *argv[]) { char optStr[] = "ab"; int c; while ((c = getopt(argc, argv, optStr)) != -1) { printf("optind: %d\n", optind); switch (c) { case 'a': printf("-a\n"); break; case 'b': printf("-b\n"); break; case '?': printf("error\n"); break; } } return 0; }
测试结果:测试
$ ./a.out -ab #例子1 optind: 1 -a optind: 2 -b $ ./a.out -a #例子2 optind: 2 -a
例子1:ui
#argv[]数据以下 argv[0]="./a.out" argv[1]="-ab" argv[2]=0
从optind
=1开始,处理完a
,optind
指向b
所在位置,其实仍是1;处理完b,指向下一个选项,即2命令行
例子2:指针
#argv[]数据以下 argv[0]="./a.out" argv[1]="-a" argv[2]=0
从optind
=1开始,处理完a,指向下一个选项,即2
optarg
: 若是合法选项带有参数,那么对应的参数,赋值给optarg
根据函数名就能够知道getopt_long()
用于处理长选项,如-help
。函数声明以下:
#include <getopt.h> int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);
前三个选项和getopt()
彻底相同,在此再也不赘述。
longopts数组
: 用于规定合法长选项以及长选项是否带参数(argument)。涉及到的option结构体
声明以下struct option { const char *name; int has_arg; int *flag; int val; };
name
: 长选项的名称has_arg
: 参数状况符号常量 | 数值 | Meaning |
---|---|---|
no_argument |
0 |
无参数 |
required_argument |
1 |
有参数 |
optional_argument |
2 |
参数可选 |
考虑到“可读性”,通常使用“符号常量”
int *flag
: 若是flag
为 NULL
, getup_long()
返回val
的值; 若是不是NULL
, val
的值赋给flag
指针指向的内容,同时getopt_long()
返回 0int val
: flag
为NULL
,val
做为getopt_long()
的返回值;若是flag
不为NULL
,val
赋值给flag
指针所指内容;int *flag | return value |
---|---|
NULL |
val |
&name (<— val ) |
0 |
经过例子(摘自webbench)可加深理解
static const struct option long_options[]= { {"force",no_argument,&force,1}, //-force 参数三(flag)不为NULL,force=1,getopt_long()返回0 {"reload",no_argument,&force_reload,1}, {"time",required_argument,NULL,'t'}, {"help",no_argument,NULL,'?'}, //-help 第三个参数(flag)为NULL,直接返回 "?" {"http09",no_argument,NULL,'9'}, {"http10",no_argument,NULL,'1'}, {"http11",no_argument,NULL,'2'}, {"get",no_argument,&method,METHOD_GET}, {"head",no_argument,&method,METHOD_HEAD}, {"options",no_argument,&method,METHOD_OPTIONS}, {"trace",no_argument,&method,METHOD_TRACE}, {"version",no_argument,NULL,'V'}, {"proxy",required_argument,NULL,'p'}, {"clients",required_argument,NULL,'c'}, {NULL,0,NULL,0} //最后一个元素应该全为0 }; int main(int argc, char *argv[]) { int options_index=0; ... while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF ) { ... } }
注意:
longopts数组
的最后一个元素应该全为0.
longindex
: 通常设置为NULL
; 若是不为NUll
, 指向每次找到的长选项在longopts
的位置,能够经过该值(即索引)找到当前长选项的具体信息。但愿本文能帮助你们更好地理解getopt()
和getopt_long()
。
更多的相关用法能够参考Linux Programming by Example: The Fundamentals