2015-09-03 49 views
1

我的目標是創建一個程序,它可以處理這樣的論點:提升程序選項值名稱

myProgram -i my_int=20 -s my_string=foo -f my_float=3.1415

進展
我目前PROGRAMM可以這樣執行:

myProgram -i 10 12 2 -s foobar anotherstring -f 3.1425 1.5
注意:這個數值沒有名字
忽略的多重價值

我已經與升壓program_options這樣做:

po::options_description desc("Allowed options"); 
desc.add_options() 
    ("help", "produce help message") 
    ("float,f", po::value< std::vector<float> >()->multitoken(), "add a float to the map") 
    ("int,i", po::value< std::vector<int> >()->multitoken(),"add a int to the map") 
    ("string,s", po::value< std::vector<std::string> >()->multitoken(),"add a string to the map") 
    ; 

我已經試過

我試圖給po::value此類型:
std::pair<std::string, std::vector<float> >
但這給了我一個complie錯誤

所以我的問題是:

是有可能處理程序的參數一樣-s my_string=str與升壓庫或不?

+0

你嘗試像'-s 「my_string = STR」'? – Jepessen

+0

@Jepessen那麼我需要將my_string = str分割爲my_string和str。可能的,但我希望有一個更好,更乾淨的解決方案 – YvesHendseth

回答

1

首先,這個語法引起我更多的參與,你可以考慮爲它寫一個語法。

這可以讓您更靈活地添加邏輯/約束條件,並且可以更直接地解析您想要的AST類型。對於這樣的一個例子中看到這樣的回答:

我發現的情況下,一個相對簡單的方式,您可以臨時數據類型更改爲std::vector<std::pair<std::string, T> >代替。

由於使用lexical_cast<>發生轉換,您可以讀取任何可以輸入流式傳輸的值類型。讓我們std::pair輸入流化:

namespace std { 
    template <typename V> static inline std::istream& operator>>(std::istream& is, std::pair<std::string, V>& into) { 
     char ch; 
     while (is >> ch && ch!='=') into.first += ch; 
     return is >> into.second; 
    } 
} 

現在,你可以做的說明:

desc.add_options() 
    ("help", "produce help message") 
    ("float,f", po::value<Floats>()->multitoken(), "add a float to the map") 
    ("int,i", po::value<Ints>()->multitoken(), "add a int to the map") 
    ("string,s", po::value<Strings>()->multitoken(), "add a string to the map") 
    ; 

讓我們分析您的樣品命令行

po::variables_map vm; 
po::store(po::parse_command_line(argc, argv, desc, po::command_line_style::default_style), vm); 
po::notify(vm); 

和印刷解析的結果:

po::variables_map vm; 
po::store(po::parse_command_line(argc, argv, desc, po::command_line_style::default_style), vm); 
po::notify(vm); 

std::cout << "Floats:"; for (auto p : vm["float"].as<Floats>()) std::cout << " ['" << p.first << "' -> " << p.second << "]"; 
std::cout << "\nInts:"; for (auto p : vm["int"].as<Ints>())  std::cout << " ['" << p.first << "' -> " << p.second << "]"; 
std::cout << "\nStrings:"; for (auto p : vm["string"].as<Strings>()) std::cout << " ['" << p.first << "' -> " << p.second << "]"; 

Live On Coliru

#include <boost/program_options.hpp> 
#include <boost/program_options/cmdline.hpp> 
#include <boost/any.hpp> 
#include <vector> 
#include <iostream> 

namespace po = boost::program_options; 

using Floats = std::vector<std::pair<std::string, float>>; 
using Ints = std::vector<std::pair<std::string, int>>; 
using Strings = std::vector<std::pair<std::string, std::string>>; 

namespace std { 
    template <typename V> static inline std::istream& operator>>(std::istream& is, std::pair<std::string, V>& into) { 
     char ch; 
     while (is >> ch && ch!='=') into.first += ch; 
     return is >> into.second; 
    } 
} 

int main(int argc, char** argv) { 

    po::options_description desc("Allowed options"); 

    desc.add_options() 
     ("help", "produce help message") 
     ("float,f", po::value<Floats>()->multitoken(), "add a float to the map") 
     ("int,i", po::value<Ints>()->multitoken(), "add a int to the map") 
     ("string,s", po::value<Strings>()->multitoken(), "add a string to the map") 
     ; 


    po::variables_map vm; 
    po::store(po::parse_command_line(argc, argv, desc, po::command_line_style::default_style), vm); 
    po::notify(vm); 

    std::cout << "Floats:"; for (auto p : vm["float"].as<Floats>()) std::cout << " ['" << p.first << "' -> " << p.second << "]"; 
    std::cout << "\nInts:"; for (auto p : vm["int"].as<Ints>())  std::cout << " ['" << p.first << "' -> " << p.second << "]"; 
    std::cout << "\nStrings:"; for (auto p : vm["string"].as<Strings>()) std::cout << " ['" << p.first << "' -> " << p.second << "]"; 
} 

打印:

Floats: ['my_float' -> 3.1415] 
Ints: ['my_int' -> 20] 
Strings: ['my_string' -> foo] 
+0

看起來很不錯...我今天會嘗試:) – YvesHendseth