当在做嵌入式开发或网络编程时,通常会因为产品型号不同,或者监听的端口号不同需要对程序进行修改,因此为了提高代码重用性,我们可以在执行程序时出传入相应的命令行参数,减少对源码的修改。在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
可选选项输入错误:
![](/qrcode.jpg)
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匹配。