Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用boost spirit从括号中提取字符串_C++_Boost_Boost Spirit_Boost Spirit Qi - Fatal编程技术网

C++ 使用boost spirit从括号中提取字符串

C++ 使用boost spirit从括号中提取字符串,c++,boost,boost-spirit,boost-spirit-qi,C++,Boost,Boost Spirit,Boost Spirit Qi,我有以下字符串: %%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C) 我想解析它并存储/提取括号中的90pv-RKSJ-UCS2C字符串 我的规则如下: std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)"; std::string strStartTokenRecur; std::string token_intRecur; bool bP

我有以下字符串:

%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)
我想解析它并存储/提取括号中的
90pv-RKSJ-UCS2C
字符串

我的规则如下:

std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
std::string strStartTokenRecur;
std::string token_intRecur;
bool bParsedLine1 = qi::phrase_parse(strLinesRecur.begin(), strLinesRecur.end(), +char_>>+char_,':', token_intRecur, strStartTokenRecur);

看起来你认为skipper是一个分隔符。恰恰相反

在这种罕见的情况下,我想我更喜欢正则表达式。但是,既然你问了,这就是你的精神:

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main() {
    std::string const line = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";

    auto first = line.begin(), last = line.end();

    std::string label, token;
    bool ok = qi::phrase_parse(
            first, last, 
            qi::lexeme [ "%%" >> +~qi::char_(":") ] >> ':' >> qi::lexeme["CMap"] >> '(' >> qi::lexeme[+~qi::char_(')')] >> ')',
            qi::space,
            label, token);

    if (ok)
        std::cout << "Parse success: label='" << label << "', token='" << token << "'\n";
    else
        std::cout << "Parse failed\n";

    if (first!=last)
        std::cout << "Remaining unparsed input: '" << std::string(first, last) << "'\n";
}

好的,假设我们使用和别名名称空间指令得到以下

using namespace boost::spirit::qi;
namespace phx = boost::phoenix;
给定字符串:

std::string strLinesRecur = "%%DocumentNeededResources: CMap (90pv-RKSJ-UCS2C)";
我们想将括号内的“代码”提取到
res

std::string res;
一种方法是使用
boost::phoenix::ref
作为语义动作。 因此,给出如下代码语法:

using boost::spirit::ascii::alnum;
auto code = copy(+(alnum | char_('-')));
(这与正则表达式中的
[a-zA-Z\-]
类似)

我们可以为整个字符串创建自己的语法:

using boost::spirit::ascii::alpha;
auto grammar = copy(
    (char_('%') >> char_('%') >> +alpha >> char_(':')) 
        >> +alpha >> char_('(') >> as_string[lexeme[code]][phx::ref(res) = _1] >> char_(')'));
它解析以两个
%
开头的任何内容,后跟一些字母字符和一个
,然后在括号内后跟一些“code”

这一点的关键是
作为字符串[lexeme[code]][phx::ref(res)=\u1]
。如果我们把它分解:
lexeme[code]
只是说把解析的
code
当作一个原子单元,
作为字符串
“返回”结果作为
std::string
(与
std::vector
)和
[phx::ref(res)=\u 1]
使用语义操作将解析的字符串存储到
res(
\u 1
是该语法中第一个匹配项的占位符)

在这种情况下,以下调用将跳过空格:

using boost::spirit::ascii::blank;
phrase_parse(begin(strLinesRecur), end(strLinesRecur), grammar, blank);

当然,这只是一个适合字符串的语法示例


注意:
copy
指的是
qi::copy
,它是一种能够存储语法片段的方法,比如在对象
code
grammar
中。如果不这样做,
auto
的使用将失败(可能有分段错误).

Hmm我不知道
qi::copy
o.o我总是使用
boost::proto::deep\u copy
boost\u SPIRIT\u AUTO
(这也有在c++03中工作的好处)。这里我根据您的想法为您提供我的(非常:)简化版:谢谢各位上帝保佑您:)
using boost::spirit::ascii::blank;
phrase_parse(begin(strLinesRecur), end(strLinesRecur), grammar, blank);