一、简介
getopt.h
是C语言中的一个标准头文件,它为命令行选项解析提供了便利的接口。如果你想让自己的程序支持命令行选项,那么getopt.h
是非常实用的一个工具。
getopt.h
提供了一个函数getopt()
,该函数可以解析命令行中的选项和参数。在解析过程中,getopt()
会自动识别选项的名称、选项的参数、以及选项顺序的先后关系。同时,getopt()
还提供了一些额外的接口,可以设置选项解析的细节,比如是否支持长选项、选项的缺省值等等。
二、基本使用
在使用getopt.h
之前,我们需要在代码中include
这个头文件,并在main
函数的程序入口处添加下面这个语句,让getopt()
开始工作:
#include <getopt.h>
int main(int argc, char *argv[])
{
int opt = 0;
while ((opt = getopt(argc, argv, "a:b:c")) != -1) {
switch (opt) {
case 'a':
printf("Option a: %s\n", optarg);
break;
case 'b':
printf("Option b: %s\n", optarg);
break;
case 'c':
printf("Option c\n");
break;
case '?':
printf("Unknown option: %c\n", optopt);
break;
}
}
return 0;
}
上面的代码中,opt
代表解析得到的选项的名称。如果选项具有参数,则可以通过optarg
来获得选项的参数值。在这个例子中,选项"a"
和"b"
后面都跟有参数,而选项"c"
则没有参数。
getopt()
函数的第三个参数是一个字符串,表示支持的选项名称。在上面的代码中,"a:b:c"
表示程序支持三个选项:"a"
、"b"
和"c"
。其中,选项"a"
和"b"
后面跟有冒号,表示它们是带参数的选项。
通过运行这个程序并添加选项参数,可以得到下面的输出结果:
$ ./a.out -a hello -b world -c
Option a: hello
Option b: world
Option c
三、长选项
除了短选项,getopt.h
还支持长选项。长选项通常用更长、更可读的名称来表示选项,比如"--version"
和"--help"
等。
使用长选项需要进行一些额外的设置。首先,我们需要定义一个静态的option
数组,该数组描述了所有支持的长选项和对应的短选项。
#include <getopt.h>
static struct option long_options[] = {
{"version", no_argument, 0, 'v'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
int opt = 0;
while ((opt = getopt_long(argc, argv, "vi:o:h", long_options, NULL)) != -1) {
switch (opt) {
case 'v':
printf("Version 1.0\n");
break;
case 'h':
printf("Usage: %s [OPTION]...\n", argv[0]);
break;
case 'i':
printf("Input file: %s\n", optarg);
break;
case 'o':
printf("Output file: %s\n", optarg);
break;
case '?':
break;
}
}
return 0;
}
在上面的例子中,我们定义了一个静态的option
数组。该数组的每个元素都表示一个长选项和对应的短选项。数组的最后一个元素必须是全零的结构体,用来表示数组的结束。
通过运行这个程序并添加长选项,可以得到下面的输出结果:
$ ./a.out --version --input=sample.txt --output=result.txt
Version 1.0
Input file: sample.txt
Output file: result.txt
四、支持选项参数缺省值
有些选项可能需要有缺省值以应对一些常见场景。比如,在一个图片处理工具中,我们可能会让用户指定保存图片的质量等级。但是,如果用户没有指定该选项,则可以使用一个默认的质量等级。
我们可以通过在定义选项时添加一个“=
”后面的字符串来设置该选项的缺省值。如果用户没有指定该选项,则会使用该选项的缺省值。
#include <getopt.h>
static struct option long_options[] = {
{"quality=", required_argument, 0, 'q'},
{0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
int opt = 0;
const char *quality = "medium";
while ((opt = getopt_long(argc, argv, "q:", long_options, NULL)) != -1) {
switch (opt) {
case 'q':
quality = optarg;
break;
case '?':
break;
}
}
printf("Quality: %s\n", quality);
return 0;
}
在上面的例子中,我们为选项"quality"
添加了一个"="
后面的字符串"default"
,表示该选项的缺省值为"default"
。如果用户没有指定该选项,则quality
变量的值就是"default"
。
通过运行这个程序并添加选项参数,可以得到下面的输出结果:
$ ./a.out -q high
Quality: high
$ ./a.out
Quality: medium
五、支持多个参数
有些选项可能需要支持多个参数,比如指定多个文件夹或者多个文件名。在getopt.h
中,我们可以通过双冒号来表示一个选项带有多个参数。
#include <getopt.h>
int main(int argc, char *argv[])
{
int opt = 0;
while ((opt = getopt(argc, argv, "a::")) != -1) {
switch (opt) {
case 'a':
if (optarg != NULL) {
printf("Option a: %s\n", optarg);
} else {
printf("Option a without argument\n");
}
break;
case '?':
break;
}
}
return 0;
}
在上面的例子中,我们为选项"a"
添加双冒号,表示该选项可以有多个参数。在程序中,我们通过判断optarg
的值是否为NULL
,来判断选项"a"
是否带有参数。
通过运行这个程序并添加选项参数,可以得到下面的输出结果:
$ ./a.out -a hello -a world -a
Option a: hello
Option a: world
Option a without argument