argparse
- 项目地址argparse
开始使用
位置参数
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; }
控制台命令和输出
XHCompiler.exe 15 ----------------------------------------------------------------------------------------- 225
可选参数
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; } }
控制台命令和输出
XHCompiler.exe --verbose ----------------------------------------------------------------------------------------- Verbosity enabled
使用flag()函数
flag函数像上面的.default_value(false).implicit_value(true);一样,是它的简写
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()来表示即可
program.add_argument("-o", "--output") .required() .help("specify the output file.");
如果我们给该参数加了默认值,即可编程非必要参数,但是实际使用的时候该参数是以默认值形式存在的
program.add_argument("-o", "--output") .default_value(std::string("-")) .required() .help("specify the output file.");
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; }
控制台命令和输出
XHCompiler.exe -o "aaa" -b "bbb" ----------------------------------------------------------------------------------------- aaa bbb
is_used(“–arg”)
auto explicit_verbose = program.is_used("--verbose"); std::cout << explicit_verbose << std::endl;
使用is_used(“–arg”)来判断可选参数是否被使用, 可以在上面例子中加入如下代码,则输出的时候会输出你是否使用了verbose这个参数
重复和互斥的可选参数
- 重复的可选参数
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"}
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
- 互斥的可选参数
auto &group = program.add_mutually_exclusive_group(); group.add_argument("--first"); group.add_argument("--second");
负数参数
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; }
输出结果
XHCompiler.exe -2 -2.2 -3.3 -4.4 -5.5 ---------------------------------------------- -2.2 -2
将位置参数和可选参数组合起来
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; }
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
打印帮助
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; }
输出结果
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)来确定输入和类型后续复合参数来确定
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; }
输出结果
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
复合参数
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; }
输出结果
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如果我们需要自己的,可以使用下列函数禁用默认的参数
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()函数即可
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; }
输出
E:\XHCompiler\cmake-build-debug>XHCompiler.exe aa bb ccbb ddfb 4 files provided aa bb ccbb ddfb
注意:请记住将所有可选参数放在其余参数之前。如果可选参数放在其余参数之后,它也将被视为剩余参数:
父子解析器
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(),该命令用来检查是否使用了子命令
- 我们还可以用下列函数获取子解析器
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");
解析未知参数
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; }
自定义前缀字符
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; }
自定义分配字符
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; }
输出
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