Boost 库中的实用工具类使用入门(3)
作者:asio转载自:asio分享学习快乐更新时间:2009-8-2

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);