gpt4 book ai didi

c++ - 当键不唯一时解析键值对

转载 作者:行者123 更新时间:2023-11-28 04:28:53 25 4
gpt4 key购买 nike

我的输入是多个键值对,例如:

A=1, B=2, C=3, ..., A=4

我想将输入解析为以下类型:

 std::map< char, std::vector< int > > m

相等键的值应附加到 vector 中。所以解析后的输出应该等于:

m['A']={1,4};
m['B']={2};
m['C']={3};

使用“boost::spirit::qi”的最简单解决方案是什么?

最佳答案

这是一种方法:

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <iostream>
#include <utility>
#include <string>
#include <vector>
#include <map>

namespace qi = boost::spirit::qi;
namespace fusion = boost::fusion;

int main()
{
std::string str = "A=1, B=2, C=3, A=4";

std::map< char, std::vector< int > > m;
auto inserter = [&m](fusion::vector< char, int > const& parsed,
qi::unused_type, qi::unused_type)
{
m[fusion::at_c< 0 >(parsed)].push_back(fusion::at_c< 1 >(parsed));
};

auto it = str.begin(), end = str.end();
bool res = qi::phrase_parse(it, end,
((qi::char_ >> '=' >> qi::int_)[inserter]) % ',',
qi::space);

if (res && it == end)
std::cout << "Parsing complete" << std::endl;
else
std::cout << "Parsing incomplete" << std::endl;

for (auto const& elem : m)
{
std::cout << "m['" << elem.first << "'] = {";
for (auto value : elem.second)
std::cout << " " << value;
std::cout << " }" << std::endl;
}

return 0;
}

关于实现的一些评论:

  1. qi::phrase_parse 是一种 Boost.Spirit 算法,它采用一对迭代器、一个解析器和一个跳过解析器,并在迭代器表示的输入上运行解析器。在此过程中,它会更新起始迭代器(本例中为 it),使其在返回时指向已消耗输入的末尾。返回的 res value 指示解析器是否已成功(即可以成功解析使用的输入)。还有其他形式的qi::phrase_parse允许提取属性(就 Boost.Spirit 而言,这是已解析的数据),但我们在这里不使用属性,因为您对生成的容器结构有特殊要求。

  2. 跳过解析器用于跳过主解析器元素之间的输入部分。在这种情况下, qi::space 意味着输入中的任何空白字符都将被忽略,例如"A = 1"和 "A=1"都可以类似地解析。有 qi::parse没有跳过解析器的算法系列,因此需要主解析器处理所有输入而不跳过。

  3. (qi::char_ >> '=' >> qi::int_)主解析器的一部分匹配 single character , 后跟等号字符,然后是 signed integer .等号表示为文字(即它等效于 qi::lit('=') 解析器),这意味着它仅匹配输入但不会产生解析数据。因此,此解析器的结果是一个属性,它是两个元素的序列 - 一个字符和一个整数。

  4. % ','解析器的一部分是 list parser ,它解析由左侧解析器(即上述解析器)描述的任意数量的输入,由右侧解析器描述的片段分隔(即在我们的例子中使用逗号字符)。和以前一样,逗号字符是文字​​解析器,因此它不会产生输出。

  5. [inserter]部分是 semantic action ,这是解析器每次匹配输入字符串的一部分时调用的函数。解析器将其所有已解析的输出作为第一个参数传递给此函数。在我们的例子中,语义 Action 附加到项目符号 #3 中描述的解析器,这意味着传递了一个字符和一个整数的序列。 Boost.Spirit 使用 fusion::vector 传递这些数据。语义 Action 的其他两个参数在本例中没有使用,可以忽略。

  6. inserter这个例子中的函数是一个 lambda 函数,但它可以是任何其他类型的函数对象,包括一个常规函数,一个由 std::bind 生成的函数。等。重要的部分是它具有指定的签名,并且它的第一个参数的类型与解析器的属性兼容,它作为语义操作附加到解析器。因此,如果我们在项目符号 #3 中使用不同的解析器,则必须相应地更改此参数。

  7. fusion::at_c< N >() inserter获得索引 N 处的 vector 元素.它与 std::get< N >() 非常相似当应用于 std::tuple .

关于c++ - 当键不唯一时解析键值对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53504421/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com