003-掌控命令行-CLI11-C++开源库108杰

首选的现代C++风格命令行参数解析器!
(本课程包含两段教学视频。)
CLI11-命令行解析库

  1. 以文件对象监控程序为实例,五分钟实现从命令行读入多个监控目标路径;
  2. 区分两大时机,学习 CLI11 构建与解析参数两大场景下的异常处理;
  3. 区分三种选项:匿名vs.具名、选项vs.标志、必选vs.可选,全面掌握CLI11

0. 楔

本课含两段教学视频

在代码中,将关键业务数据写死,通常不是一个好做法。譬如前面课堂中基于 libwatch 所写的文件对象变动信息监控工具,用户拿到手后,就只能监控一个既定的位置:d:/tmp ,在真实工作中,这是妥妥要主动离职的节奏……

有两种常用方法用于解决类似此类的,要在运行前才能获得关键信息的问题:

  1. 命令行参数:运行程序时,通过在程序后面加参数(称为 command-line arguments)获取信息;
  2. 配置文件:程序运行后,从指定文件中读取相关配置。

这节课我们讲第1种方法,下一节课讲第2种方法,以及(真正的重点)两种方法的配合。

命令行参数和配置文件本就是为了同一个业务目标(程序运行时取得外部关键可变信息),因此,如果库本身未能支持与另一方的配合,二者的配合逻辑就只能由程序员完成。CLII很好的支持和配置文件的结合,是我们将它作为首选学习(也推荐在工作中使用)的命令行参数解析库的重要原因(甚至没有之一)。

1. 快速感受

CLI11 是一个纯头文件的库,使用起来非常方便。

纯头文件库:只有头文件,使用时只需 include 必要的头文件即可,无需事先编译库本身。缺点是:通常此类库的头文件都相对巨大,会造成目标项目每次编译时,为其耗费较长的时间。在后面的练习中,你将痛苦地感受到一点(不要问视频中为什么编译那么快,因为很多等待过程被一剪没了……)。

在 msys2 (以UCRT64环境为例)中安装 CLI11 :

pacman -S mingw-w64-ucrt-x86_64-cli11

我们以实现文件监控工具监控目标可通过命令行参数设定为案例,快速感受 CLI11 的功能与基本使用方式。

  • 视频1

007-CLI11命令行解析-1快速感受-C++108杰

  • 关键代码

加入CLI以实现从命令行读取待监控路径(支持多个)功能后,HellFSWatch 项目的主函数为:

int main(int argc, char** argv) 
{// 一、定义一个CLI::App 的变量CLI::App app("HelloFSWatch");// 二、定义需要从命令行参数读入的变量std::vector<std::string> paths;// 三、添加参数项app.add_option("paths", paths, "paths to watch"); // 四、开始解析命令行app.parse(argc, argv);if (paths.empty()){std::cerr << "paths is empty!" << std::endl;return -1;}else{for (auto const& path : paths){std::cout << path << std::endl;}}auto *monitor = fsw::monitor_factory::create_monitor(system_default_monitor_type,paths,on_file_changed);// 启动监控monitor->start();  // 进入死循环
}

这段代码能工作,但相当脆弱,用户一不小心给错参数就可能造成程序发生异常,并相当不体面地直接退出……,详细改进方法,请同学们学完下一小节 “2. 用法详解” 后,结合作业完成(完成后可提交给老师)。

2. 用法详解

在“用法详解”的视频中,我们将学习到:

  1. 异常处理:构建阶段的异常处理和解析阶段的异常处理;
  2. 匿名参数与具名参数:其中的匿名参数也称为位置参数,因为此类区分此类参数在命令行中没有名字指示,因此,最终识别它们的唯一方法,是通过它们出现在命令行中的位置加以区分;
  3. 长名字、短名字(注意,超过一个字母,就叫长名字);
  4. option 和 flag 之分;
  5. 必选和可选之分;
  6. 命令行参数与配置文件的基本配合思路。
  • 视频2

008-CLI11命令行解析-2用法详解-C++108杰

  • 代码 - CMakeLists.txt
cmake_minimum_required(VERSION 3.10.0)
project(HelloCLI11 VERSION 0.1.0 LANGUAGES C CXX)set(CMAKE_EXE_LINKER_FLAGS "-static")add_executable(HelloCLI11 main.cpp)

其中添加 “-staic” 链接选项并非必须,仅为方便在控制台(包括VSCODE集成的终端中)直接运行例程(否则,需要复制一大堆相关的动态库到程序目录下才能运行)。

  • 代码 - main.cpp
#include <cstdlib>#include <iostream>
#include <vector>
#include <string>
#include <iomanip>#include <CLI/CLI.hpp>int main(int argc, char** argv)
{std::system("chcp 65001 > nul");CLI::App app ("一个CLI11命令行参数解析的例子");std::vector<std::string> paths;int maxCount = 0;bool createdOnly = false;try{app.add_option("paths", paths, "待监控的文件夹路径(可含多个)")->required();app.add_option("--max-count,-m", maxCount, "最大消息数");app.add_flag("-c,--created-only", createdOnly, "只关注新建信息");}catch(CLI::ConstructionError const& e){return app.exit(e);}CLI11_PARSE(app, argc, argv);std::cout << "待监控的目录:\n";for (auto const& path: paths){std::cout << path << "\n";}std::cout << "max-count : " << maxCount << "\n";std::cout << "created-only: " << std::boolalpha << createdOnly << "\n";std::system("pause");
}

其中的 CLI11_PARSE 是 CLI11 提供的宏,CLI11_PARSE (app, argc, argv) 大体将对应到以下代码:

    try{app.parse(argc, argv); }catch(CLI::ParseError const& e){return app.exit(e);}

3. 知识小结

  1. 构建时期产生的异常,基类为 CLI::ConstructionError ,此类错误通常是我们在使用add_option()或add_flag()时,所配置的参数项逻辑不合理,比如:同名的参数,或者误以为可以添加名字超过一个字母的“短名字”;
  2. app.parse() 过程产生的异常,称为 “CLI::ParseError”,是一种典型的运行期异常:因为它通常由程序用户的错误造成(给出错误的命令行参数,比如,未给必选项参数),躲都没处躲,因此一定要加 try-catch 处理,为此,CLI11 干脆给了一个宏来简化处理;
  3. 再次强调:超过一个字母,就算长名字,必须在前面加两个杠 --;一个字母才是短名字,加一个杠 -;一个杠都不用加的,课程称之为 “匿名参数”,不过 CLI11 自身称之为 positionals 参数,即基于位置识别的参数;
  4. 绑定变量类型主要支持:整数、字符串、布尔值等,以及对应的动态数组(std::vector);
  5. 当绑定的变量是 std::vector 类型,CLI11 会自动帮我们尝试读入连续的参数,存放到目标 vector 对象中;
  6. 类型是布尔值时,也可以通过是否提供该参数(名字)来推理参数值:有提供为true,否则为false,使用此方法时 ,需要通过 app.add_flag() 来添加参数;
  7. 同一参数的短名称和长名称,可在指定名称时,通过逗号分隔,二者次序无关,如例程代码中的 “–max-count,-m” 以及 “-c,–created-only”;
  8. 通过级联调用 ->required() ,可将对应参数设置为必选项;
  9. CLI11 已经自动添加了 --help,-h 参数,因此我们不能再添加它们。

如何避免“看着都懂了,一要写代码就又不会”的学习困境?想想,网络学习,总是差了点什么?当然是 “作业” 呀!请到 d2school.com 网站进入本文对应的课堂,做练习并交给老师批改(可能需要花10毛)。
CLI::App d2school

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/37930.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV图像拼接(2)基于羽化(feathering)技术的图像融合算法拼接类cv::detail::FeatherBlender

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::detail::FeatherBlender 是 OpenCV 中用于图像拼接的一个类&#xff0c;它属于 stitching 模块的一部分。这个类实现了基于羽化&#xff08;…

如何用Function Calling解锁OpenAI的「真实世界」交互能力?(附Node.js 实战)

一、Function Calling&#xff1a;大模型的「手脚延伸器」 1.1 核心定义 Function Calling是OpenAI在2023年6月13日推出的革命性功能&#xff08;对应模型版本gpt-3.5-turbo-0613和gpt-4-0613&#xff09;&#xff0c;允许开发者通过自然语言指令触发预定义函数&#xff0c;实…

鸿蒙ArkTS+ArkUI实现五子棋游戏

鸿蒙ArkTSArkUI实现五子棋游戏 前言 近期&#xff0c;鸿蒙系统热度飙升&#xff0c;引发了周围众多朋友的热烈探讨。出于这份浓厚的好奇心&#xff0c;我初步浏览了其官方文档&#xff0c;发现信息量庞大&#xff0c;全面消化需耗时良久并考验人的毅力。自踏入编程领域以来&am…

单元测试mock

一、背景 现在有A类,B类,C类&#xff0c;A类依赖B类,依赖C类&#xff0c;如果想要测试A类中的某个方法的业务逻辑。A类依赖其他类&#xff0c;则把其他类给mock&#xff0c;然后A类需要真实对象。这样就可以测试A类中的方法。 举例&#xff1a;Ticket类需要调用Flight类和Pas…

深度学习篇---深度学习中的范数

文章目录 前言一、向量范数1.L0范数1.1定义1.2计算式1.3特点1.4应用场景1.4.1特征选择1.4.2压缩感知 2.L1范数&#xff08;曼哈顿范数&#xff09;2.1定义2.2计算式2.3特点2.4应用场景2.4.1L1正则化2.4.2鲁棒回归 3.L2范数&#xff08;欧几里得范数&#xff09;3.1定义3.2特点3…

JVM常见概念之条件移动

问题 当我们有分支频率数据时&#xff0c;有什么有趣的技巧可以做吗&#xff1f;什么是条件移动&#xff1f; 基础知识 如果您需要在来自一个分支的两个结果之间进行选择&#xff0c;那么您可以在 ISA 级别做两件不同的事情。 首先&#xff0c;你可以创建一个分支&#xff…

Debug-037-table列表勾选回显方案

效果展示&#xff1a; 图1 图2 最近实现一个支持勾选的el-table可以回显之前勾选项的功能。实现了一个“编辑”的功能&#xff1a; 在图1中的列表中有三行数据&#xff0c;当点击“更换设备”按钮时&#xff0c;打开抽屉显示el-table组件如图2所示&#xff0c;可以直接回显勾选…

Python散点图(Scatter Plot):数据探索的“第一张图表”

在数据可视化领域,散点图是一种强大而灵活的工具,它能够帮助我们直观地理解和探索数据集中变量之间的关系。本文将深入探讨散点图的核心原理、应用场景以及如何使用Python进行高效绘制。 后续几篇将介绍高级技巧、复杂应用场景。 Python散点图(Scatter Plot):高阶分析、散点…

docker利用ollama +Open WebGUI在本地搭建部署一套Deepseek-r1模型

系统&#xff1a;没有限制&#xff0c;可以运行docker就行 磁盘空间&#xff1a;至少预留50GB; 内存&#xff1a;8GB docker版本&#xff1a;4.38.0 桌面版 下载ollama镜像 由于docker镜像地址&#xff0c;网络不太稳定&#xff0c;建议科学上网的一台服务器拉取ollama镜像&am…

JavaScript |(六)DOM事件 | 尚硅谷JavaScript基础实战

学习来源&#xff1a;尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 笔记来源&#xff1a;在这位大佬的基础上添加了一些东西&#xff0c;欢迎大家支持原创&#xff0c;大佬太棒了&#xff1a;JavaScript |&#xff08;六&#xff09;DOM事件 | 尚硅谷JavaScript基础…

卷积神经网络 - 梯度和反向传播算法

在卷积网络中&#xff0c;参数为卷积核中权重以及偏置。和全连接前馈网络类似&#xff0c;卷积网络也可以通过误差反向传播算法来进行参数学习。本文我们从数学角度&#xff0c;来学习卷积神经网络梯度的推导和其反向传播算法的原理。 一、梯度&#xff1a;损失函数 L 关于第 …

鸿蒙NEXT项目实战-百得知识库03

代码仓地址&#xff0c;大家记得点个star IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点&#xff1a; 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三…

【测试篇】关于allpairs实现正交测试用例保姆级讲解,以及常见的错误问题

前言 &#x1f31f;&#x1f31f;本期讲解关于测试工具相关知识介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不多说…

OpenCV图像拼接(4)图像拼接模块的一个匹配器类cv::detail::BestOf2NearestRangeMatcher

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::detail::BestOf2NearestRangeMatcher 是 OpenCV 库中用于图像拼接模块的一个匹配器类&#xff0c;专门用于寻找两幅图像之间的最佳特征点匹配…

C++: AVL树(实现旋转操作)

前言 map/set容器有个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的&#xff0c;但是二叉搜索树有其自身的缺陷&#xff0c;假如往树中插入的元素有序或者接近有序&#xff0c;二叉搜索树就会退化成单支树&#xff0c;时间复杂度会退化成O(N)&#xff0c;因此map、set…

OpenCV中距离公式

一、各类距离公式总结 常见距离公式 欧氏距离&#xff1a; 曼哈顿距离&#xff08;L1&#xff09;‌&#xff1a; 切比雪夫距离&#xff08;Chessboard&#xff09;‌&#xff1a; 1、点与点距离(欧氏距离) ‌二维空间‌ 设两点坐标为 P1(x1,y1)、P2(x2,y2)&#xff0c;其距离…

六十天前端强化训练之第二十四天之Vue 模板语法与 v-for 指令大师级详解

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、模板语法与指令知识精讲 1.1 模板语法三大核心 1.2 常见指令全家福 1.3 v-for 深度解析 二、商品列表示例完整实现 2.1 完整可运行代码 2.2 代码解析 2.3 运行效果…

XSS跨站脚本攻击漏洞(Cross Site Scripting)

前提概要 本文章主要用于分享XSS跨站脚本攻击漏洞基础学习&#xff0c;以下是对XSS跨站脚本攻击漏洞的一些个人解析&#xff0c;请大家结合参考其他文章中的相关信息进行归纳和补充。 XSS跨站脚本攻击漏洞描述 跨站脚本攻击&#xff08;XSS&#xff09;漏洞是一种常见且危害较…

用ArcGIS做一张符合环评要求的植被类型图

植被类型图是环境影响评价&#xff08;环评&#xff09;中的重要图件&#xff0c;需满足数据准确性、制图规范性和信息完整性等要求。本教程将基于ArcMap平台&#xff0c;从数据准备到成果输出&#xff0c;详细讲解如何制作符合环评技术规范的植被类型图。 ArcGIS遥感解译土地…

详解string类+迭代器

迭代器 概念&#xff1a;在 C 中&#xff0c;迭代器是访问容器&#xff08;如数组、列表、向量、字符串等&#xff09;元素的一种方式。迭代器提供了一种统一的接口&#xff0c;使得你可以使用相同的代码来遍历不同类型的容器。迭代器本质上是一个指针或者指针的封装&#xff0…