我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++BoostSpirit入门教程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++BoostSpirit入门教程

一、Boost.Spirit库介绍

本章介绍库 Boost.Spirit。 Boost.Spirit 用于开发文本格式的解析器。例如,您可以使用 Boost.Spirit 开发解析器来加载配置文件。 Boost.Spirit 也可以用于二进制格式,尽管它在这方面的用处有限。

Boost.Spirit 简化了解析器的开发,因为格式是用规则描述的。规则定义格式的外观——其余的由 Boost.Spirit 完成。您可以将 Boost.Spirit 与正则表达式进行比较,因为它可以让您处理复杂的过程——正则表达式的模式搜索和 Boost.Spirit 的解析——而无需编写代码来实现该过程。

Boost.Spirit 期望使用解析表达式语法 (PEG) 来描述规则。 PEG 与扩展巴库斯-瑙尔形式 (EBNF) 有关。即使您不熟悉这些语言,本章中的示例也足以帮助您入门。

Boost.Spirit 有两个版本。第一个版本称为 Spirit.Classic。这个版本不应该再使用了。当前版本是 2.5.2。这是本章介绍的版本。

从 2.x 版本开始,Boost.Spirit 可用于生成生成器和解析器。解析器读取文本格式,生成器编写它们。 Boost.Spirit 中用于开发解析器的组件称为 Spirit.Qi。 Spirit.Karma 是用于开发生成器的组件。命名空间被相应地划分:用于开发解析器的类和函数可以在 boost::spirit::qi 中找到,用于开发生成器的类和函数可以在 boost::spirit::karma 中找到。

除了 Spirit.Qi 和 Spirit.Karma,该库还包含一个名为 Spirit.Lex 的组件,可用于开发词法分析器。

本章的重点是开发解析器。示例主要使用来自 boost::spirit 和 boost::spirit::qi 的类和函数。对于这些类和函数,包含头文件 boost/spirit/include/qi.hpp 就足够了。

如果您不想包含像 boost/spirit/include/qi.hpp 这样的主头文件,您可以单独包含来自 boost/spirit/include/ 的头文件。仅包含此目录中的头文件很重要。 boost/spirit/include/ 是用户界面。其他目录中的头文件可以在新的库版本中更改。

二、boost::spirit::qi::parse()解析格式

Boost.Spirit 提供 boost::spirit::qi::parse() 和 boost::spirit::qi::phrase_parse() 来解析格式。

Example11.1.Usingboost::spirit::qi::parse()

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::parse(it, s.end(), ascii::digit);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

例 11.1 引入了 boost::spirit::qi::parse()。这个函数需要两个被解析字符串的迭代器和一个解析器。该示例使用由 Boost.Spirit 提供的解析器 boost::spirit::ascii::digit。这是几个字符分类解析器之一。这些解析器测试字符是否属于某个类。 boost::spirit::ascii::digit 测试字符是否为 0 到 9 之间的数字。

该示例传递从 std::cin 读取的字符串的迭代器。请注意,开始迭代器没有直接传递给 boost::spirit::qi::parse()。它存储在变量 it 中,然后传递给 boost::spirit::qi::parse()。这样做是因为 boost::spirit::qi::parse() 可能会修改迭代器。

如果您键入一个数字,然后按 Enter,该示例将显示 true。如果您输入两位数然后回车,则输出将为真,后跟第二位数字。如果你输入一个字母然后回车,输出将是假的,然后是字母。

例 11.1 中使用的解析器 boost::spirit::ascii::digit 只测试一个字符以查看它是否是数字。如果第一个字符是数字,boost::spirit::qi::parse() 返回 true,否则返回 false。 boost::spirit::qi::parse() 的返回值表示解析器是否成功。

boost::spirit::qi::parse() 如果您输入多个数字,也会返回 true。因为解析器 boost::spirit::ascii::digit 只测试第一个字符,所以它会在这样的字符串上成功。第一个之后的所有数字都将被忽略。

为了让您确定可以成功解析多少字符串,boost::spirit::qi::parse() 更改了它的迭代器。调用 boost::spirit::qi::parse() 后,它指向最后一个解析成功后的字符。如果输入多个数字,则指第二个数字。如果您只输入一位数字,则它等于 s 的结束迭代器。如果你输入一个字母,它指的是那个字母。

boost::spirit::qi::parse() 不会忽略空格。如果运行示例 11.1 并输入空格,则会显示 false。 boost::spirit::qi::parse() 测试第一个输入的字符,即使该字符是空格。如果你想忽略空格,使用 boost::spirit::qi::phrase_parse() 而不是 boost::spirit::qi::parse()。

Example11.2.Usingboost::spirit::qi::phrase_parse()

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

boost::spirit::qi::phrase_parse() 的工作方式与 boost::spirit::qi::parse() 类似,但需要另一个名为 skipper 的参数。船长是应该被忽略的字符的解析器。示例 11.2 使用 boost::spirit::ascii::space,一个字符分类解析器来检测空格,作为船长。

boost::spirit::ascii::space 丢弃空格作为分隔符。如果您开始该示例并输入一个空格后跟一个数字,则显示为 true。与前面的示例不同,解析器 boost::spirit::ascii::digit 不应用于空格,而是应用于不是空格的第一个字符。

请注意,此示例忽略了任意数量的空格。因此,如果您输入多个空格后跟一个数字, boost::spirit::qi::phrase_parse() 将返回 true。

与 boost::spirit::qi::parse() 一样,boost::spirit::qi::phrase_parse() 修改了作为第一个参数传递的迭代器。这样,您就知道解析器能够成功工作到字符串多远。示例 11.2 跳过成功解析字符后出现的空格。如果您输入一个数字后跟一个空格,然后是一个字母,迭代器将引用该字母,而不是它前面的空格。如果您希望迭代器引用空间,请将 boost::spirit::qi::skip_flag::dont_postskip 作为另一个参数传递给 boost::spirit::qi::phrase_parse()。

Example11.3.phrase_parse()withboost::spirit::qi::skip_flag::dont_postskip

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.3 将 boost::spirit::qi::skip_flag::dont_postskip 传递给 boost::spirit::qi::phrase_parse() 以告诉解析器不要跳过在成功解析数字之后但在第一个不成功数字之前出现的空格解析的字符。如果你输入一个数字后跟一个空格再跟一个字母,它指的是调用 boost::spirit::qi::phrase_parse() 之后的空格。

标志 boost::spirit::qi::skip_flag::postskip 是默认值,如果 boost::spirit::qi::skip_flag::dont_postskip 和 boost::spirit::qi::skip_flag 都不是,则使用该标志: :postskip 已指定。

Example11.4.boost::spirit::qi::phrase_parse()with wide strings

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::wstring s;
  std::getline(std::wcin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::wcout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::wcout << std::wstring{it, s.end()} << '\n';
}

boost::spirit::qi::parse() 和 boost::spirit::qi::phrase_parse() 接受迭代器到一个宽字符串。示例 11.4 与前面的示例类似,只是使用了宽字符串。

Boost.Spirit 还支持来自 C++11 标准库的字符串类型 std::u16string 和 std::u32string。

三、解析器

本节说明如何定义解析器。您通常从 Boost.Spirit 访问现有的解析器——例如 boost::spirit::ascii::digit 或 boost::spirit::ascii::space。通过组合解析器,您可以解析更复杂的格式。该过程类似于定义正则表达式,它们也是由基本构建块构建的。

Example11.5.A parser for two consecutive digits

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit >> ascii::digit,
    ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.5 测试是否输入了两个数字。 boost::spirit::qi::phrase_parse() 仅在两个数字连续时才返回 true。空格被忽略。

与前面的示例一样, boost::spirit::ascii::digit 用于识别数字。因为 boost::spirit::ascii::digit 只测试一个字符,所以解析器使用了两次来测试两位数字的输入。要连续两次使用 boost::spirit::ascii::digit,必须使用运算符。 Boost.Spirit 为解析器重载 operator>>。使用 ascii::digit >> ascii::digit 创建了一个解析器,用于测试字符串是否包含两个数字。

如果您运行该示例并输入两位数,则会显示 true。如果您只输入一位数字,该示例将显示为 false。

请注意,如果您在两位数之间输入空格,该示例也会显示 true。无论在解析器中使用运算符 operator>> 的任何位置,都允许使用被船长忽略的字符。因为示例 11.5 使用 boost::spirit::ascii::space 作为跳过符,所以您可以在两个数字之间输入任意数量的空格。

如果您希望解析器仅在两个数字之间没有空格的情况下才接受它们,请使用 boost::spirit::qi::parse() 或指令 boost::spirit::qi::lexeme。

Example11.6.Parsing character by character withboost::spirit::qi::lexeme

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(),
    qi::lexeme[ascii::digit >> ascii::digit], ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.6 使用解析器 qi::lexeme[ascii::digit >> ascii::digit]。现在, boost::spirit::qi::phrase_parse() 仅在数字之间没有空格时才返回 true。

boost::spirit::qi::lexeme 是可以改变解析器行为的几个指令之一。如果你想禁止在使用 operator>> 时会被船长忽略的字符,你可以使用 boost::spirit::qi::lexeme。

Example11.7.Boost.Spirit rules similar to regular expressions

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), +ascii::digit, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

例 11.7 用 +ascii::digit 定义了一个解析器,它至少需要一个数字。这种语法,特别是加号 (+),类似于正则表达式中使用的语法。加号标识一个字符或字符组,该字符或字符组预计在字符串中至少出现一次。如果您启动示例并输入至少一位数字,则会显示 true。数字是否由空格分隔并不重要。如果解析器应该只接受没有空格的数字,请再次使用 boost::spirit::qi::lexeme。

Example11.8.Numeric parsers

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), qi::int_, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.8 需要一个整数。 boost::spirit::qi::int_ 是一个可以识别正整数和负整数的数值解析器。与 boost::spirit::ascii::digit 不同,boost::spirit::qi::int_ 可以将多个字符(例如 +1 或 -23)识别为整数。

Boost.Spirit 提供了额外的逻辑解析器。 boost::spirit::qi::float_、boost::spirit::qi::double_ 和 boost::spirit::qi::bool_ 是可以读取浮点数和布尔值的数值解析器。使用 boost::spirit::qi::eol,您可以测试行尾字符。 boost::spirit::qi::byte_ 和 boost::spirit::qi::word 可用于读取一个或两个字节。 boost::spirit::qi::word 和其他二进制解析器识别平台的字节顺序并进行相应的解析。如果要基于特定的字节序进行解析,无论平台如何,都可以使用 boost::spirit::qi::little_word 和 boost::spirit::qi::big_word 等解析器。

到此这篇关于C++ Boost Spirit入门教程的文章就介绍到这了,更多相关C++ Boost Spirit内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++BoostSpirit入门教程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++BoostSpirit入门教程

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-16

C++教程(超长最全入门)

这篇文章主要介绍了C++教程(超长最全),需要的朋友可以参考下
2023-05-18

Python爬虫入门教程 1-100 C

简介你好,当你打开这个文档的时候,我知道,你想要的是什么! Python爬虫,如何快速的学会Python爬虫,是你最期待的事情,可是这个事情应该没有想象中的那么容易,况且你的编程底子还不一定好,这套课程,没有你想要的Python基础,没有变
2023-01-30

HTML5 入门教程

本篇内容主要讲解“HTML5 入门教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“HTML5 入门教程”吧!JavaScript作为一种弱类型语言,最大的特点就是动态类型。也就是说不用提前声明
2023-06-09

maven3 入门教程

Maven库:http://repo2.maven.org/maven2/Maven依赖查询:http://mvnrepository.com/Maven常用命令: 1. 创建Maven的普通java项目:    mvn archetype
2023-01-31

IPv6入门教程

本篇文章主要从基础概念、IPv6的相关网络工具、关于移动应用在IPv6和IPv4网络环境中自动降级机制的研究等三个方面介绍了IPv6的入门教程。前言众所周知,32位的IPv4地址已经基本耗尽(这里的耗尽只是说的分配完了,实际上有相当一部分并
2023-06-03

node.js入门教程

Node是个啥?写个东西还是尽量面面俱到吧,所以有关基本概念的东西我也从网上选择性的拿了些下来,有些地方针对自己的理解有所改动,对这些概念性的东西有过了解的可选择跳过这段。1.Node 是一个服务器端 JavaScript 解释器,可是真的
2022-06-04

pgpool-II 入门教程

欢迎阅读 pgpool-II 入门教程。从本教程中,你将学会如何安装,设置 pgpool-II 以及使用 pgpool-II 运行并行查询和复制。我们假设你已经知道PostgreSQL的基础操作,所以如果有必要,请先参考 PostgreSQL 的文档。
pgpool-II 入门教程
2016-11-03

Android RecylerView入门教程

今年Google I/0大会,Google开放了两个全新的视图:RecyclerView和CardView。这篇文章会提供关于RecylerView的简介。 RecylerView作为support-library发布出来,这对开发者来说绝
2022-06-06

Python入门教程(二)

今天讲编程思维。  可能这对初次接触编程的人有用——我不是不想切入正题,我只是想强调根本没什么正题,我可能在其他文章里提过这一点。“编程语言就是语法糖”,可能你不知道什么是语法糖,但是知道的人也未必认同我。我不保证你们能听懂……python
2023-01-31

Python NLP 入门教程

本文简要介绍Python自然语言处理(NLP),使用Python的NLTK库。NLTK是Python的自然语言处理工具包,在NLP领域中,最常使用的一个Python库。什么是NLP?简单来说,自然语言处理(NLP)就是开发能够理解人类语言的
2023-01-31

linux入门教程(3)

(文:flynng)  3.4 进程管理  Linux是一个多用户多任务的操作系统。多用户是指多个用户可以在同一时间使用计算机系统;多任务是指Linux可以同时执行几个任务,它可以在还未执行完一个任务时又执行另一项任务。  在Linux系统
2023-01-31

python jupyter入门教程

目录1.jupyter2.jupyter基础操作2.1windows更新pip库2.2jupyter安装2.3初次启动jupyter2.4设置密码进入jupyter3.创建一个jupyter文本4.jupyter文本的用法4.1保存和下载文
2022-06-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录