【问题标题】:boost program options name for values值的提升程序选项名称
【发布时间】:2015-09-03 13:21:48
【问题描述】:

我的目标是创建一个可以处理如下参数的程序:

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&lt;std::string, std::vector&lt;float&gt; &gt;
但这给了我一个编译错误

所以我的问题是:

是否可以使用 boost 库处理像 -s my_string=str 这样的程序参数?

【问题讨论】:

  • 你尝试过类似-s "my_string=str"的方法吗?
  • @Jepessen 那么我需要将"my_string=str" 拆分为my_stringstr。可能,但我希望有更好更清洁的解决方案

标签: c++ boost boost-program-options


【解决方案1】:

首先,这个语法让我印象深刻,你可以考虑为它写一个语法。

这使您可以更灵活地添加逻辑/约束,并更直接地解析为您设想的 AST 类型。有关此示例,请参阅此答案:

我找到了一种相对简单的方法,以防您可以将临时数据类型更改为 std::vector&lt;std::pair&lt;std::string, T&gt; &gt;

由于使用lexical_cast&lt;&gt; 进行转换,您可以读取任何可输入流的值类型。让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]

【讨论】:

  • 看起来很不错...我今天会试试 :)
猜你喜欢
  • 1970-01-01
  • 2012-07-02
  • 1970-01-01
  • 2018-01-20
  • 2018-08-29
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多