-
在linux中,一切皆文件,所有的可执行程序都可以通过命令行启动,程序启动时通常都会带上各种参数以控制程序的行为。所以解析命令行参数通常是一个可执行程序的第一步,下面就来介绍下经常用到的命令行参数的解析函数——getopt_long。
-
我们先来了解一下命令行参数。命令行参数可以分为两类,一类是短选项,一类是长选项。在命令行中"-"表示短选项,"--"则表示长选项。例如,在linux中最常用的ls命令中“-a,-A,-b”都是短选项,而它们对应的长选项则是“--all,--almost-all, --escape”。它们还都可选择性的添加额外参数,比如“--block-size=SIZE”。
-
getopt_long支持处理长短选项的命令行解析,函数在<getopt.h>头文件中。其函数定义是:
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
-
接下来介绍一下其参数以及返回值。
- argc和argv和main函数的两个参数一致。
- optstring: 表示短选项字符串。
形式如“a:b::cd:“,分别表示程序支持的命令行短选项有-a、-b、-c、-d,冒号含义如下:- 只有一个字符,不带冒号——只表示选项, 如-c。
- 一个字符,后接一个冒号——表示选项后面带一个参数,如-a 100。
- 一个字符,后接两个冒号——表示选项后面带一个可选参数,即参数可有可无, 如果带参数,则选项与参数之间不能有空格,如-b123。
- longopts:表示长选项结构体。其结构以及解释如下:
struct option { const char *name;// 表示的是长选项名称 int has_arg;// 表示选项后面是否携带参数。有3个值。 // no_argument(或者是0),参数后面不跟参数值。 // required_argument(或者是1),参数输入格式为:--参数 值 或者 --参数=值。 // optional_argument(或者是2),参数输入格式只能为:--参数=值。 int *flag;//用来决定函数的返回值。如果flag是null,则函数会返回与该项option匹配的val值,如果flag不是null,则函数返回0,并将flag指针参数指向与该项option匹配的val值。 int val; //和flag联合决定返回值 }
-
longindex:longindex不是null的话则指向的变量将记录longopts的下标值。
-
返回值:
- 如果短选项找到,那么将返回短选项对应的字符。
- 如果长选项找到,且flag为null,返回val,flag不为null,返回0。
- 如果发生错误,如:未识别选项或者必须加参数的选项丢失参数,返回“?”,如果在optstring中设置了第一个字符为“:”,丢失参数返回“:”。
- 当缩写长选项引起歧义时或者不需要的选项强加了参数,都会返回“?”。
- 返回-1表示选项处理全部结束。
- 如果在输入的argv[]中包含了独立的“--”字符串,解析到这里返回-1,停止选项的解析。
-
还有一些需要了解的全局变量:
- optarg(指针):表示当前选项对应的参数值。
- optind:表示的是下一个将被处理到的参数在argv中的下标值。
- opterr:如果opterr = 0,遇到错误将不会输出错误信息到标准输出流。opterr在非0时,向屏幕输出错误。
- optopt:表示出错或者未识别的选项。
-
注意事项:
- longopts的最后一个元素必须是全0填充,否则会报段错误
- 短选项中每个选项都是唯一的。而长选项如果简写,也需要保持唯一性。
-
下面是一个简单的例子:
/* 程序运行参数结构体 */
struct InputArgs
{
std::string user_id;
std::string user_name;
std::string pwd;
void printArgs();
bool checkArgs()
{
if (user_id.empty())
{
return false;
}
if (user_name.empty())
{
return false;
}
if (pwd.empty())
{
return false;
}
return true;
}
};
InputArgs g_input_arg_info;
void InputArgs::printArgs(){
printf("ARGS: --= %s\n", userId.c_str());
printf(" --userName = %s\n", user_name.c_str());
printf(" --pwd = %s\n", pwd.c_str());
}
/* 参数解析 */
const char* short_options = "i:n:p:";
struct option long_options[] = {
{ "userId", required_argument, NULL, 'i' },
{ "userName", required_argument, NULL, 'n' },
{ "pwd", required_argument, NULL, 'p' },
{ 0, 0, 0, 0 },
};
void print_usage(){
printf("DESCRIPTION\n");
printf(" --userId, -i\n");
printf(" --userName, -n\n");
printf(" --pwd, -p\n");
}
void print_arg(int argc, char *argv[])
{
for (int i = 0; i < argc; i++)
{
printf("%s\n", argv[i]);
}
}
int parse_arg(int argc, char *argv[])
{
print_arg(argc, argv);
int c;
std::string opt;
while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) !=
-1)
{
switch (c)
{
case 'i':
opt = optarg;
g_input_arg_info.user_id = opt;
break;
case 'n':
opt = optarg;
g_input_arg_info.user_name = opt;
break;
case 'p':
opt = optarg;
g_input_arg_info.pwd = opt;
break;
default:
return -1;
}
}
if (false == g_input_arg_info.checkArgs())
{
return -2;
}
return 0;
}
int main(int argc, char *argv[])
{
if (0 != parse_arg(argc, argv))
{
print_usage();
printf("parse input args failed!\n");
return 1;
}
g_input_arg_info.printArgs();
// do things here
}
网友评论