背景
在用c写测试工具的时候也希望看到跟linux中常用工具那样的详细的参数说明。这时我们就需要用到c中常用的参数处理函数get_opt(),get_long().这两个函数在头文件#include
1. 短参数处理函数get_opt()
使用场景:
getopt是用来解析命令行选项参数的,但是只能解析短选项: -d 100,不能解析长选项:--prefix函数原型
int getopt(int argc, char * const argv[], const char *optstring);
-- optstring: 选项字符串,告知 getopt()可以处理哪个选项以及哪个选项需要参数
- 重点参数讲解 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 —— 指向当前选项参数(如果有)的指针,本身是指针,如果value是一个字符,那么可以取optarg[0]。
optind —— 再次调用 getopt() 时的下一个 argv指针的索引。
optopt —— 最后一个未知选项。
opterr —— 如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。
返回值
如果选项成功找到,返回选项字母;如果所有命令行选项都解析完毕,返回 -1;如果遇到选项字符不在 optstring 中,返回字符 '?';如果遇到丢失参数,那么返回值依赖于 optstring 中第一个字符,如果第一个字符是 ':' 则返回':',否则返回'?'并提示出错误信息例程:
#include
#include
#include
int main(intargc, char *argv[])
{
int opt;
char *string = "a::b: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] = %s\n",argv[optind]);
}
}
编译后可以用下面任何一种格式调用:
./opt -a100 -b 200 -c 300 -d
./opt -a100 -b200 -c300 -d
./opt -a -b 200 -c 300 -d
2. 长参数处理函数get_opt()
使用场景:
getopt_long 函数包含了 getopt 函数的功能,并且还可以指定"长参数”(--ip 127.0.0.1 , --help之类的)函数原型
int getopt_long(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex);
可以看到比get_opt()多了两个参数 longopts, logindex.
- 重点参数讲解
- longopts 指明了长参数的名称和属性,可以看到它是一个结构体指针,我们通常传一个结构体数组进去,每个元素代表一个参数,每个参数都是由下面的结构组成。
struct option {
const char *name; /* 参数名称 */
int has_arg; /* 指明是否带有参数 */
int *flag; /* flag=NULL时,返回value;不为空时,*flag=val,返回0 */
int val; /* 用于指定函数找到选项的返回值(长选项的缩写)或flag非空时指定*flag的值 */
};
- longindex 如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值
返回值
对于短选项,返回值同getopt函数;对于长选项,如果flag是NULL,返回val,否则返回0;对于错误情况返回值同getopt函数例程
int main(intargc, 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);
}
}
编译执行结果:
./long --reqarg 100 --optarg=200 --noarg
opt = r optarg =100 optind = 3 argv[optind] = --optarg=200 option_index = 0
opt = o optarg =200 optind = 4 argv[optind] = --noarg option_index = 1
opt = n optarg =(null) optind = 5 argv[optind] =(null) option_index = 2
- 例程2
#include
#include
void usage(void)
{
fprintf(stdout, "Usage: %s",
"consistency_check <-t type> <--ip addr> <-f file>\n\n\
-t type: specify s/c of the routine, the server start write first and \n\
and the client will notify server stop write, then write the \n\
same file and do read and check.\n\n\
-f file: the file name we will do IO.\n\n\
--ip addr: the ip of server.\n\n");
}
static struct option long_options[] = {
{"ip", required_argument, NULL, 'i'},
};
int main ()
{
string name;
char *ip_addr;
char type;
int opt;
while((opt =getopt_long(argc,argv,"t:f:",long_options, NULL))!= -1)
{
switch(opt) {
case 't':
type = optarg[0];
break;
case 'f':
name = optarg;
break;
case 'i’: // ip’s short char
ip_addr = optarg;
break;
defaul:
usage();
}
}
cout << "+----------------------------------------------------------------------------+" << endl;
cout << "|Type: " << type << " IP: " << ip_addr << " file: " << name << endl;;
cout << "+----------------------------------------------------------------------------+" << endl;
}
参考
https://www.cnblogs.com/chenliyang/p/6633739.html