好奇的探索者,理性的思考者,踏实的行动者。
Table of Contents:
函数原型
int getopt(int argc,char * const argv[ ],const char * optstring);
optstring选项字符串格式:
`a:b:cd::e`,这就是一个选项字符串。
对应到命令行就是-a ,-b ,-c ,-d, -e 。
冒号又是什么呢?
冒号表示参数,一个冒号就表示这个选项后面必须带有参数(没有带参数会报错哦),但是这个参数可以和选项连在一起写,也可以用空格隔开,比如-a123 和-a 123(中间有空格) 都表示123是-a的参数;
两个冒号的就表示这个选项的参数是可选的,即可以有参数,也可以没有参数,但要注意有参数时,参数与选项之间不能有空格(有空格会报错的哦),这一点和一个冒号时是有区别的。
命令行的处理工具。
主要通过三个组件完成:
options_description(选项描述器) 描述当前的程序定义了哪些选项
parse_command_line(选项分析器) 解析由命令行输入的参数
variables_map(选项存储器) 容器,用于存储解析后的选项
CLI11是一个基于C++开发的命令行解析库
使用很方便,只需要#include <CLI11.hpp>
,当然也可以使用cmake编译版本
#include "CLI11.hpp"
#include <iostream>
//只接受一个可选参数-p
int main(int argc, char **argv) {"App description"};
CLI::App app{
// Define options
0;
int p = "-p", p, "Parameter");
app.add_option(
CLI11_PARSE(app, argc, argv);
std::cout << "Parameter value: " << p << std::endl;
0;
return }
CLI::App 是与库的所有交互的基础
CLI11_PARSE 宏内部执行app.parse(argc,argv)对命令行参数解析,出错时抛出ParseError,然后捕获异常,打印错误信息并退出程序
cp source_file destination_file
source_file
和destination_file
就是位置参数,它们分别指定了源文件和目标文件的路径。python -v
--option=value
或--option value
,具体取决于命令的要求。例如,在以下命令中:python script.py --input-file=input.txt --output-file=output.txt
--input-file
和--output-file
是选项,分别传递了输入文件和输出文件的路径。子命令就是包含了一系列选项的一个关键字,如git commit/clone 这里面的commit clone后面还可以跟各种选项,他们就是git程序的子命令
子命令的类类型和App相同,因此可以任意嵌套
//把CLI11.hpp放到当前目录下
#include "CLI11.hpp"
#include <iostream>
using namespace std;
int main(int argc, char **argv) {"App description"}; // 软件描述出现在第一行打印
CLI::App app{"My footer"); // 最后一行打印
app.footer(40); // 列的宽度
app.get_formatter()->column_width(1); // 表示运行命令需要且仅需要一个子命令
app.require_subcommand(
"sub1", "subcommand1");
auto sub1 = app.add_subcommand("sub2", "subcommand1");
auto sub2 = app.add_subcommand(// 当出现的参数子命令解析不了时,返回上一级尝试解析
sub1->fallthrough();
sub2->fallthrough();
// 定义需要用到的参数
string filename;10;
int threads = 0;
int mode = int> barcodes;
vector<
bool reverse = false;
string outPath;
if (sub1)
{// 第一个参数不加-, 表示位置参数,位置参数按出现的顺序来解析
// 这里还检查了文件是否存在,已经是必须参数
"file", filename, "Position paramter")->check(CLI::ExistingFile)->required();
sub1->add_option(
// 检查参数必须大于0
"-n,-N", threads, "Set thread number")->check(CLI::PositiveNumber);
sub1->add_option(
}
if (sub2)
{// 设置范围
"-e,-E", mode, "Set mode")->check(CLI::Range(0,3));
sub2->add_option(// 将数据放到vector中,并限制可接受的长度
"-b", barcodes, "Barcodes info:start,len,mismatch")->expected(3,6);
sub2->add_option(
}// 添加flag,有就是true
"-r,-R", reverse, "Apply reverse");
app.add_flag(// 检查目录是否存在
"-o", outPath, "Output path")->check(CLI::ExistingDirectory);
app.add_option(
CLI11_PARSE(app, argc, argv);
// 判断哪个子命令被使用
if (sub1->parsed())
{"Got sub1"<<endl;
cout<<"filename:"<<filename<<endl;
cout<<"threads:"<<threads<<endl;
cout<<
}
else if (sub2->parsed())
{"Got sub2"<<endl;
cout<<"mode:"<<mode<<endl;
cout<<"barcodes:";
cout<<auto& b : barcodes)
for (" ";
cout<<b<<
cout<<endl;
}"Comman paras"<<endl;
cout<<endl<<"reverse:"<<reverse<<endl;
cout<<"outPath:"<<outPath<<endl;
cout<<
0;
return }