program_options 是一个实现了类似 optarg 但是比 optargs 功能强大的 boost库.
使用它来解析命令行参数或者配置文件都是很简单的.
官方教程
http://www.boost.org/doc/libs/1_57_0/doc/html/program_options.html
依赖
安装boost库, 至少编译 program_options 部分.
添加include路径
-I boost_include_path
添加链接库
-lboost_program_options
头文件 命名空间
#include "boost/program_options.hpp"
using namespace boost::program_options;
简单操作
定义并添加命令说明
int opt;
/* 类 options_description 是存储选项详细信息的类 */
options_description parser("name_your_like");
/*add_option() 支持() 操作. 多次调用add_options() 的效果等同于将所有的选项使用() 并列声明*/
parser.add_options()
/*无参数的选项格式 : "命令名" , "命令说明" */
("help", "produce help message")
/* 有参赛的选项格式 :
"命令名" , "参数说明" , "命令说明" */
("set-float" ,value<float>(), "set a float parameter")
/* 参数对应已有数据(特定地址) , 并且有初始值 : */
("optimization", value<int>(&opt)->default_value(10),
"optimization level")
/* 支持短选项 ( --include-path 和 -I 等效 ) ,
多次调用存在依次vector中 */
("include-path,I", value< vector<string> >(),
"include path")
;
解析命令行 , 存储在variables_map 类的变量中
/* variables_map 类是用来存储具体传入参数数据的类 , 和map很相似. 使用as接口来传出数据 */
variables_map vm;
/* ac 就是参数个数 , av 就是参数列表指针 */
/* int ac , const char ** av */
/* parse_command_line 接口不支持猜测选项 */
store(parse_command_line(ac, av, desc), vm);
notify(vm);
注意: 如果传入没有定义的选项, 会抛出异常!
判断命令是否触发 , 以 help 为例
/* variables_map 使用 count 接口来判断具体选项是否触发 */
if (vm.count("help")) {
/*如果触发就输出命令说明 , option_description 类重载了 << 行为, 将格式化的输出
命令说明 */
cout << desc << "\n";
return 1;
}
取出传入的参数 , 以上面的float参数为例
首先, 如果已经指定了一个接受数据 [ 比如 : (“optimization”, value(&opt)->default_value(10), “optimization level”) ]的话,就可以直接使用它.
if (vm.count("set-float")) {
cout << "set-float "<<
/*map直接使用键值当index , 然后使用as< 具体类型> 接口来取出参数*/
vm["set-float"].as<float>() << ".\n";
} else {
cout << "float not set\n";
}
定义默认参数.
上面的例子中 ,如下操作:
$ a.out –set-float=0.131415926
$ set-float 0.131415926
然而假设我们想要以下面的命令实现上面的效果:
$ a.out 0.131415926
$ set-float 0.131415926
就需要设置set-float 为默认的参数.
int opt;
options_description parser("name_your_like");
parser.add_options()
("help", "produce help message")
("set-float" ,value<float>(), "set a float parameter")
("optimization", value<int>(&opt)->default_value(10),
"optimization level")
("include-path,I", value< vector<string> >(),
"include path")
;
/* 定义一个可以猜测的命令 positional_options_description */
positional_options_description p;
/* 指定猜测的时候参数的位置, -1 标识没有任何限制 */
p.add("set-float", -1);
variables_map vm;
/* 使用可以猜测的命令行解析接口来解析 */
store(command_line_parser(ac, av).options(desc).positional(p).run(), vm);
notify(vm);
这样就支持了默认选项是 –set-float
对配置文件的支持
/*将文件读入流*/
ifstream ifs("file_name");
/* 调用解析文件接口 */
store(parse_config_file(ifs, desc), vm);
notify(vm);
下面是一个例子
boost::program_options::positional_options_description arguments;
arguments.add("type", 1);
arguments.add("connect", 1);
boost::program_options::options_description all;
all.add_options()
( "type", "0mq socket type" )
;
all.add(miscellaneous_options());
all.add(connection_options());
boost::program_options::variables_map vm;
client_options options;
try
{
boost::program_options::store( boost::program_options::command_line_parser( argc, argv ).options( all ).positional( arguments ).run(), vm );
}
catch(boost::program_options::too_many_positional_options_error& e)
{
std::cerr << "Too many arguments provided." << std::endl;
options.show_usage = true;
}
catch(boost::program_options::unknown_option& e)
{
std::cerr << "Unknown option '" << e.get_option_name() << "'." << std::endl;
options.show_usage = true;
}
catch(boost::program_options::error& e)
{
std::cerr << "command line parse error: " << e.what() << "'." << std::endl;
options.show_usage = true;
}
socket_type_index socket_types = socket_type_options();
if ( vm.count( "type" ) && ( socket_types.end() == socket_types.find( vm["type"].as<std::string>() ) ) )
{
std::cerr << "Unknown value '" << vm["type"].as<std::string>() << "' provided for 0mq socket type." << std::endl;
options.show_usage = true;
}
if ( (0 == vm.count( "type" )) || vm.count( "help" ) || ( (0 == vm.count( "connect" )) && (0 == vm.count( "bind" )) ) )
{
options.show_usage = true;
}
options.show_version = ( vm.count( "version" ) > 0 );
options.show_help = ( vm.count( "help" ) > 0 );
if ( vm.count( "type" ) ) { options.type = socket_types[ vm["type"].as<std::string>() ]; }
if ( vm.count( "bind" ) ) { options.binds = vm["bind"].as<std::vector<std::string>>(); }
if ( vm.count( "connect" ) ) { options.connects = vm["connect"].as<std::vector<std::string>>(); }
options.singlepart = ( vm.count( "singlepart" ) > 0 );
options.annotate = ( vm.count( "annotate" ) > 0 );
options.verbose = ( vm.count( "verbose" ) > 0 || vm.count( "detailed" ) > 0 );
options.detailed = ( vm.count( "detailed" ) > 0 );
options.exit_on_empty = ( vm.count( "exit-when-no-input" ) > 0 );
return options;