C++ 02.好用的命令行解析库cmdline和CLI11
1. 获取命令行参数
在 C++ 程序中,我们可以通过 main
函数的参数来接收命令行参数。主要有两种形式:
1.1. 传统方式
int main(int argc, char* argv[])
其中:
argc
: argument count,表示命令行参数的数量argv
: argument vector,是一个指针数组,包含所有的命令行参数字符串argv[0]
通常是程序名称argv[1]
开始才是实际的命令行参数
1.1.1. 示例代码
下面是一个简单的命令行参数处理示例:
#include <iostream>int main(int argc, char* argv[]) {std::cout << "参数数量: " << argc << std::endl;for(int i = 0; i < argc; i++) {std::cout << "参数 " << i << ": " << argv[i] << std::endl;}return 0;
}
1.1.2. 使用方法
编译并运行上述程序:
g++ main.cpp -o program
./program arg1 arg2 "argument 3"
输出将类似于:
参数数量: 4
参数 0: ./program
参数 1: arg1
参数 2: arg2
参数 3: argument 3
1.2. 现代处理方式
对于更复杂的命令行参数处理,建议使用一些现代的库:
- Boost.Program_options: 功能强大的命令行解析库
- cxxopts: 轻量级的头文件库
- CLI11: 现代化的命令行解析器
- cmdline: 一个简单的头命令行解析器,直接引入到程序中即可。头文件下载
这些现代库提供了更多功能:
- 自动生成帮助信息
- 类型安全的参数解析
- 必选参数验证
- 短选项和长选项支持
- 默认值设置
1.3. cmdline
仅能在linux
下运行,在windows
下运行会报错,报错信息如下:找不到文件: #include <cxxabi.h>
示例代码
#include "cmdline.h"#include <iostream>
using namespace std;int main(int argc, char *argv[])
{cmdline::parser parser;parser.add<string>("host", 'h', "host name", true, "");parser.add<int>("port", 'p', "port number", false, 80, cmdline::range(1, 65535));parser.add<string>("type", 't', "protocol type", false, "http", cmdline::oneof<string>("http", "https", "ssh", "ftp"));parser.add("gzip", '\0', "gzip when transfer");parser.parse_check(argc, argv);cout << parser.get<string>("type") << "://"<< parser.get<string>("host") << ":"<< parser.get<int>("port") << endl;if (parser.exist("gzip")) cout << "gzip" << endl;return 0;
}
linux
编译&运行
g++ main.cpp -o main
./main --host "a.com" -p 8080 -t https
输出将类似于:
https://a.com:8080
常见的用法
parser.add<std::string>("host", 'h', "host name", true, ""); //参数做为std::string 类型
parser.add<int>("port", 'p', "port number", false, 80, cmdline::range(1, 65535)); //参数做为int 类型
add()
函数的参数说明,以add<std::string>()
为例:
template <class T, class F>void add(const std::string &name, //长的参数名,运行时带 --char short_name=0, //短的参数名,运行时带 -const std::string &desc="", //参数描述bool need=true, //是否必须const T def=T(), //默认值F reader=F()){if (options.count(name)) throw cmdline_error("multiple definition: "+name);options[name]=new option_with_value_with_reader<T, F>(name, short_name, need, def, desc, reader);ordered.push_back(options[name]);}
注意:
char
型值在解析命令行时会报错,可以使用string类型值暂时存储解析的命令行的值,然后从string类型值中获取char型值
1.4. CLI11用法
vcpkg install cli11
简要示例代码
#include <CLI/CLI.hpp>
#include <iostream>int main(int argc, char** argv) {// 创建CLI对象CLI::App app{"A brief description of your program"};// 定义一个变量来存储命令行参数值int my_int{0};std::string my_string;// 添加选项app.add_option("-i,--int-option", my_int, "An integer option");app.add_option("-s,--string-option", my_string, "A string option");// 解析命令行CLI11_PARSE(app, argc, argv);// 使用获取到的值std::cout << "Integer option: " << my_int << "\n";std::cout << "String option: " << my_string << "\n";return 0;
}
编译&运行
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
cmake --build build
if ($?)
{.\build\Debug\main.exe -i 5 -s hello
}
输出如下:
Integer option: 5
String option: hello
1.5. 参考资料
- GitHub - tanakh/cmdline: A Command Line Parser