您的位置:首页 > 娱乐 > 明星 > 洛阳市网站建设_域名到期如何续费_做个小程序需要花多少钱_西安外包公司排行

洛阳市网站建设_域名到期如何续费_做个小程序需要花多少钱_西安外包公司排行

2025/1/8 15:04:52 来源:https://blog.csdn.net/baiyu33/article/details/144872343  浏览:    关键词:洛阳市网站建设_域名到期如何续费_做个小程序需要花多少钱_西安外包公司排行
洛阳市网站建设_域名到期如何续费_做个小程序需要花多少钱_西安外包公司排行

C++库 CLI11 介绍和使用

CLI11 是一个 single-header-only 库, 用于命令行解析。 用户只需要包含一个头文件即可使用:

#include <CLI11.hpp>

CLI11 的官方仓库是: https://github.com/CLIUtils/CLI11.git

官方 README.md 提供的最基本用法:

int main(int argc, char** argv)
{CLI::App app{"App description"};argv = app.ensure_utf8(argv);std::string filename = "default";app.add_option("-f,--file", filename, "A help string");CLI11_PARSE(app, argc, argv);return 0;
}

显示帮助

对于 CLI11 写的应用程序, 万能的查看命令行参数的方式, 是指定 --help. 例如前一节给出的代码,编译出的可执行文件 cli_test:

./cli_test --help

输入:

My App
Usage: ./cli_test [OPTIONS]Options:-h,--help                   Print this help message and exit-f,--file TEXT              A help string

可以看到, -f,--file TEXT 被打印出来, 很直观.

命名扫盲:flag 和 option

  • flag 指的是开关, 用 - 开头, 例如 -a.
  • option 指的是选项,有 name 和 value, 例如 -f filename.
  • positional option 指的是位置参数, 不以 - 开头,用户提供 value, 程序内部为它维护 name, 例如 ./program value1 value2.

稍微复杂的形式:

  • --long: long flag (长flag)
  • --long_flag=true: 带等号的长 flag, 目的是覆盖默认值
  • --file filename: option
  • --file=filename: option
  • -a -b: 多个 flag
  • -ffilename: option 的 name 和 value 之间可以省略空格

更复杂的:

  • -ab: flag 可以合并
  • -abf filename: flag 和 option 可以组合

如果调用了 allow_windows_style_options(), 还可以传入 windows 风格的 flag 或 option, 也就是 / 替代 -, 例如:

  • /a: 这是一个 flag
  • /f filename: 这是一个 option
  • /long: 长 flag
  • /file filename: option, 空格分隔 name 和 value
  • /file:filename: option, 冒号(:)分隔 name 和 value
  • /long_flag:false: 长 flag 使用 : 覆盖默认值

ensure_utf8(argv)

CLI11 从 v2.4.0 开始, 在 App 类提供 ensure_utf8() 成员函数.

argv = app.ensure_utf8(argv); 是在做什么?

int main(int argc, char** argv)
{CLI::App app{"App description"};argv = app.ensure_utf8(argv); // 关注这里std::string filename = "default";app.add_option("-f,--file", filename, "A help string");CLI11_PARSE(app, argc, argv);return 0;
}

在 Windows 上, 使用 unicode 作为参数时你的 main() 函数可能已经接收到损坏的 Unicode。 这种情况下解析 argv 会导致得到不正确的字符串。 推荐的解决方法, 是在所有参数被解析之前调用 app.ensure_utf8(argv): 如果 argv 已经是 UTF-8(比如 Linux 和 macOS 系统)则返回为了原本的 argv, 如果是 Windows 则会申请的内存, 并将原本的 argv 转换到新的 argv 中, 这个转换指的是 decode, 是基于 win32 API 实现的:

int main(int argc, char** argv)
{CLI::App app;printf("argv = %p\n", argv); // ...A62000argv = app.ensure_utf8(argv); // 申请新的内存printf("argv = %p\n", argv); // ...A88120CLI11_PARSE(app, argc, argv);return 0;
}

对应的源码如下:

  • 数据成员 normalized_argv_ 存放被正确解析后的参数
  • 数据成员 normalized_argv_view_ 则是 normalized_argv_ 的 view, 它的 .data() 是返还给用户的 “新的 argv"
namespace CLI {
class App {...
#ifdef _WIN32/// When normalizing argv to UTF-8 on Windows, this is the storage for normalized args.std::vector<std::string> normalized_argv_{};/// When normalizing argv to UTF-8 on Windows, this is the `char**` value returned to the user.std::vector<char *> normalized_argv_view_{};
#endif/// Convert the contents of argv to UTF-8. Only does something on Windows, does nothing elsewhere.CLI11_NODISCARD char **ensure_utf8(char **argv);
};CLI11_NODISCARD CLI11_INLINE char **App::ensure_utf8(char **argv) {
#ifdef _WIN32(void)argv;normalized_argv_ = detail::compute_win32_argv();if(!normalized_argv_view_.empty()) {normalized_argv_view_.clear();}normalized_argv_view_.reserve(normalized_argv_.size());for(auto &arg : normalized_argv_) {// using const_cast is well-defined, string is known to not be const.normalized_argv_view_.push_back(const_cast<char *>(arg.data()));}return normalized_argv_view_.data();
#elsereturn argv;
#endif
}

API: 添加 flag 和 option

CLI::App 类提供两个成员函数,分别用于添加 flag 和 option

  • add_option()
  • add_option()
int main(int argc, char** argv)
{CLI::App app{"App description"};argv = app.ensure_utf8(argv);std::string filename = "default";app.add_option("-f,--file", filename, "A help string"); // 关注这里app.add_option(option_name, help_string=""); // 关注这里CLI11_PARSE(app, argc, argv);return 0;
}

其他

本篇算是 CLI11 库的小白扫盲贴, 谈不上平均水平的用法, 主要还是个人简单记录。

CLI11 添加 option 和 flag 时, 有多种写法, 这里没提及。

CLI11 支持子命令, 这里没提及。

没有提及的内容, 可以参照官方 README.md ,也可以从 CLI11.hpp 源码研读。 没大段贴这两个来源的内容的原因, 是细节太多, 使用 CLI11 的目的并不是陷入细节而是掌握基本的框架感, 用到的时候再查也来得及。

2025.01.01 21:20:00

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com