首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >促进::精神qi::uint_有效数字范围

促进::精神qi::uint_有效数字范围
EN

Stack Overflow用户
提问于 2021-07-09 10:40:15
回答 2查看 66关注 0票数 2

我想解析由CCn组成的字符串,其中包含1 <= n <= 4,或从SERVICEk解析1 <= k <= 63。

有效字符串:"CC1“、"CC2”、"CC3“、"CC4”、"SERVICE1“、"SERVICE2”、.、"SERVICE63“。

我写了下一个表达式:

代码语言:javascript
复制
( '"' >> (qi::raw["CC" >> qi::uint_] | qi::raw["SERVICE" >> qi::uint_]) >> '"' >> qi::eoi)

但是我怎么能限制n和k呢?

在输出中,我需要得到完整的字符串CC1,CC2,.SERVICE63

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-07-09 12:19:47

最简单的方法是使用symbols<>

详细的方法是验证语义动作中的数字。

我的建议是,要么是符号,要么是独立的语义验证与解析(即解析原始数字并在解析后验证AST )。

符号

这可能更灵活、最有效,并且允许您在AST域中进行强类型输入。它避开了语义操作的编译开销和复杂性:促进精神:“语义行为是邪恶的”?

住在Coliru

代码语言:javascript
复制
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;

int main() {
    qi::symbols<char> cc, service;
    cc += "CC1", "CC2", "CC3", "CC4";
    service += "SERVICE1", "SERVICE2", "SERVICE3", "SERVICE4", "SERVICE5",
        "SERVICE6", "SERVICE7", "SERVICE8", "SERVICE9", "SERVICE10",
        "SERVICE11", "SERVICE12", "SERVICE13", "SERVICE14", "SERVICE15",
        "SERVICE16", "SERVICE17", "SERVICE18", "SERVICE19", "SERVICE20",
        "SERVICE21", "SERVICE22", "SERVICE23", "SERVICE24", "SERVICE25",
        "SERVICE26", "SERVICE27", "SERVICE28", "SERVICE29", "SERVICE30",
        "SERVICE31", "SERVICE32", "SERVICE33", "SERVICE34", "SERVICE35",
        "SERVICE36", "SERVICE37", "SERVICE38", "SERVICE39", "SERVICE40",
        "SERVICE41", "SERVICE42", "SERVICE43", "SERVICE44", "SERVICE45",
        "SERVICE46", "SERVICE47", "SERVICE48", "SERVICE49", "SERVICE50",
        "SERVICE51", "SERVICE52", "SERVICE53", "SERVICE54", "SERVICE55",
        "SERVICE56", "SERVICE57", "SERVICE58", "SERVICE59", "SERVICE60",
        "SERVICE61", "SERVICE62", "SERVICE63";

    for (std::string const input : {
             // valid:
             "CC1",
             "CC2",
             "CC3",
             "CC4",
             "SERVICE1",
             "SERVICE2",
             "SERVICE63",
             // invalid:
             "CC0",
             "CC5",
             "SERVICE0",
             "SERVICE64",
         }) {

        bool valid = parse(begin(input), end(input), service|cc);
        std::cout << std::quoted(input) << " -> "
                  << (valid ? "valid" : "invalid") << "\n";
    }
}

打印

代码语言:javascript
复制
"CC1" -> valid
"CC2" -> valid
"CC3" -> valid
"CC4" -> valid
"SERVICE1" -> valid
"SERVICE2" -> valid
"SERVICE63" -> valid
"CC0" -> invalid
"CC5" -> invalid
"SERVICE0" -> invalid
"SERVICE64" -> invalid

奖金:强类型的想法:http://coliru.stacked-crooked.com/a/2cb07d4da9aad39e

语义行为

简而言之:

代码语言:javascript
复制
qi::rule<It, intmax_t(intmax_t min, intmax_t max)> constrained_num =
    qi::uint_[_pass = (_1 >= _r1 && _1 <= _r2)];

qi::rule<It> cc      = "CC" >> constrained_num(1, 4),
             service = "SERVICE" >> constrained_num(1, 63);

住在Coliru

代码语言:javascript
复制
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
using It     = std::string::const_iterator;

int main() {
    using namespace qi::labels;
    qi::rule<It, intmax_t(intmax_t min, intmax_t max)> constrained_num =
        qi::uint_[_pass = (_1 >= _r1 && _1 <= _r2)];

    qi::rule<It> cc      = "CC" >> constrained_num(1, 4),
                 service = "SERVICE" >> constrained_num(1, 63);

    for (std::string const input : {
            // valid:
             "CC1",
             "CC2",
             "CC3",
             "CC4",
             "SERVICE1",
             "SERVICE2",
             "SERVICE63",
             // invalid:
             "CC0",
             "CC5",
             "SERVICE0",
             "SERVICE64",
         }) {

        bool valid = parse(begin(input), end(input), service|cc);
        std::cout << std::quoted(input) << " -> "
                  << (valid ? "valid" : "invalid") << "\n";
    }
}

打印与上面相同

票数 2
EN

Stack Overflow用户

发布于 2021-07-09 12:07:58

要限制uint_范围,可以在语义操作中执行范围检查。例如,它可以作为lambda实现,或者更简洁地作为Boost.Phenix表达式实现。

以下代码将这些数字解析为向量(省略字符串):

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>


int main()
{
    std::string input =  "CC1 CC2 CC3 CC4 SERVICE1 SERVICE2";
    std::vector<unsigned int> out;

    using namespace boost::spirit::qi;
    phrase_parse(
        input.begin(), 
        input.end(), 
        *(lexeme[lit("CC") >> uint_ [ _pass = (_1>=1 && _1<=4) ]] | 
        lexeme[lit("SERVICE") >> uint_ [ _pass = (_1>=1 && _1<=63) ]]), 
        ascii::space, 
        out
    );
    for (auto i : out)
        std::cout << i << std::endl;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68315418

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档