- 在 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“,别离示意程序反对的命令行短选项有 -a、-b、-c、-d,冒号含意如下:
1. 只有一个字符,不带冒号——只示意选项,如 -c。
2. 一个字符,后接一个冒号——示意选项前面带一个参数,如 -a 100。
3. 一个字符,后接两个冒号——示意选项前面带一个可选参数,即参数可有可无,如果带参数,则选项与参数之间不能有空格,如 -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 }