我的目标是创建一个可以处理这样的参数的程序:
myProgram -i my_int=20 -s my_string=foo -f my_float=3.1415
进度
我当前的程序可以像这样执行:
myProgram -i 10 12 2 -s foobar anotherstring -f 3.1425 1.5
注意:没有值的名称
忽略多个值
我用boost 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错误
所以我的问题是:
是否可以使用boost库处理
-s my_string=str
之类的程序参数?
答案 0 :(得分: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]