【问题标题】:Parsing string containing specific characters with boost::spirit::qi使用 boost::spirit::qi 解析包含特定字符的字符串
【发布时间】:2023-03-12 15:48:01
【问题描述】:

我需要使用 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&lt;string&gt;?或者我做错了什么。

如何修改上面的代码以将匹配的输出写入一个字符串而不传递 charboost::optional&lt;std::string&gt; 属性?

提前致谢!

【问题讨论】:

    标签: c++ boost boost-spirit boost-spirit-qi


    【解决方案1】:

    我并不完全清楚你想要达到什么目的。

    如果我假设我能想到的最简单的事情,这就是我的看法:

    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, "::");
    }
    

    演示

    Live On Coliru

    #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::*
    

    【讨论】:

      猜你喜欢
      • 2017-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多