我需要使用 boost::spirit::qi 解析如下字符串:
str1
str1_str
str1_str/str
str1_str/str/*
即,需要解析由 '/'
分隔的标识符字符串, 如果最后一个符号是 '/'
,那么 '*'
应该在之后。
我写了下面的代码来完成工作:
#include <boost/spirit/include/qi.hpp>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace client
{
namespace qi = boost::spirit::qi;
template <typename Iterator>
bool parseName(Iterator first, Iterator last, std::string& name)
{
std::vector<std::string> vec;
char c;
boost::optional<std::string> o;
std::string spaces;
std::string spaces1;
bool r = qi::phrase_parse(first, last,
(
qi::alnum >> *(+qi::alnum | qi::string("_") | (qi::string("/") >> +qi::alnum)) >> -qi::string("/*")
)
,
qi::blank, c, vec, o);
if (first != last) // fail if we did not get a full match
return false;
name = c + boost::algorithm::join(vec, "");
if (o) {
name += *o;
}
return r;
}
}
int main()
{
std::string str;
std::getline(std::cin, str);
std::string name;
if (client::parseName(str.begin(), str.end(), name)) {
std::cout << "parsed:\n";
std::cout << "name: " << name << std::endl;
} else {
std::cout << "not oook\n" ;
}
return 0;
}
我想知道为什么 qi::phrase_parse
无法将所有匹配项写入一个属性 string
或至少 vector<string>
?或者我做错了什么。
如何修改上面的代码以将匹配的输出写入一个字符串而不传递 char
和 boost::optional<std::string>
属性?
提前致谢!
最佳答案
我不太清楚您要实现的目标。
如果我假设我能想到的最简单的事情,这就是我的看法:
static const qi::rule<Iterator, std::string()> segment = qi::alnum >> *(qi::alnum|qi::char_('_'));
std::vector<std::string> segments;
bool have_wildcard;
bool r = qi::parse(
first, last,
segment % '/' >> -qi::matches [ "/*" ],
segments,
have_wildcard);
现在,我创建了一个小测试程序,请注意,我加入了 ::
作为分隔符,因此更容易看到结果:
r &= (first == last); // fail if we did not get a full match
if (r) {
if (have_wildcard)
segments.emplace_back("*");
name = boost::algorithm::join(segments, "::");
}
演示
#include <boost/spirit/include/qi.hpp>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace client {
namespace qi = boost::spirit::qi;
template <typename Iterator>
bool parseName(Iterator first, Iterator last, std::string& name) {
static const qi::rule<Iterator, std::string()> segment = qi::alnum >> *(qi::alnum|qi::char_('_'));
std::vector<std::string> segments;
bool have_wildcard;
bool r = qi::parse(
first, last,
segment % '/' >> -qi::matches [ "/*" ],
segments,
have_wildcard);
r &= (first == last); // fail if we did not get a full match
if (r) {
if (have_wildcard)
segments.emplace_back("*");
name = boost::algorithm::join(segments, "::");
}
return r;
}
}
int main()
{
//std::string str = "";
//std::getline(std::cin, str);
for (std::string const str : {
"str1",
"str1_str",
"str1_str/str",
"str1_str/str/*",
})
{
std::string name;
std::cout << "\n-------------------\ninput: '" << str << "'\n";
if (client::parseName(str.begin(), str.end(), name)) {
std::cout << "name: " << name << std::endl;
} else {
std::cout << "not oook\n";
}
}
}
打印
-------------------
input: 'str1'
name: str1
-------------------
input: 'str1_str'
name: str1_str
-------------------
input: 'str1_str/str'
name: str1_str::str
-------------------
input: 'str1_str/str/*'
name: str1_str::str::*
关于c++ - 使用 boost::spirit::qi 解析包含特定字符的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31109530/