概述
命令行工具下的参数选项有两种,长选项和短选项。
getopt可以解析短选项,短选项以-开头,后面跟单个字母;
getopt_long可以解析长选项和短选项:长选项以--开头,后面可跟多个字母,短选项以-开头
getopt_long_only可以解析长选项和短选项:长选项以-或者--开头,后面可跟多个字母,短选项以-开头
执行时,可以是./test --opt xxx或者./test --opt=xxx
getopt
函数介绍
头文件:
getopt.h
unistd.h
函数原型:
int getopt(int argc, char * const argv[], const char *optstring);
功能:
解析命令行短选项参数
参数:
argc:参数的个数(main)
argv:参数数组(main)
optstring:短选项字符集合,如 -i -n中的i,n
返回值:
若getopt找到短选项字符,则返回该选项字符;
若出现不能接受的选项字符或丢失选项参数,则返回?,同时optopt将被设置成相应选项字符;
如果所有命令行选项都解析完毕,返回 -1
若选项后面有参数,则选项字符后加:, 对应的参数值保存在外部变量optarg中
如optstring 为"i:a",则表示程序支持两个短选项 -i arg和-a, -i后面须有参数值
当执行./a.out -i filename -a时,optarg指针就指向filename
optstring中的指定的内容的意义(例如getopt(argc, argv, "ab:c:de::");)
1.单个字符,表示选项(如下例中的abcde各为一个选项)。
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg(如下例中的b:c:)。
3 单个字符后跟两个冒号,表示该选项后可以跟一个参数,也可以不跟。如果跟一个参数,参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(如上例中的e::,如果没有跟参数,则optarg = NULL)
几个外部变量(全局变量),可以直接用。
optarg:若短选项后有参数,则optarg指向该参数。char *类型
optind:扫描选项时,标识下一个选项的索引;扫描结束后,标识第一个非选项参数索引。int类型
opterr:出现不可识别的选项时,getopt将打印错误信息。将opterr设为0,可不打印错误信息。int类型
optopt:最后一个未知选项。int类型
解析过程
getopt首先扫描argv[1]到argv[argc-1],并将选项及参数依次放到argv数组的最左边,非选项参数依次放到argv的最后边
如执行程序为:
0 1 2 3 4 5 6 7 8 9
$ ./mygetopt file1 -i infile -a -o outfile -v -h file2
扫描过程中,optind是下一个选项的索引, 非选项参数将跳过,同时optind增1。
optind初始值为1。当扫描argv[1]时,为非选项参数,跳过,optind=2;
扫描到-i选项时,后面有参数,下一个将要扫描的选项是-a,则optind更改为4;
扫描到-a选项时,下一个选项是-o,optind=5;
扫描到-o选项时,后面有参数,下一个选项是-v,optind=7;
扫描到-v选项时,下一个选项是-h,optind=8;
扫描到-h选项时,optind=9
扫描结束后,getopt会将argv数组修改成下面的形式
0 1 2 3 4 5 6 7 8 9
$./mygetopt -i infile -a -o outfile -v -h file1 file2
同时,optind会指向非选项的第一个参数,如上面,optind将指向file1
例程
1.while ((iError = getopt(argc, argv, "s:f:h:d:")) != -1)
{
switch(iError)
{ case 's':
{
dwFontSize = strtoul(optarg, NULL, 0);
break;
}
case 'f':
{
strncpy(acFreetypeFile, optarg, 128);
acFreetypeFile[127] = '\0';
break; ....
2.
void usage(const char *p);
int main(int argc, char *argv[])
{
int ch=0;
opterr=0; // prevent error information to print for unrecognized options
while( (ch=getopt(argc, argv, "i:ao:vh") ) != -1 )
{
switch(ch)
{
case 'i':
printf("option i: %s\n", optarg);
printf("optind=%d\n\n", optind);
break;
case 'a':
printf("option a :%c\n", ch);
printf("optind=%d\n\n", optind);
break;
case 'o':
printf("option o: %s\n", optarg);
printf("optind=%d\n\n", optind);
break;
case 'v':
printf("option v: %c\n", ch);
printf("optind=%d\n\n", optind);
break;
case 'h':
usage(argv[0]);
printf("optind=%d\n\n", optind);
break;
default:
printf("unrecognized option: %c\n", optopt);
usage(argv[0]);
}
}
if ( optind < argc )
{
printf("\nnon-option arguments below:\n");
while( optind < argc )
{
printf("%s\n", argv[optind++]);
}
}
return 0;
}
void usage(const char *p)
{
printf("Usage: %s [-i infile] [-a] [-o outfile] [-v] [-h] [file]\n", p);
}
执行结果:
$ ./mygetopt file1 -i infile -a -o outfile -v -h file2
option i: infile
optind=4
option a :a
optind=5
option o: outfile
optind=7
option v: v
optind=8
Usage: ./mygetopt [-i infile] [-a] [-o outfile] [-v] [-h] [file]
optind=9
non-option arguments below:
file1
file2
getopt_long
函数介绍
功能: 解析命令行长选项参数
头文件:
getopt.h
unistd.h
函数原型:
int getopt_long(int argc, char * const argv[],
const char *optstring,
const struct option *longopts, int *longindex);
参数:
argc:参数的个数(main)
argv:参数数组(main)
optstring:短选项字符集合,如 -i -n中的i,n
longopts:结构的实例
struct option {
const char *name; //name表示的是长参数名
int has_arg; //has_arg有3个值:
// no_argument(或者是0),表示该参数后面不跟参数值
// required_argument(或者是1),表示该参数后面一定要跟参数值:--name Tom
// optional_argument(或者是2),表示该参数后参数可选:--name和--name Tom皆可。
int *flag; //用来决定,getopt_long()的返回值到底是什么。
//null(通常情况),函数会返回与该项option匹配的val值;
//不是NULL,val的值被赋到flag指向的整型数中,并且返回值设置为0。
int val; //用于指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值。
}
longindex:当前长参数在longopts中的索引值
返回值:
取决于longopts的成员:flag
例程
程序
#include
#include
#include
#include
int main(int argc, char **argv)
{
int opt;
int digit_optind = 0;
int option_index = 0;
char *optstring = "a:b:c:d";
static struct option long_options[] = {
{"reqarg", required_argument, NULL, 'r'},
{"nonarg", no_argument, NULL, 'n'},
{"optarg", optional_argument, NULL, 'o'},
{0, 0, 0, 0}
};
while ( (opt = getopt_long(argc, argv, optstring, long_options, &option_index)) != -1)
{
printf("opt = %c\n", opt);
printf("optarg = %s\n", optarg);
printf("optind = %d\n", optind);
printf("argv[optind - 1] = %s\n", argv[optind - 1]);
printf("option_index = %d\n", option_index);
}
return 0;
}
运行结果:
1. ./test_getopt_long -a 100 --reqarg 100 --nonarg
opt = a
optarg = 100
optind = 3
argv[optind - 1] = 100
option_index = 0
opt = r
optarg = 100
optind = 5
argv[optind - 1] = 100
option_index = 0
./test_getopt_long: unrecognized option '--nonarg'
opt = ?
optarg = (null)
optind = 6
argv[optind - 1] = --nonarg
option_index = 0
2. 所给的参数存在问题时,opt(即函数返回值是’?’),如:
./test_getopt_long -a
./test_getopt_long: option requires an argument -- 'a'
opt = ?
optarg = (null)
optind = 2
argv[optind - 1] = -a
option_index = 0
./test_getopt_long --reqarg
./test_getopt_long: option '--reqarg' requires an argument
opt = ?
optarg = (null)
optind = 2
argv[optind - 1] = --reqarg
getopt_long_only
与getopt_long对比
相同点
函数参数、参数含义,返回值都一样。
不同点
getopt_long_only把’-’后的选项依然当做长选项,如果一个以’-’开头的选项没有在option数组中找到匹配的选项,但是在optstring中有匹配的短选项,则当成短选项处理。
例:以下两种是一样的
./test_getopt_long_only -a 100 --reqarg 100 --nonarg
./test_getopt_long_only -a 100 -reqarg 100 -nonarg
处理非法参数
在使用getopt或者getopt_long函数解析参数的时候,需要对非法参数进行处理,处理方法如下。
在while ((ret = getopt_long (...))!= -1 ) {}之后,写以下程序
//提示用户输入的命令中含有无效字符,并列举出所有的无效字符
if ( optind < argc )
{
fprintf ( stderr, "Invalid configuration information:");
while ( optind < argc )
{
fprintf ( stderr, "%s ", argv[optind++]);
}
fprintf ( stderr, "\n");
printf("please input\"./sd_test -h\" or \"./sd_test --help\" get some help information!\n ");
return -1;
}