c++ - 使用 boost::spirit::qi 解析包含特定字符的字符串

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

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

如何修改上面的代码以将匹配的输出写入一个字符串而不传递 charboost::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, "::");
}

演示

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

关于c++ - 使用 boost::spirit::qi 解析包含特定字符的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31109530/

相关文章:

c++ - TR1 共享阵列

c++ - 在语义 Action 中 boost spirit 改变变量值

C++ spirit boost : Making a input iterator into a forward iterator

c++ - 在 C++ 中使用 ifstream 逐行读取文件

c++ - STL容器的只读操作

android - 来自 Android JNI 中任何线程的 FindClass

c++ - QImage::setPixel: 坐标超出范围

c++ - boost microsec_time_clock.hpp 警告 C4244

C++如何为 float 设置固定的小数精度

c++ - boost::spirit::qi 差异解析器行为