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

news2025/3/25 20:58:15

首选的现代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.coloradmin.cn/o/2319869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙HarmonyOS NEXT应用崩溃分析及修复

鸿蒙HarmonyOS NEXT应用崩溃分析及修复 如何保证应用的健壮性&#xff0c;其中一个指标就是看崩溃率&#xff0c;如何降低崩溃率&#xff0c;就需要知道存在哪些崩溃&#xff0c;然后对症下药&#xff0c;解决崩溃。那么鸿蒙应用中存在哪些崩溃类型呢&#xff1f;又改如何解决…

机器学习——分类、回归、聚类、LASSO回归、Ridge回归(自用)

纠正自己的误区&#xff1a;机器学习是一个大范围&#xff0c;并不是一个小的方向&#xff0c;比如&#xff1a;线性回归预测、卷积神经网络和强化学都是机器学习算法在不同场景的应用。 机器学习最为关键的是要有数据&#xff0c;也就是数据集 名词解释&#xff1a;数据集中的…

【canvas】一键自动布局:如何让流程图节点自动找到最佳位置

一键自动布局&#xff1a;如何让流程图节点自动找到最佳位置 引言 在流程图、拓扑图和系统架构图设计中&#xff0c;节点布局往往是最令人头疼的问题。如果手动调整每个节点位置&#xff0c;不仅耗时费力&#xff0c;还难以保证美观性和一致性。本文将深入解析如何实现自动布…

[每周一更]-(第137期):Go + Gin 实战:Docker Compose + Apache 反向代理全流程

文章目录 **1. Go 代码示例&#xff08;main.go&#xff09;****2. Dockerfile 多段构建**3.构建 Docker 镜像**4. docker-compose.yml 直接拉取镜像****5. 运行容器****6. 测试 API**7、配置域名访问**DNS解析&#xff1a;将域名转换为IP地址****DNS寻址示例** 8.错误记录 访问…

SpringCache小记

Spring Cache 小记 官方文档&#xff1a;https://springdoc.cn/spring-cache-tutorial/ 基础知识 常用注解 EnableCaching&#xff1a;开启缓存功能&#xff0c;一般放在启动类上。 Cacheable&#xff1a;表示该方法支持缓存。当调用被注解的方法时&#xff0c;如果对应的键已…

Web-Machine-N7靶机通关攻略

获取靶机ip arp-scan -l 端口扫描 nmap xxxx 访问80端口发现没用 扫描目录 gobuster dir -u http:/192.168.117.160 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium,txt -x php,html,txt ,zip 打开exploit.html 点击F12&#xff0c;修改localhost为靶机ip&#…

第十五次CCF-CSP认证(含C++源码)

第十五次CCF-CSP认证 小明上学满分思路 数据中心满分思路 小明放学满分题解 小明上学 题目链接 满分思路 其实题目看着长&#xff0c;但是做起来是非常好写的&#xff0c;其实主要原因在于&#xff0c;他的红绿灯的变化规律是一定的&#xff0c;而且小明路上的每次红绿灯情况…

Java-servlet(七)详细讲解Servlet注解

Java-servlet&#xff08;七&#xff09;详细讲解Servlet注解 前言一、注解的基本概念二、Override 注解2.1 作用与优势2.2 示例代码 三、Target 注解3.1 定义与用途3.2 示例代码 四、WebServlet 注解4.1 作用4.2 示例代码 五、反射与注解5.1 反射的概念5.2 注解与反射的结合使…

SQLark 实战 | 如何通过对象名和 DDL 快速搜索数据库对象

在数据库运维管理、应用开发和问题定位时&#xff0c;常常需要搜索相关的数据库对象。本文将为你介绍如何使用 SQLark 的搜索功能&#xff0c;实现对数据库对象的快速查找与定位。 &#x1f449; 前往 SQLark 官网&#xff1a;www.sqlark.com 下载全功能免费版。 通过对象名称搜…

C/S模型-TCP

下图是基于TCP协议的客户端/服务器程序的一般流程&#xff1a; TCP协议通讯流程 服务器调用socket()、bind()、listen()完成初始化后&#xff0c;调用accept()阻塞等待&#xff0c;处于监听端口的状态&#xff0c;客户端调用socket()初始化后&#xff0c;调用connect()发出SY…

51c自动驾驶~合集24

我自己的原文哦~ https://blog.51cto.com/whaosoft/11926510 #DriveArena 上海AI Lab又放大招&#xff1a;首个高保真闭环生成仿真平台 仓库链接&#xff1a;https://github.com/PJLab-ADG/DriveArena 项目链接&#xff1a;https://pjlab-adg.github.io/DriveArena/ D…

19.哈希表的实现

1.哈希的概念 哈希(hash)⼜称散列&#xff0c;是⼀种组织数据的⽅式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进⾏快速查找。 1.2.直接定址法…

【PCB工艺】晶体管的发展历史

晶体管被认为是20世纪最伟大的发明之一&#xff0c;因为没有晶体管就不会有现代电脑、手机或平板​​&#xff0c;你也无法阅读到这里的内容&#xff0c;因为不存在网络。 ——本文纯粹出于对过往奋斗在这个领域中科学家的缅怀。科学家有太多宝贵的思想和经验值得我们认真总结和…

通向AGI的未来之路!首篇2D/视频/3D/4D统一生成框架全景综述(港科大中山等)

文章链接&#xff1a; https://arxiv.org/pdf/2503.04641 摘要 理解并复现现实世界是人工通用智能&#xff08;AGI&#xff09;研究中的一个关键挑战。为实现这一目标&#xff0c;许多现有方法&#xff08;例如世界模型&#xff09;旨在捕捉支配物理世界的基本原理&#xff0…

【亚马逊云科技】大模型选型实战(挑选和测评对比最适合业务的大模型)

文章目录 前言1、实验内容2、手册内容 一、环境准备二、Prompt 实战与模型配置2.1 基于 Amazon Bedrock 对比测试不同模型的逻辑推理效果2.2 基于 Amazon Bedrock 对比测试不同模型知识问答能力2.3 Prompt 实战结果分析 三、基于 Amazon Bedrock Evaluations 进行模型评测与自动…

调用feapder作为子程序时setting.py文件不起作用

feaper 官方文档地址&#xff1a; 简介及安装 - feapder官方文档|feapder-document 问题&#xff1a; 在最近的开发中需要调用feapder作为主程序调用的子程序时发现自动入库时无法入库&#xff0c;通过查看日志信息发现连接数据库时被拒绝连接了&#xff0c;但是我的setting.p…

【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试

【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试 Web系统测试Web系统基本组成Web系统的服务器端应用特点Web系统测试的分类Web应用系统测试的实施功能测试链接测试表单测试性能测试连接速度测试负载测试压力测试可用性测试导航测试图形测试内容测试表格测试…

G-Star 校园开发者计划·黑科大|开源第一课之 Git 入门

万事开源先修 Git。Git 是当下主流的分布式版本控制工具&#xff0c;在软件开发、文档管理等方面用处极大。它能自动记录文件改动&#xff0c;简化合并流程&#xff0c;还特别适合多人协作开发。学会 Git&#xff0c;就相当于掌握了一把通往开源世界的钥匙&#xff0c;以后参与…

5.0 VisionPro调用USB相机的方法与步骤说明(一)

本文介绍如何在C#中调用visionPro以处理USB相机采集到的图片。示例如下: 主要思路如下: 1. 使用AForge来打开以及采集usb相机照片。 usb相机处于一直运行状态。每隔100ms采集一次照片。且触发一次事件。 public void Start() { this.videoSourcePlayer.Stop(); …

微信小程序计算属性与监听器:miniprogram-computed

小程序框架没有提供计算属性相关的 api &#xff0c;但是官方为开发者提供了拓展工具库 miniprogram-computed。 该工具库提供了两个功能&#xff1a; 计算属性 computed监听器 watch 一、安装 miniprogram-computed 在项目的根目录下&#xff0c;使用如下命令&#xff0c;…