C++ 02.好用的命令行解析库cmdline和CLI11

发布于:2025-05-23 ⋅ 阅读:(18) ⋅ 点赞:(0)

1. 获取命令行参数

在 C++ 程序中,我们可以通过 main 函数的参数来接收命令行参数。主要有两种形式:

1.1. 传统方式

int main(int argc, char* argv[])

其中:

  • argc: argument count,表示命令行参数的数量
  • argv: argument vector,是一个指针数组,包含所有的命令行参数字符串
    • argv[0] 通常是程序名称
    • argv[1] 开始才是实际的命令行参数

1.1.1. 示例代码

下面是一个简单的命令行参数处理示例:

#include <iostream>

int main(int argc, char* argv[]) {
    std::cout << "参数数量: " << argc << std::endl;
    
    for(int i = 0; i < argc; i++) {
        std::cout << "参数 " << i << ": " << argv[i] << std::endl;
    }
    
    return 0;
}

1.1.2. 使用方法

编译并运行上述程序:

g++ main.cpp -o program
./program arg1 arg2 "argument 3"

输出将类似于:

参数数量: 4
参数 0: ./program
参数 1: arg1
参数 2: arg2
参数 3: argument 3

1.2. 现代处理方式

对于更复杂的命令行参数处理,建议使用一些现代的库:

  1. Boost.Program_options: 功能强大的命令行解析库
  2. cxxopts: 轻量级的头文件库
  3. CLI11: 现代化的命令行解析器
  4. cmdline: 一个简单的头命令行解析器,直接引入到程序中即可。头文件下载

这些现代库提供了更多功能:

  • 自动生成帮助信息
  • 类型安全的参数解析
  • 必选参数验证
  • 短选项和长选项支持
  • 默认值设置

1.3. cmdline

仅能在linux下运行,在windows下运行会报错,报错信息如下:找不到文件: #include <cxxabi.h>
示例代码


#include "cmdline.h"

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
  cmdline::parser parser;
  parser.add<string>("host", 'h', "host name", true, "");
  parser.add<int>("port", 'p', "port number", false, 80, cmdline::range(1, 65535));
  parser.add<string>("type", 't', "protocol type", false, "http", cmdline::oneof<string>("http", "https", "ssh", "ftp"));
  parser.add("gzip", '\0', "gzip when transfer");

  parser.parse_check(argc, argv);

  cout << parser.get<string>("type") << "://"
       << parser.get<string>("host") << ":"
       << parser.get<int>("port") << endl;

  if (parser.exist("gzip")) cout << "gzip" << endl;

  return 0;
}

linux编译&运行

g++ main.cpp -o main
./main  --host "a.com" -p 8080 -t https 

输出将类似于:

https://a.com:8080

常见的用法

parser.add<std::string>("host", 'h', "host name", true, "");  //参数做为std::string 类型
parser.add<int>("port", 'p', "port number", false, 80, cmdline::range(1, 65535));  //参数做为int 类型

add() 函数的参数说明,以add<std::string>()为例:

template <class T, class F>
  void add(const std::string &name,  //长的参数名,运行时带 --
           char short_name=0, //短的参数名,运行时带 -
           const std::string &desc="", //参数描述
           bool need=true, //是否必须
           const T def=T(), //默认值
           F reader=F()){
    if (options.count(name)) throw cmdline_error("multiple definition: "+name);
    options[name]=new option_with_value_with_reader<T, F>(name, short_name, need, def, desc, reader);
    ordered.push_back(options[name]);
  }

注意:

  1. char 型值在解析命令行时会报错,可以使用string类型值暂时存储解析的命令行的值,然后从string类型值中获取char型值

1.4. CLI11用法

vcpkg install cli11

简要示例代码

#include <CLI/CLI.hpp>
#include <iostream>

int main(int argc, char** argv) {
    // 创建CLI对象
    CLI::App app{"A brief description of your program"};

    // 定义一个变量来存储命令行参数值
    int my_int{0};
    std::string my_string;

    // 添加选项
    app.add_option("-i,--int-option", my_int, "An integer option");
    app.add_option("-s,--string-option", my_string, "A string option");

    // 解析命令行
    CLI11_PARSE(app, argc, argv);

    // 使用获取到的值
    std::cout << "Integer option: " << my_int << "\n";
    std::cout << "String option: " << my_string << "\n";

    return 0;
}  

编译&运行

cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
cmake --build build 
if ($?)
{
    .\build\Debug\main.exe -i 5 -s hello
}

输出如下:

Integer option: 5
String option: hello

1.5. 参考资料

  1. GitHub - tanakh/cmdline: A Command Line Parser

网站公告

今日签到

点亮在社区的每一天
去签到