2012-08-02 68 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>()成員函數一樣。編輯:它也直接訪問選項結構的成員。