2012-08-02 74 views
5

我正在使用Boost Graph和Program Options来建立图形发生器。例如,有两种类型的组件C和W,每种都有一个源,一个接收器和一些额外的参数来指定它们之间的拓扑。我希望能够按照命令行参数顺序提供的顺序将它们缝合在一起。如何使用Boost程序选项提取已解析选项的序列?

例如:

./bin/make_graph -c4,5,1 -w3,3 -c3,1,2 

应该创建一个曲线图类似于以下:

C -- W -- C 

但:

./bin/make_graph -c4,5,1 -c3,1,2 -w3,3 

应该创建一个曲线图类似于以下:

C -- C -- W 

使用boost :: program_options,我无法确定如何提取确切的顺序,因为它将相同string_key的选项“合成”为value_type == vector的地图(在我的情况下)。

通过遍历地图,订单将丢失。有没有办法不重复解析,但有一个函数调用(也许是一个回调)每次解析一个选项?我找不到这方面的文件。还有其他建议吗?

说服你,我不是做这件事,这是我到目前为止有:

namespace bpo = boost::program_options; 
    std::vector<std::string> args_cat, args_grid, args_web; 
    bpo::options_description desc("Program options:"); 
    desc.add_options() 
      .operator()("help,h","Displays this help message.") 
      .operator()("caterpillar,c",bpo::value< std::vector<std::string> >(&args_cat)->default_value(std::vector<std::string>(1,"4,7,2"), "4,7,2"),"Caterpillar tree with 3 parameters") 
      .operator()("grid,g",bpo::value< std::vector<std::string> >(&args_grid)->default_value(std::vector<std::string>(1,"3,4"), "3,4"),"Rectangular grid with 2 parameters") 
      .operator()("web,w",bpo::value< std::vector<std::string> >(&args_web)->default_value(std::vector<std::string>(1,"3,4"), "3,4"),"Web with 2 parameters") 
      ; 
    bpo::variables_map ops; 
    bpo::store(bpo::parse_command_line(argc,argv,desc),ops); 
    bpo::notify(ops); 
    if((argc < 2) || (ops.count("help"))) { 
     std::cout << desc << std::endl; 
     return; 
    } 
    //TODO: remove the following scope block after testing 
    { 
     typedef bpo::variables_map::iterator OptionsIterator; 
     OptionsIterator it = ops.options.begin(), it_end = ops.options.end(); 
     while(it != it_end) { 
      std::cout << it->first << ": "; 
      BOOST_FOREACH(std::string value, it->second) { 
       std::cout << value << " "; 
      } 
      std::cout << std::endl; 
      ++it; 
     } 
     return; 
    } 

我意识到,我也可以包括类型作为参数和平凡解决这个问题,比如:

./bin/make_graph --component c,4,5,1 --component w,3,3 --component c,3,1,2 

但要搬进来编写解析器/验证自己的方向(即使不使用升压程序选项可能):

./bin/make_graph --custom c,4,5,1,w,3,3,c,3,1,2 
./bin/make_graph c,4,5,1,w,3,3,c,3,1,2 

你会如何推荐我以优雅的方式做到这一点?

在此先感谢! PS:我已经在发布之前在SO上搜索过“[boost] +顺序程序选项”和“[boost-program-options] +顺序”(及其变体),所以如果发生这种情况,我很抱歉。原来是重复的。

回答

2

如何:

./bin/make_graph c,4,5,1 c,3,1,2 w,3,3 

"c,4,5,1""c,3,1,2""w,3,3"是(在此tutorial就像--input-file位置参数其存储(按顺序)在std::vector<std::string>。然后使用Boost.Tokenizerboost::algorithm::split从每个参数字符串中提取子句。

如果图形可能很复杂,则应考虑使用户可以指定包含图形参数的输入文件。 Boost.Program_Options可以解析使用与命令行选项相同语法的用户config file

+0

谢谢。我同意配置文件。我的动机是避免大量运行的文件I/O。 – scribbleink 2012-08-02 17:16:20

4

自从发布这个问题以来,我做了一些挖掘工作,并有一个“黑客”,可以与我上面提到的现有示例一起使用。

bpo::parsed_options p_ops = bpo::parse_command_line(argc,argv,desc); 
typedef std::vector< bpo::basic_option<char> >::iterator OptionsIterator; 
OptionsIterator it = p_ops.options.begin(), it_end = p_ops.options.end(); 
while(it != it_end) { 
    std::cout << it->string_key << ": "; 
    BOOST_FOREACH(std::string value, it->value) { 
     std::cout << value << " "; 
    } 
    std::cout << std::endl; 
    ++it; 
} 

我之所以称之为hack,是因为它可访问所有参数为字符串,一会要多少从中提取的类型,如BPO :: variables_map与.as<T>()成员函数一样。编辑:它也直接访问选项结构的成员。