简体   繁体   English

增强精神分析

[英]Boost spirit parsing

I'm trying to take a string and then retrieve the required elements from it. 我正在尝试取一个字符串,然后从中检索所需的元素。 At the moment, I can't seem to find a way of doing it because the input string that will change from time to time, although the elements won't. 目前,我似乎无法找到一种方法,因为输入字符串会不时改变,尽管元素不会。

My code so far is below. 到目前为止,我的代码如下。 What I want to do is extract the '.V/' from the string when parsed. 我想做的是在解析时从字符串中提取'.V/'

My code so far below will work, but I need it to be more generic as there are many elements within the inputted string 到目前为止我的代码将起作用,但我需要它更通用,因为输入字符串中有许多元素

  • ie

     .V/ER/12/FRG/45S/16JAN .E/45/SHAM/CAMP/2 

    and I would need to retrieve .V/ and .E/ 我需要检索.V/.E/

std::vector<std::string>elements;
std::string input = ".V/ER/12/FRG/45S/16JAN ";

bool result = qi::parse(input.begin(),input.end(),
        *(*(qi::char_ - " /ER/12/FRG/45S/16JAN\n") >> " /ER/12/FRG/45S/16JAN\n"),
        elements
        );  

I'd really suggest using a regular expression (boost regex or std::regex) for this job. 我真的建议为该工作使用正则表达式(增强正则表达式或std :: regex)。

The regular expression would probably look like 正则表达式可能看起来像

std::regex re("^(\\.[EV]/).*?$"); // the first submatch is the part you are looking for

Here is a bit of spirit in case you really need it: 如果您真的需要它,这里有点精神:

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;

typedef std::string::const_iterator It;

int main()
{
    std::vector<std::string>elements;
    std::string input = 
        ".V/ER/12/FRG/45S/16JAN\n"
        ".E/45/SHAM/CAMP/2";

    It first(input.begin()), last(input.end());

    bool ok = qi::parse(first, last,
            (
              '.' > qi::char_("EV") > '/' 
                 >> qi::omit [ *(qi::char_ - qi::eol) ] 
            ) % qi::eol,
            elements);

    if (ok)
    {
        for (int i=0; i<elements.size(); ++i)
            std::cout << elements[i] << std::endl;
    } else
    {
        std::cerr << "Parse failed at '" << std::string(first, last) << std::endl;
    }

}

This will output 这将输出

V
E

If you want to show '.E/' there, there are many ways about it, eg 如果您想在那里显示“ .E /”,有很多方法,例如

bool ok = qi::parse(first, last,
        (
          (qi::char_('.') > qi::char_("EV") > qi::char_('/' )
             >> qi::omit [ *(qi::char_ - qi::eol) ] )
        ) % qi::eol,
        elements);

output: 输出:

.V/
.E/

Bonus 奖金

To show how to include the 'tail' of the line, possibly storing into map: 要显示如何包括线的“尾部”(可能存储到地图中):

#include <map>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
namespace qi = boost::spirit::qi;

typedef std::string::const_iterator It;

int main()
{
    typedef std::map<std::string, std::string> result_t;
    // or use a list to allow duplicate keys:
    // typedef std::list<std::pair<std::string, std::string> > result_t;
    result_t mappings;

    std::string input = 
        ".V/ER/12/FRG/45S/16JAN\n"
        ".E/45/SHAM/CAMP/2";

    It first(input.begin()), last(input.end());

    bool ok = qi::parse(first, last, (
                  qi::raw [ '.' > qi::char_("EV") > '/' ]
                > qi::raw [ *(qi::char_ - qi::eol) ]
            ) % qi::eol,
            mappings);

    if (ok)
    {
        for (result_t::const_iterator it=mappings.begin();
             it!=mappings.end(); ++it)
        {
            std::cout << it->first << " maps to " << it->second << std::endl;
        }
    } else
    {
        std::cerr << "Parse failed at '" << std::string(first, last) << std::endl;
    }

}

would output 会输出

.E/ maps to 45/SHAM/CAMP/2
.V/ maps to ER/12/FRG/45S/16JAN

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM