boost的配置解析库

介绍

程序参数项(programoptions)是一系列name=value对,program_options允许程序开发者获得通过命令行(commandline)和配置文件(configfile)获取这些参数项。

为什么需要这样一个库?为什么比你手工写代码分解命令行参数要好?

  • 使用更容易。定义参数处理的语法简单,库自身很小。像转换参数值到指定的类型和保存参数值到变量的事情都是自动处理。

  • 错误报告更友好。可报告错误的命令行参数。另外这个库能自动生成使用帮助,避免手工更新使用帮助导致的不一致。

  • 参数能从不同地方读取。当命令行参数不能满足要求,需要改用配置文件或环境变量。
    这些功能都能支持,代码改动很小。使用指南

快速入门

使用详解

参数多种来源

在本节,我们从最简单的例子开始,学习program_options库的通常用法。下面的例子仅仅是代码片断,完整例子在BOOST_ROOT/libs/program_options/example”目录里。对所有例子,假定都在如下名字空间中:

namespacepo = boost::program_options;

一、快速入门

第一个例子尽可能简单:仅仅包含两个参数项。代码如下(完整代码见example/first.cpp”):

//Declare the supported options.

po::options_descriptiondesc("Allowed options");

desc.add_options()

("help","produce help message")

("compression",po::value(), "set compression level")

;


po::variables_map vm;

po::store(po::parse_command_line(ac,av, desc), vm);

po::notify(vm);


if(vm.count("help")) {

cout<< desc << "\n";

return1;

}


if(vm.count("compression")) {

cout<< "Compression level was set to "

<<vm["compression"].as() << ".\n";

}else {

cout<< "Compression level was not set.\n";

}

首先用类options_description描述所有允许的参数项,类的add_options方法返回定义了operator()的代理对象,调用其operator()用来实际描述参数项,函数参数是参数项名称,相关值信息,参数项描述。本例中,第一个参数项没有值,第二个参数项有一个int类型的值。

其后,定义一个类variables_map对象。用来存储参数项的值,其能存储任意类型的值。接着调用store,parse_command_linenotify函数,解析命令行参数并保存到vm中。

现在,可以像使用std::map一样来使用variables_map类,但存储的值必须能通过at方法找回。假如调用as方法指定的类型和实际类型不符,将抛出异常)

现在自己可以尝试编译一下代码,如何编译的例子如下:

$bin/gcc/debug/first

Compressionlevel was not set.

$bin/gcc/debug/first--help

Allowedoptions:

--help : produce help message

--compressionarg : set compression level


$bin/gcc/debug/first--compression 10

Compressionlevel was set to 10.


使用详解

参数项的值,除了int还有其他类型,还有其他属性,我们下面将讨论。完整例子在example/options_description.cpp”中。

假如我们写一个编译器程序。它有最优化级别,包含多个路径,多个输入文件等参数。描述参数项如下:
 

intopt;

po::options_descriptiondesc("Allowed options");

desc.add_options()

("help","produce help message")

("optimization",po::value(&opt)->default_value(10),

"optimizationlevel")

("include-path,I",po::value< vector >(),

"includepath")

("input-file",po::value< vector >(), "input file")

;

The"--help"项和前例一样,在项目中有这个参数项是个好注意。

The"optimization"项体现两个新特性.首先,我们传递变量(&opt)地址,这个变量用来保存获得的参数项的值。然后,指定一个缺省值,用在此参数项用户没有设置值的时候。
 

The"include-path"项说明了options_description类接口仅仅来源于命令行的例子。用户喜欢用短参数项名称,include-path,I”名指出短参数项名是I”.因此,--include-path”-I”都能用。
 

The"input-file"参数项指定处理文件列表。像下面这样写没有问题:

compiler--input-file=a.cpp

但通常情况常常这么写:

compilera.cpp

这里要解释一下这种用法。

像上例,没有参数名的命令行选项,在这个库里称为位置参数项,也能处理。库能解释a.cpp”等同于--input-file=a.cpp”。下面是所需的附加的代码:

po::positional_options_descriptionp;

p.add("input-file",-1);


po::variables_mapvm;

po::store(po::command_line_parser(ac,av).

options(desc).positional(p).run(),vm);

po::notify(vm);

前两行指出所有的位置参数项应被翻译成input-file”项。要注意用command_line_parser类解析命令行,而不是parse_command_line函数。parse_command_line函数是为处理简单情况对command_line_parser类的封装,但现在要传递附加信息就
不适用了。

现在,所有参数项被描述且被解析。我们暂不实现剩下的编译逻辑,仅仅打印参数项:

if(vm.count("include-path"))

{

cout<< "Include paths are: "

<<vm["include-path"].as< vector >() << "\n";

}


if(vm.count("input-file"))

{

cout<< "Input files are: "

<<vm["input-file"].as< vector >() << "\n";

}


cout<< "Optimization level is " << opt <<"\n";

如何编译的例子如下:

$bin/gcc/debug/options_description--help

Usage:options_description [options]

Allowedoptions:

--help : produce help message

--optimizationarg : optimization level

-I[ --include-path ] arg : include path

--input-filearg : input file

$bin/gcc/debug/options_description

Optimizationlevel is 10

$bin/gcc/debug/options_description--optimization 4 -I foo a.cpp

Includepaths are: foo

Inputfiles are: a.cpp

Optimizationlevel is 4

这里有个小问题,帮助信息要求指定--input-file”项名称,这将把用户弄糊涂。在后面的例子中可看到怎样隐藏这个信息。


参数多种来源

 

要求用户在命令行给我们的编译器指定所有参数不太现实。假如用户安装新库且想传递一个附加命令行参数该怎么做?想实现一次选择多次运行的时候使用该怎么做?可以创建一个配置文件把命令行参数组织在一起来完成这个工作。

当然,解析时需要结合命令行参数和配置文件两方面的值。例如,在命令行指定的最优化级别的值将覆盖配置文件的值。另一方面,包含路径应该包含命令行和配置文件里两方面的值。

面看代码。完整代码在examples/multiple_sources.cpp”。参数项定义有两种细节。首先,定义options_description类的几个实例。原因是,通常情况下,不是所有参数项属性是类似的。一些项,例如上面的input-file”应该在自动帮助信息里不出现。一下项仅在配置文件中有意义。其次,帮助信息有组织的输出是个好主意,而不仅仅是参数项的长列表。下面声明几组参数项:

//Declare a group of options that will be

//allowed only on command line

po::options_descriptiongeneric("Generic options");

generic.add_options()

("version,v","print version string")

("help","produce help message")

;

//Declare a group of options that will be

//allowed both on command line and in

//config file

po::options_descriptionconfig("Configuration");

config.add_options()

("optimization",po::value(&opt)->default_value(10),

"optimizationlevel")

("include-path,I",

po::value<vector >()->composing(),

"includepath")

;


//Hidden options, will be allowed both on command line and

//in config file, but will not be shown to the user.

po::options_descriptionhidden("Hidden options");

hidden.add_options()

("input-file",po::value< vector >(), "input file")

;

注意在"include-path"项声明中调用composing方法,说明从不同来源的值应当被合并在一起,下面很快就会看到。

options_description类的add方法能被用于进一步组合参数项:

po::options_descriptioncmdline_options;

cmdline_options.add(generic).add(config).add(hidden);


po::options_descriptionconfig_file_options;

config_file_options.add(config).add(hidden);


po::options_descriptionvisible("Allowed options");

visible.add(generic).add(config);

除了额外需要调用parse_config_filestore函数以外,参数值的解析和存储和通常一样。但是当命令行和配置文件中同样的参数被指定了如何处理?通常,首选第一个被存储的值。这说明了--optimization”项的值如何产生。对组合(composing)”项,像include-file”,值被合并在一起。

如何编译的例子如下: 

$bin/gcc/debug/multiple_sources

Includepaths are: /opt

Optimizationlevel is 1

$bin/gcc/debug/multiple_sources--help

Allowsoptions:


Genericoptions:

-v[ --version ] : print version string

--help : produce help message


Configuration:

--optimizationn : optimization level

-I[ --include-path ] path : include path


$bin/gcc/debug/multiple_sources--optimization=4 -I foo a.cpp b.cpp

Includepaths are: foo /opt

Inputfiles are: a.cpp b.cpp

Optimizationlevel is


附录

为加强理解,这里列出了上面提到的完整源代码。

文件example/first.cpp

 

#include

namespacepo = boost::program_options;


#include

#include

usingnamespace std;


intmain(int ac, char* av[])

{

try{


po::options_descriptiondesc("Allowed options");

desc.add_options()

("help","produce help message")

("compression",po::value(), "set compression level")

;


po::variables_mapvm;

po::store(po::parse_command_line(ac,av, desc), vm);

po::notify(vm);


if(vm.count("help")) {

cout<< desc << "\n";

return1;

}


if(vm.count("compression")) {

cout<< "Compression level was set to "

<<vm["compression"].as() << ".\n";

}else {

cout<< "Compression level was not set.\n";

}

}

catch(exception&e) {

cerr<< "error: " << e.what() << "\n";

return1;

}

catch(...){

cerr<< "Exception of unknown type!\n";

}


return0;

}

文件example/options_description.cpp

#include


usingnamespace boost;

namespacepo = boost::program_options;


#include

#include

#include

usingnamespace std;



//A helper function to simplify the main part.

template

ostream&operator<<(ostream& os, const vector& v)

{

copy(v.begin(),v.end(), ostream_iterator(cout, " "));

returnos;

}


intmain(int ac, char* av[])

{

try{

intopt;

po::options_descriptiondesc("Allowed options");

desc.add_options()

("help","produce help message")

("optimization",po::value(&opt)->default_value(10),

"optimizationlevel")

("include-path,I",po::value< vector >(),

"includepath")

("input-file",po::value< vector >(), "input file")

;


po::positional_options_descriptionp;

p.add("input-file",-1);

po::variables_mapvm;

po::store(po::command_line_parser(ac,av).

options(desc).positional(p).run(),vm);

po::notify(vm);

if(vm.count("help")) {

cout<< "Usage: options_description [options]\n";

cout<< desc;

return0;

}


if(vm.count("include-path"))

{

cout<< "Include paths are: "

<<vm["include-path"].as< vector >() << "\n";

}


if(vm.count("input-file"))

{

cout<< "Input files are: "

<<vm["input-file"].as< vector >() << "\n";

}


cout<< "Optimization level is " << opt <<"\n";

}

catch(exception&e)

{

cout<< e.what() << "\n";

return1;

}

return0;

}

 

文件examples/multiple_sources.cpp

#include

namespacepo = boost::program_options;



#include

#include

#include

usingnamespace std;


//A helper function to simplify the main part.

template

ostream&operator<<(ostream& os, const vector& v)

{

copy(v.begin(),v.end(), ostream_iterator(cout, " "));

returnos;

}



intmain(int ac, char* av[])

{

try{

intopt;

//Declare a group of options that will be

//allowed only on command line

po::options_descriptiongeneric("Generic options");

generic.add_options()

("version,v","print version string")

("help","produce help message")

;

//Declare a group of options that will be

//allowed both on command line and in

//config file

po::options_descriptionconfig("Configuration");

config.add_options()

("optimization",po::value(&opt)->default_value(10),

"optimizationlevel")

("include-path,I",

po::value<vector >()->composing(),

"includepath")

;


//Hidden options, will be allowed both on command line and

//in config file, but will not be shown to the user.

po::options_descriptionhidden("Hidden options");

hidden.add_options()

("input-file",po::value< vector >(), "input file")

;


po::options_descriptioncmdline_options;

cmdline_options.add(generic).add(config).add(hidden);


po::options_descriptionconfig_file_options;

config_file_options.add(config).add(hidden);


po::options_descriptionvisible("Allowed options");

visible.add(generic).add(config);

po::positional_options_descriptionp;

p.add("input-file",-1);

po::variables_mapvm;

store(po::command_line_parser(ac,av).

options(cmdline_options).positional(p).run(),vm);


ifstreamifs("multiple_sources.cfg");

store(parse_config_file(ifs,config_file_options), vm);

notify(vm);

if(vm.count("help")) {

cout<< visible << "\n";

return0;

}


if(vm.count("version")) {

cout<< "Multiple sources example, version 1.0\n";

return0;

}


if(vm.count("include-path"))

{

cout<< "Include paths are: "

<<vm["include-path"].as< vector >() << "\n";

}


if(vm.count("input-file"))

{

cout<< "Input files are: "

<<vm["input-file"].as< vector >() << "\n";

}


cout<< "Optimization level is " << opt <<"\n";

}

catch(exception&e)

{

cout<< e.what() << "\n";

return1;

}

return0;

}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在C++中使用Boost进行命令行参数解析,您需要使用Boost.Program_options模块。以下是一个示例: ```cpp #include <iostream> #include <boost/program_options.hpp> namespace po = boost::program_options; int main(int argc, char** argv) { po::options_description desc("Allowed options"); desc.add_options() ("help", "显示帮助信息") ("input", po::value<std::string>(), "输入文件名") ("output", po::value<std::string>(), "输出文件名"); po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); if (vm.count("help")) { std::cout << desc << std::endl; return 0; } if (vm.count("input")) { std::string inputFileName = vm["input"].as<std::string>(); std::cout << "输入文件名: " << inputFileName << std::endl; } if (vm.count("output")) { std::string outputFileName = vm["output"].as<std::string>(); std::cout << "输出文件名: " << outputFileName << std::endl; } return 0; } ``` 在这个示例中,我们使用`boost::program_options`命名空间来定义命令行选项。`desc`对象包含了可以接受的选项,比如`--help`、`--input`和`--output`。每个选项都可以接受一个参数。 然后,我们使用`po::parse_command_line`函数来解析命令行参数,并将解析结果存储在`vm`(variables_map)对象中。`po::notify`函数用于通知`variables_map`对象已经完成解析。 接下来,我们可以通过检查`variables_map`对象中的选项是否存在来处理用户提供的命令行参数。在示例中,我们检查`--help`、`--input`和`--output`选项是否存在,并使用`as<std::string>()`方法获取选项的值。 如果用户提供了`--help`选项,我们将打印出命令行选项的帮助信息。否则,我们将打印出输入文件名和输出文件名(如果有提供的话)。 请确保在编译时链接了Boost.Program_options,并将编译器的标志设置为`-lboost_program_options`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值