文章目录
argparse
- 项目地址argparse
开始使用
位置参数
cpp
int positionalArguments(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");
program.add_argument("square")
.help("display the square of a given integer")
.scan<'i', int>();
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
return 1;
}
auto input = program.get<int>("square");
std::cout << (input * input) << std::endl;
return 0;
}
控制台命令和输出
shell
XHCompiler.exe 15
-----------------------------------------------------------------------------------------
225
可选参数
cpp
int optionalArguments(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");
program.add_argument("--verbose")
.help("increase output verbosity")
.default_value(false)
.implicit_value(true);
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
if (program["--verbose"] == true) {
std::cout << "Verbosity enabled" << std::endl;
}
}
控制台命令和输出
shell
XHCompiler.exe --verbose
-----------------------------------------------------------------------------------------
Verbosity enabled
使用flag()函数
flag函数像上面的.default_value(false).implicit_value(true);一样,是它的简写
cpp
int optionalArguments(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");
program.add_argument("--verbose")
.help("increase output verbosity")
.flag();
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
if (program["--verbose"] == true) {
std::cout << "Verbosity enabled" << std::endl;
}
}
这里不在重复结果
必选参数
在某些情况下,我们需要一些必选参数,我们只要在可选参数中增加required()来表示即可
cpp
program.add_argument("-o", "--output")
.required()
.help("specify the output file.");
如果我们给该参数加了默认值,即可编程非必要参数,但是实际使用的时候该参数是以默认值形式存在的
cpp
program.add_argument("-o", "--output")
.default_value(std::string("-"))
.required()
.help("specify the output file.");
cpp
int requiredArguments(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe", "0.0.0");
program.add_argument("--verbose")
.help("increase output verbosity")
.flag();
program.add_argument("-o", "--output")
.required()
.help("specify the output file.");
program.add_argument("-b", "--base")
.default_value(std::string("-"))
.required()
.help("specify the base.");
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto output = program.get<std::string>("--output");
std::cout << output << std::endl;
auto base = program.get<std::string>("--base");
std::cout << base << std::endl;
return 0;
}
控制台命令和输出
shell
XHCompiler.exe -o "aaa" -b "bbb"
-----------------------------------------------------------------------------------------
aaa
bbb
is_used("--arg")
cpp
auto explicit_verbose = program.is_used("--verbose");
std::cout << explicit_verbose << std::endl;
使用is_used("--arg")来判断可选参数是否被使用, 可以在上面例子中加入如下代码,则输出的时候会输出你是否使用了verbose这个参数
重复和互斥的可选参数
- 重复的可选参数
cpp
program.add_argument("--color")
.default_value<std::vector<std::string>>({ "orange" })
.append()
.help("specify the cat's fur color");
try {
program.parse_args(argc, argv); // Example: ./main --color red --color green --color blue
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto colors = program.get<std::vector<std::string>>("--color"); // {"red", "green", "blue"}
cpp
int verbosity = 0;
program.add_argument("-V", "--verbose")
.action([&](const auto &) { ++verbosity; })
.append()
.default_value(false)
.implicit_value(true)
.nargs(0);
program.parse_args(argc, argv); // Example: ./main -VVVV
std::cout << "verbose level: " << verbosity << std::endl; // verbose level: 4
- 互斥的可选参数
cpp
auto &group = program.add_mutually_exclusive_group();
group.add_argument("--first");
group.add_argument("--second");
负数参数
cpp
int negativeNumbers(int argc, char *argv[])
{
argparse::ArgumentParser program;
program.add_argument("integer")
.help("Input number")
.scan<'i', int>();
program.add_argument("floats")
.help("Vector of floats")
.nargs(4)
.scan<'g', float>();
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto colors = program.get<std::vector<float>>("floats");
auto inta = program.get<int>("integer");
std::cout << colors[0] << std::endl;
std::cout <<inta << std::endl;
return 0;
}
输出结果
shell
XHCompiler.exe -2 -2.2 -3.3 -4.4 -5.5
----------------------------------------------
-2.2
-2
将位置参数和可选参数组合起来
cpp
int compareArgs(int argc, char *argv[])
{
argparse::ArgumentParser program;
program.add_argument("square")
.help("display the square of a given number")
.scan<'i', int>();
program.add_argument("--verbose")
.default_value(false)
.implicit_value(true);
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
int input = program.get<int>("square");
if (program["--verbose"] == true) {
std::cout << "The square of " << input << " is " << (input * input) << std::endl;
}
else {
std::cout << (input * input) << std::endl;
}
return 0;
}
shell
E:\XHCompiler\cmake-build-debug>XHCompiler.exe 15
225
E:\XHCompiler\cmake-build-debug>XHCompiler.exe 15 --verbose
The square of 15 is 225
E:\XHCompiler\cmake-build-debug>XHCompiler.exe --verbose 15
The square of 15 is 225
打印帮助
cpp
int main(int argc, char *argv[]) {
int ret = 0;
// ret = positionalArguments(argc, argv);
// ret = optionalArguments(argc, argv);
// ret = requiredArguments(argc, argv);
// ret = negativeNumbers(argc, argv);
// ret = compareArgs(argc, argv);
argparse::ArgumentParser program("main");
program.add_argument("thing").help("Thing to use.").metavar("THING");
program.add_argument("--member").help("The alias for the member to pass to.").metavar("ALIAS");
program.add_argument("--verbose").default_value(false).implicit_value(true);
program.add_description("Forward a thing to the next member.");
program.add_epilog("Possible things include betingalw, chiz, and res.");
program.parse_args(argc, argv);
std::cout << program << std::endl;
return ret;
}
输出结果
sehll
E:\XHCompiler\cmake-build-debug>XHCompiler.exe --help
Usage: main [--help] [--version] [--member ALIAS] [--verbose] THING
Forward a thing to the next member.
Positional arguments:
THING Thing to use.
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
--member ALIAS The alias for the member to pass to.
--verbose
Possible things include betingalw, chiz, and res.
参数列表
我们可以说使用nargs(int) 来确定参数个数。也可是使用scan('g',float)来确定输入和类型后续复合参数来确定
cpp
int paramsList(int argc, char *argv[])
{
argparse::ArgumentParser program;
program.add_argument("-i", "--input_files")
.help("The list of input files")
.nargs(2);
try {
program.parse_args(argc, argv); // Example: ./main --input_files config.yml System.xml
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto files = program.get<std::vector<std::string>>("--input_files"); // {"config.yml", "System.xml"}
for(auto file : files)
{
std::cout << file << " ";
}
std::cout << std::endl;
return 0;
}
输出结果
shell
E:\XHCompiler\cmake-build-debug>XHCompiler.exe --input_files "aa aa" "bb"
aa aa bb
E:\XHCompiler\cmake-build-debug>XHCompiler.exe --input_files aa bb
aa bb
复合参数
cpp
int compoundParamsList(int argc, char *argv[])
{
argparse::ArgumentParser program;
program.add_argument("-a")
.default_value(false)
.implicit_value(true);
program.add_argument("-b")
.default_value(false)
.implicit_value(true);
program.add_argument("-c")
.nargs(2)
.default_value(std::vector<float>{0.0f, 0.0f})
.scan<'g', float>();
try {
program.parse_args(argc, argv); // Example: ./main -abc 1.95 2.47
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
auto a = program.get<bool>("-a"); // true
auto b = program.get<bool>("-b"); // true
auto c = program.get<std::vector<float>>("-c"); // {1.95, 2.47}
std::cout << a << std::endl;
std::cout << b << std::endl;
for(auto file : c)
{
std::cout << file << " ";
}
std::cout << std::endl;
return 0;
}
输出结果
shell
E:\XHCompiler\cmake-build-debug>XHCompiler.exe -abc 1.0 2.0
1
1
1 2
数值类型转换
我们在使用scan()函数的时候使用了'g'这个,这些转换有一些预定类型,如下:
Shape | interpretation |
---|---|
'a' or 'A' | 十六进制浮点数 |
'e' or 'E' | 科学记数法(浮点数) |
'f' or 'F' | 固定表示法(浮点) |
'g' or 'G' | 一般形式(固定形式或科学形式) |
'd' | 十进制 |
'i' | std::from_chars 带基数的语法 == 10 |
'o' | 八进制(无符号) |
'u' | 十进制(无符号) |
'x' or 'X' | 十六进制(无符号) |
默认的-h和-v
对于默认的-h和-v如果我们需要自己的,可以使用下列函数禁用默认的参数
cpp
int defaultCommand(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe", "1.0"
, argparse::default_arguments::none);
program.add_argument("-h", "--help")
.action([=](const std::string& s) {
std::cout << program.help().str();
})
.default_value(false)
.help("shows help message")
.implicit_value(true)
.nargs(0);
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
return 0;
}
收集剩余参数
只需要在参数使用remaining()函数即可
cpp
int remainingParamsList(int argc, char *argv[])
{
argparse::ArgumentParser program;
program.add_argument("-o")
.default_value(std::string("a.out"));
program.add_argument("files")
.remaining();
program.add_argument("-m")
.default_value(std::string("a.out"));
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
try {
auto files = program.get<std::vector<std::string>>("files");
std::cout << files.size() << " files provided" << std::endl;
for (auto& file : files)
std::cout << file << std::endl;
} catch (std::logic_error& e) {
std::cout << "No files provided" << std::endl;
}
return 0;
}
输出
shell
E:\XHCompiler\cmake-build-debug>XHCompiler.exe aa bb ccbb ddfb
4 files provided
aa
bb
ccbb
ddfb
注意:请记住将所有可选参数放在其余参数之前。如果可选参数放在其余参数之后,它也将被视为剩余参数:
父子解析器
cpp
int parentAndChildParamsList(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe");
// git add subparser
argparse::ArgumentParser add_command("add");
add_command.add_description("Add file contents to the index");
add_command.add_argument("files")
.help("Files to add content from. Fileglobs (e.g. *.c) can be given to add all matching files.")
.remaining();
// git commit subparser
argparse::ArgumentParser commit_command("commit");
commit_command.add_description("Record changes to the repository");
commit_command.add_argument("-a", "--all")
.help("Tell the command to automatically stage files that have been modified and deleted.")
.default_value(false)
.implicit_value(true);
commit_command.add_argument("-m", "--message")
.help("Use the given <msg> as the commit message.");
// git cat-file subparser
argparse::ArgumentParser catfile_command("cat-file");
catfile_command.add_description("Provide content or type and size information for repository objects");
catfile_command.add_argument("-t")
.help("Instead of the content, show the object type identified by <object>.");
catfile_command.add_argument("-p")
.help("Pretty-print the contents of <object> based on its type.");
// git submodule subparser
argparse::ArgumentParser submodule_command("submodule");
submodule_command.add_description("Initialize, update or inspect submodules");
argparse::ArgumentParser submodule_update_command("update");
submodule_update_command.add_description("Update the registered submodules to match what the superproject expects");
submodule_update_command.add_argument("--init")
.default_value(false)
.implicit_value(true);
submodule_update_command.add_argument("--recursive")
.default_value(false)
.implicit_value(true);
submodule_command.add_subparser(submodule_update_command);
program.add_subparser(add_command);
program.add_subparser(commit_command);
program.add_subparser(catfile_command);
program.add_subparser(submodule_command);
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
return 1;
}
return 0;
}
执行输出自己尝试。
- 解析器具有is_subcommand_used(),该命令用来检查是否使用了子命令
- 我们还可以用下列函数获取子解析器
cpp
argparse::ArgumentParser program("test");
program.add_argument("--dir");
program.at("--dir").default_value(std::string("/home/user"));
program.add_subparser(argparse::ArgumentParser{"walk"});
program.at<argparse::ArgumentParser>("walk").add_argument("depth");
解析未知参数
cpp
int unknownParamsList(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe");
program.add_argument("--foo").implicit_value(true).default_value(false);
program.add_argument("bar");
auto unknown_args =
program.parse_known_args({"test", "--foo", "--badger", "BAR", "spam"});
assert(program.get<bool>("--foo") == true);
assert(program.get<std::string>("bar") == std::string{"BAR"});
assert((unknown_args == std::vector<std::string>{"--badger", "spam"}));
return 0;
}
自定义前缀字符
cpp
int selfPrefixChar(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe");
program.set_prefix_chars("-+/");
program.add_argument("+f");
program.add_argument("--bar");
program.add_argument("/foo");
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
return 1;
}
if (program.is_used("+f")) {
std::cout << "+f : " << program.get("+f") << "\n";
}
if (program.is_used("--bar")) {
std::cout << "--bar : " << program.get("--bar") << "\n";
}
if (program.is_used("/foo")) {
std::cout << "/foo : " << program.get("/foo") << "\n";
}
return 0;
}
自定义分配字符
cpp
int selfAssignmentChar(int argc, char *argv[])
{
argparse::ArgumentParser program("XHCompiler.exe");
program.set_prefix_chars("-+/");
program.set_assign_chars("=:");
program.add_argument("--foo");
program.add_argument("/B");
try {
program.parse_args(argc, argv);
}
catch (const std::exception& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
return 1;
}
if (program.is_used("--foo")) {
std::cout << "--foo : " << program.get("--foo") << "\n";
}
if (program.is_used("/B")) {
std::cout << "/B : " << program.get("/B") << "\n";
}
return 0;
}
输出
shell
E:\XHCompiler\cmake-build-debug>XHCompiler.exe /B a
/B : a
E:\XHCompiler\cmake-build-debug>XHCompiler.exe /B=a
/B : a
E:\XHCompiler\cmake-build-debug>XHCompiler.exe /B:a
/B : a