C++ 提振::精神::保气空白
我使用这段代码将“k1=v1;k2=v2;k3=v3;kn=vn”字符串解析为一个映射C++ 提振::精神::保气空白,c++,boost-spirit-qi,C++,Boost Spirit Qi,我使用这段代码将“k1=v1;k2=v2;k3=v3;kn=vn”字符串解析为一个映射 qi::phrase_parse( begin,end, *(*~qi::char_('=') >> '=' >> *~qi::char_(';') >> -qi::lit(';')), qi::ascii::space, dict); 上面的代码将删除空格字符,例如,“some_key=1 2 3”变为some_key->12
qi::phrase_parse(
begin,end,
*(*~qi::char_('=') >> '=' >> *~qi::char_(';') >> -qi::lit(';')),
qi::ascii::space, dict);
上面的代码将删除空格字符,例如,“some_key=1 2 3”变为some_key->123
我不知道如何删除或用第四个参数替换什么:qi::ascii::space
基本上,我希望在按“=”分割后保留原始字符串(键和值)
我没有多少精神方面的经验/知识。学习确实需要投入时间。如果你不想跳绳,只需使用
qi::parse
而不是qi::phrase\u parse
:
qi::parse(
begin,end,
*(*~qi::char_(";=") >> '=' >> *~qi::char_(';') >> -qi::lit(';')),
dict);
但是,您可能确实希望有选择地跳过空白。最简单的方法通常是使用一个通用的skipper,然后标记词素区域(不允许使用skipper的区域):
这本书确实提供了更多关于如何与Qi中的队长合作的技巧/背景
演示时间
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <map>
#include <iomanip>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const& input : {
R"()",
R"(foo=bar)",
R"(foo=bar;)",
R"( foo = bar ; )",
R"( foo = bar ;
foo
= qux; baz =
quux
corge grault
thud
; x=)",
// failing:
R"(;foo = bar;)",
})
{
std::cout << "-------------------------\n";
auto f=begin(input), l=end(input);
std::multimap<std::string, std::string> dict;
bool ok = qi::phrase_parse(f, l,
(qi::lexeme[+(qi::graph - '=' - ';')]
>> '='
>> qi::lexeme[*~qi::char_(';')]
) % ';',
qi::space,
dict);
if (ok) {
std::cout << "Parsed " << dict.size() << " elements:\n";
for (auto& [k,v]: dict) {
std::cout << " - " << std::quoted(k) << " -> " << std::quoted(v) << "\n";
}
} else {
std::cout << "Parse failed\n";
}
if (f!=l) {
std::cout << "Remaining input: " << std::quoted(std::string(f,l)) << "\n";
}
}
}
如果您不需要跳过,只需使用
qi::parse
而不是qi::phrase\u parse
:
qi::parse(
begin,end,
*(*~qi::char_(";=") >> '=' >> *~qi::char_(';') >> -qi::lit(';')),
dict);
但是,您可能确实希望有选择地跳过空白。最简单的方法通常是使用一个通用的skipper,然后标记词素区域(不允许使用skipper的区域):
这本书确实提供了更多关于如何与Qi中的队长合作的技巧/背景
演示时间
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <map>
#include <iomanip>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const& input : {
R"()",
R"(foo=bar)",
R"(foo=bar;)",
R"( foo = bar ; )",
R"( foo = bar ;
foo
= qux; baz =
quux
corge grault
thud
; x=)",
// failing:
R"(;foo = bar;)",
})
{
std::cout << "-------------------------\n";
auto f=begin(input), l=end(input);
std::multimap<std::string, std::string> dict;
bool ok = qi::phrase_parse(f, l,
(qi::lexeme[+(qi::graph - '=' - ';')]
>> '='
>> qi::lexeme[*~qi::char_(';')]
) % ';',
qi::space,
dict);
if (ok) {
std::cout << "Parsed " << dict.size() << " elements:\n";
for (auto& [k,v]: dict) {
std::cout << " - " << std::quoted(k) << " -> " << std::quoted(v) << "\n";
}
} else {
std::cout << "Parse failed\n";
}
if (f!=l) {
std::cout << "Remaining input: " << std::quoted(std::string(f,l)) << "\n";
}
}
}
这回答了你的问题吗?这回答了你的问题吗?谢谢你的详细回答。这真的很好。我真的不知道这个表达式构造,我也不会,除非我从一开始就开始阅读spirit教程。但我明白它的作用。从我所看到的,对于键,左键和右键的前导空格被删除。对于VAL,删除左前导,保留所有其他(中间、右侧)。我会用它来解决问题。这比使用parse()更有意义。如何调整表达式以同时跳过前导和尾随空格字符?我认为这是有道理的,只在值字符串中保留空格。这感觉有点像作弊,但可能是实现这一点最优雅的方法,利用skipper本身:。谢谢sehe。为什么感觉像作弊?因为
qi::raw[]
返回的行输入可能并不总是您想要的(例如,支持字符转义)。请参阅,谢谢你的详细回答。这真的很好。我真的不知道这个表达式构造,我也不会,除非我从一开始就开始阅读spirit教程。但我明白它的作用。从我所看到的,对于键,左键和右键的前导空格被删除。对于VAL,删除左前导,保留所有其他(中间、右侧)。我会用它来解决问题。这比使用parse()更有意义。如何调整表达式以同时跳过前导和尾随空格字符?我认为这是有道理的,只在值字符串中保留空格。这感觉有点像作弊,但可能是实现这一点最优雅的方法,利用skipper本身:。谢谢sehe。为什么感觉像作弊?因为qi::raw[]
返回的行输入可能并不总是您想要的(例如,支持字符转义)。见例。