boost::program_options 简介
命令行处理是另一个难点,开发人员通常不会采用结构化的方式来解决。其结果是从头到尾维护开销。Boost program_options 库提供了简化命令行处理的例程和数据结构。
清单 15 详细描述了 boost::program_options 的使用。这是建议在您的代码中使用的标准模板。
清单 15. 使用 boost::program_options
#include <string>
#include <iostream>
#include <boost/program_options.hpp>
using namespace std;
int main (int ac, char* av[])
{
boost::program_options::options_description options("command line options");
options.add_options() ("help", "Use -h or --help to list all arguments")
("file", boost::program_options::&#118alue<string>(),
"Provide input file name");
boost::program_options::variables_map vmap;
boost::program_options::store(
boost::program_options::parse_command_line(ac, av, options), vmap);
boost::program_options::notify(vmap);
if (vmap.count("help")) {
cout << options << endl;
}
return 0;
}
您必须包括 program_options.hpp 头文件。清单 15 的工作方式如下:
options_description 类声明所有的有效命令行选项。
使用方法 add_options,您可以注册命令和跟在命令后面的参数类型。在此例中,help 选项不需要任何参数,但是 file 选项需要一个字符串参数。
variables_map 类在运行时存储命令行选项及其参数。
Boost 的 parse_command_line 例程解析 argc 和 argv 参数。store 和 notify 方法帮助存储 vmap 对象中的数据。
当您检查 help 是否为程序的恰当命令行选项(这是 vmap.count("help") 所做的工作)时,options 对象将被转储到 cout。这意味着运算符 << 是为 options_description 类定义的。
下面是来自清单 15 的输出:
[user@/home/user1] ./a.out --help
command line options:
--help Use -h or --help to list all arguments
--file arg Provide input file name
当您遇到其他选项时,可以采取进一步的操作。例如,下面的代码片段经过了修改,以打印您输入的文件名:
…
if (vmap.count("file")) {
cout << "Setting input file to " << vmap["file"].as<string>() << ".\n";
} else {
cout << "No file specified\n";
}
…
请注意,variable_map 类在许多方面与哈希表非常相似。例如,要检索 file 参数,您可以调用 vmap["file"]。
回页首
提供多个参数和缩写的命令选项
命令行处理通常同时需要同一个命令选项的短名称和长名称。此外,您通常必须多次使用某个选项,以便收集该选项的所有参数。例如,您可能希望使用 ¨Ch 和 ¨Chelp 来打印可用的命令。清单 16 演示了这些功能。
清单 16. 使用较短的选项变体并允许多次调用命令选项
#include <string>
#include <iostream>
#include <boost/program_options.hpp>
using namespace std;
int main (int ac, char* av[])
{
boost::program_options::options_description options("command line options");
options.add_options() ("help,h", "Use -h or --help to list all arguments")
("file", boost::program_options::&#118alue<vector<string> >( ),
"Provide input file name");
boost::program_options::variables_map vmap;
boost::program_options::store(
boost::program_options::parse_command_line(ac, av, options), vmap);
boost::program_options::notify(vmap);
if (vmap.count("help")) {
cout << options << endl;
}
if (vmap.count("file")) {
vector<string> ifiles(vmap["file"].as< vector<string> > ());
vector<string>::iterator vI;
cout << "Number of input files: " << ifiles.size() << endl;
cout << "Input file list: " << endl;
for(vI = ifiles.begin(); vI != ifiles.end(); ++vI)
cout << "\t" << *vI << endl;
} else {
cout << "No file specified\n";
}
return 0;
}
在使用 add_options 来添加命令选项时,较长和较短的选项之间使用逗号进行分隔。请注意,较长的选项 (help) 必须在较短的选项 (h) 之前,代码才能正常工作。与使用单个字符串不同,file 选项现在是使用一个字符串向量来定义的。如果指定了 ¨Cfile 选项多次,则会将在所有指定中收集到的命令选项参数存储在关联的 vector<string> 中。下面是使用不同的参数来多次指定 ¨Ch 和 ¨Cfile 所获得的输出:
[user@/home/user1] ./a.out -h
command line options:
-h [ --help ] Use -h or --help to list all arguments
--file arg Provide input file name
No file specified
[user@/home/user1] ./a.out --file abc --file pqr
Number of input files: 2
Input file list:
abc
pqr
回页首
解析位置选项
带输入参数但是不带命令行选项来调用某个程序是非常普遍的。您预期参数和命令行选项之间自动存在某种神奇关联。这种行为由 boost::program_options 提供支持。
请考虑清单 17。第一个参数转换为 --file=<first parameter>,第二个参数转换为 --do-file=<second parameter>。
清单 17. 将位置参数与命令行选项相关联
#include <string>
#include <iostream>
#include <boost/program_options.hpp>
using namespace std;
int main (int ac, char* av[])
{
boost::program_options::options_description options("command line options");
options.add_options() ("help,h", "Use -h or --help to list all arguments")
("file", boost::program_options::&#118alue<string>(),
"Provide input file name")
("do-file", boost::program_options::&#118alue<string>(),
"Specify commands file");
boost::program_options::variables_map vmap;
boost::program_options::positional_options_description poptd;
poptd.add("file", 1);
poptd.add("do-file", 2);
boost::program_options::store(
boost::program_options::command_line_parser(ac, av).
options(options).positional(poptd).run(), vmap);
boost::program_options::notify(vmap);
if (vmap.count("file")) {
cout << "file&#58 " << vmap["file"].as<string> ( ) << endl;
}
if (vmap.count("do-file")) {
cout << "do-file&#58 " << vmap["do-file"].as<string> ( ) << endl;
}
return 0;
}
下面是输出内容:
[user@/home/user1] ./a.out file1 dofile1
file&#58 file1
do-file&#58 dofile1
清单 15 中使用的某些 API 在清单 17 中已发生更改。清单 17 引入了新的类 positional_options_description。该类的 add 方法(add("command option", N))将位置 N 处的输入参数与命令行选项 "command option" 相关联。因此,./a.out file1 在内部解析为 ./a.out ¨Cfile=file1。另一个区别在于调用 program_options::store 方法的方式。与使用 parse_command_line 例程不同,Boost 库要求您将 command_line_parser 例程与 store 方法结合在一起使用。
请注意,仍然可以使用 ¨Cfile 和 ¨Cdo-file 选项来调用该程序。最后,若要将所有的输入参数与同一个命令行选项相关联,您需要使用值 -1 将该命令行选项添加到 positional_options_description 对象。下面是代码:
…
boost::program_options::positional_options_description poptd;
poptd.add("file", -1);
