前言
针对简单工程甚至是单cpp文件,C++可执行二进制的参数获取,getopt被用来解析命令行选项参数。该接口在unix的头文件<unistd.h>中定义。参数类型区分为短参数(只有一个中划线’-')、长参数(有2个中划线‘–’),接口函数不同。另外我们也可以采用第三方库来实现参数解析。下面逐一介绍。
getopt短参数解析
短参数是指二进制的参数以‘-’为开始的参数形式。例如:.\paras.exe -o /a/b/c -d 123 -v 2。注意参数和参数值之间没有‘=’符号,是空格。
接口原型: int getopt(int argc, char *const argv[], const char *optstring, int *ind);
说明:
+ int argc:从 main 函数传入的参数数量。
+ char *const argv[]:从 main 函数传入的参数数组。
+ const char *optstring:选项字符串,用于指定哪些选项是有效的。
+ int *ind:可选参数,用于记录解析的位置。
使用方法:
#include <stdio.h>
#include <unistd.h>namespace
{// short getopt example with three parameters, just like "hvo".not support "--" long options.// input: .\paras.exe -o /a/b/c -d 123 -v 2// output: // Output file set to /a/b/c// depth set to 123// Version set to 2int ExplainParametersWithoutGetOpt(int argc, char **argv){int ret = 0;int option;while ((option = getopt(argc, argv, "hv:o:d:")) != -1) {switch (option) {case 'h':printf("Help option selected.\n");break;case 'v':printf("Version set to %s\n", optarg);break;case 'o':printf("Output file set to %s\n", optarg);break;case 'd':printf("depth set to %s\n", optarg);break;case '?':printf("Unknown option '%c'.\n", optopt);ret = 1;break;default:printf("Unknown option.\n");ret = 1;break;}}return ret;}
}int main(int argc, char **argv)
{int ret = ExplainParametersWithoutGetOpt(argc, argv);return ret;
}
getopt_long长参数解析
getopt_long不但支持短参还支持长参解析。
长参数是指二进制的参数以‘–’(2个短横)为开始的参数形式。
**接口原型:**int getopt_long(int argc, char *const argv[], const char *shortopts,
const struct option *longopts, int *longindex);
接口参数:
- argc 和 argv:这两个参数与 main 函数中的参数一致,分别表示命令行参数的数量和参数数组。
- shortopts:这是一个字符串,表示短选项的格式。例如,“ab:c::” 表示 a 是无参数选项,b 是带必需参数的选项,c 是带可选参数的选项。
- longopts:这是一个指向 struct option 数组的指针,用于定义长选项的格式。每个 struct option 结构体包含以下字段: name:长选项的名称。
- has_arg:指示选项是否带参数,0 表示无参数,1 表示必需参数,2
表示可选参数。 - flag:如果为 NULL,则 getopt_long 返回 val;否则,返回 0,并将 val 存储到 flag
指向的变量中。 - val:将要返回的值或存储到 flag 指向的变量中的值。
- longindex:这是一个指向整数的指针,用于返回长选项在 longopts 数组中的索引。通常设置为 NULL。
返回值
如果遇到有效的短选项或长选项,getopt_long 返回该选项的字符(对于短选项)或 val(对于长选项)。如果所有选项都已处理完毕,返回 -1。
使用方法:
#include <cstdio>
#include <getopt.h>
#include <unistd.h>static struct option long_options[] = {{"help", no_argument, nullptr, 'h'},{"version", required_argument, nullptr, 'v'},{"output", required_argument, nullptr, 'o'},{0, 0, 0, 0}
};int main(int argc, char *argv[]) {int option_index = 0;int c;int ret = 0;// binary execute: .\longgetopt.exe --version 2 --output d:\temp or .\longgetopt.exe -v 2 -o d:\temp// output: // Verbosity set to 2// Output file set to d:\tempwhile ((c = getopt_long(argc, argv, "hv:o:", long_options, &option_index)) != -1) {switch (c) {case 'h':printf("Help option selected.\n");break;case 'v':printf("Verbosity set to %s\n", optarg);break;case 'o':printf("Output file set to %s\n", optarg);break;case '?':printf("Unknown option '%c'.\n", optopt);ret = 1;break;default:printf("Unknown option.\n");ret = 1;break;}}return ret;
}
第三方库getopt解析
github有一个2016年的工程getopt, 封装了getopt,直接头文件引用就可以了。遗憾的是8年了没有更新。但学习C++参数解析够用了。
克隆代码到demo目录,目录层级如下;
$ tree -l
.paras
|-- paras.cpp
`-- thirdparty`-- getopt|-- README.md|-- demo.cc|-- getopt.cpp`-- getopt.hpp
应用代码:
#include <iostream>
// #include <string>
#include "thirdparty/getopt/getopt.hpp"namespace
{void ExplainParametersWithGetOpt(){// - No initialization required: (argc, argv) pair automatically retrieved.// - First argument is default option value, then all option indentifiers follow.// binary execute: .\paras.exe -o=/a/b/c -d=123 -v=2// output: 0,/a/b/c,123,2bool help = getarg(false, "-h", "--help", "-?");int version = getarg(0, "-v", "--version", "--show-version");int depth = getarg(1, "-d", "--depth", "--max-depth");std::string file = getarg("", "-o", "--outputfile");std::cout << help << ',' << file << ',' << depth << ',' << version << std::endl;}
}int main()
{std::cout << "Explain parameters with getopt lib" << std::endl;ExplainParametersWithGetOpt();return 0;
}
使用分析:第三方库getopt参数是短参接‘=‘,再接参数值形式。‘=‘不能省。少了一些全局变量。
总结
对于指定二进制或单个cpp,最终二进制启动参数的解析可以使用多种方法,看你的使用习惯。一般长短参都支持,程序的友好性较高。第三方包功能单一,若有更高需要,可以自己扩充。
参考文献
[1] getopt与getopt_long, slmmlk2011_2
h,ttps://blog.csdn.net/slmmlk2011_2/article/details/7964218?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EPaidSort-1-7964218-blog-142920234.235%5Ev43%5Epc_blog_bottom_relevance_base2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EPaidSort-1-7964218-blog-142920234.235%5Ev43%5Epc_blog_bottom_relevance_base2&utm_relevant_index=2