C++ Boost Xpressive示例分析使用

发布时间:

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

C++ Boost Xpressive示例分析使用

一、综述

与 Boost.Regex 一样,Boost.Xpressive 提供了使用正则表达式搜索字符串的函数。然而,Boost.Xpressive 使得将正则表达式写成 C++ 代码而不是字符串成为可能。这使得在编译时检查正则表达式是否有效成为可能。

只有 Boost.Regex 被合并到 C++11 中。标准库不支持将正则表达式编写为 C++ 代码。

boost/xpressive/xpressive.hpp 提供对 Boost.Xpressive 中大多数库函数的访问。对于某些函数,必须包含额外的头文件。该库的所有定义都可以在命名空间 boost::xpressive 中找到。

二、应用示例

2.1示例 9.1

boost::xpressive::regex_match 比较字符串

示例 9.1使用 boost::xpressive::regex_match 比较字符串。

#include <boost/xpressive/xpressive.hpp>
#include <string>
#include <iostream>
using namespace boost::xpressive;
int main()
{
  std::string s = "Boost Libraries";
  sregex expr = sregex::compile("\\w+\\s\\w+");
  std::cout << std::boolalpha << regex_match(s, expr) << '\n';
}

Boost.Xpressive 基本上提供了与 Boost.Regex 相同的功能,只是它们是在 Boost.Xpressive 的命名空间中定义的。 boost::xpressive::regex_match() 比较字符串,boost::xpressive::regex_search() 搜索字符串,boost::xpressive::regex_replace() 替换字符串中的字符。您可以在示例 9.1 中看到这一点,它使用函数 boost::xpressive::regex_match(),并且看起来类似于示例 8.1。

但是,Boost.Xpressive 和 Boost.Regex 之间存在根本区别。 Boost.Xpressive 中正则表达式的类型取决于被搜索字符串的类型。因为 s 基于示例 9.1 中的 std::string,所以正则表达式的类型必须是 boost::xpressive::sregex。将此与示例 9.2 进行比较,其中正则表达式应用于类型为 const char* 的字符串

2.2 示例 9.2

boost::xpressive::cregex 类型为 const char* 的字符串

#include <boost/xpressive/xpressive.hpp>
#include <iostream>
using namespace boost::xpressive;
int main()
{
  const char *c = "Boost Libraries";
  cregex expr = cregex::compile("\\w+\\s\\w+");
  std::cout << std::boolalpha << regex_match(c, expr) << '\n';
}

对于 const char* 类型的字符串,请使用类 boost::xpressive::cregex。如果您使用其他字符串类型,例如 std::wstring 或 const wchar_t*,请使用 boost::xpressive::wsregex 或 boost::xpressive::wcregex。

对于以字符串形式编写的正则表达式,您必须调用静态成员函数 compile()。成员函数必须在用于正则表达式的类型上调用。

Boost.Xpressive 支持以 C++ 代码编写的正则表达式的直接初始化。正则表达式必须以 Boost.Xpressive 支持的符号表示(参见示例 9.3)。

2.3 示例 9.3

带有 C++ 代码的正则表达式

#include <boost/xpressive/xpressive.hpp>
#include <string>
#include <iostream>
using namespace boost::xpressive;
int main()
{
  std::string s = "Boost Libraries";
  sregex expr = +_w >> _s >> +_w;
  std::cout << std::boolalpha << regex_match(s, expr) << '\n';
}

示例 9.2 中的正则表达式写为字符串“\w+\s\w+”,现在在示例 9.3 中表示为 +_w >> _s >> +_w。它是完全相同的正则表达式。这两个示例都搜索至少一个字母数字字符,后跟一个空格,然后搜索至少一个字母数字字符。

Boost.Xpressive 使使用 C++ 代码编写正则表达式成为可能。该库为字符组提供对象。例如,对象 _w 类似于“\w”。 _s 与“\s”的含义相同。

虽然“\w”和“\s”可以在字符串中一个接一个地写入,但像_w和_s这样的对象必须与运算符连接。否则,结果将不是有效的 C++ 代码。 Boost.Xpressive 提供运算符 operator>>,在示例 9.3 中使用。

为了表示应该找到至少一个字母数字字符,_w 以加号为前缀。虽然正则表达式的语法要求量词放在字符组后面--比如“\w+”--但加号必须放在_w前面。加号是一元运算符,在 C++ 中必须放在对象前面。

Boost.Xpressive 尽可能多地模拟正则表达式的规则,因为它们可以在 C++ 中模拟。但是,也有限制。例如,问号是正则表达式中的元字符,表示前面的项目是可选的。由于问号在 C++ 中不是有效的运算符,Boost.Xpressive 将其替换为感叹号。像“\w?”这样的符号使用 Boost.Xpressive 变为 !_w,因为感叹号必须加前缀。

Boost.Xpressive 支持可以链接到表达式的动作--这是 Boost.Regex 不支持的。

2.4 示例 9.4

将动作链接到表达式

#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>
#include <string>
#include <iterator>
#include <iostream>
using namespace boost::xpressive;
int main()
{
  std::string s = "Boost Libraries";
  std::ostream_iterator<std::string> it{std::cout, "\n"};
  sregex expr = (+_w)[*boost::xpressive::ref(it) = _] >> _s >> +_w;
  std::cout << std::boolalpha << regex_match(s, expr) << '\n';
}

示例 9.4 为 boost::xpressive::regex_match() 返回 true 并将 Boost 写入标准输出。

您可以将操作链接到表达式。当找到相应的表达式时执行一个动作。在示例 9.4 中,表达式 +_w 链接到操作 *boost::xpressive::ref(it) = _。该操作是一个 lambda 函数。对象 _ 指的是表达式找到的字符--在本例中是 s 中的第一个单词。相应的字符被分配给迭代器 it。因为它是一个类型为 std::ostream_iterator 的迭代器,它已经用 std::cout 进行了初始化,所以 Boost 被写入标准输出。

请注意,您必须使用函数 boost::xpressive::ref() 来包装迭代器。只有这样才能将_分配给迭代器。 _ 是 Boost.Xpressive 在命名空间 boost::xpressive 中提供的对象,通常不能将其分配给 std::ostream_iterator 类型的迭代器。因为仅当使用 +_w 找到字符串“Boost”时才会发生赋值,所以 boost::xpressive::ref() 会将赋值变成惰性操作。尽管根据 C++ 规则,附加到 +_w 的方括号中的代码会立即执行,但它只能在使用正则表达式时才对迭代器进行赋值。因此,*boost::xpressive::ref(it) = _ 不会立即执行。

示例 9.4 包含头文件 boost/xpressive/regex_actions.hpp。这是必需的,因为无法通过 boost/xpressive/xpressive.hpp 执行操作。

与 Boost.Regex 一样,Boost.Xpressive 支持迭代器以使用正则表达式拆分字符串。 boost::xpressive::regex_token_iterator 和 boost::xpressive::regex_iterator 类执行此操作。也可以将区域设置链接到正则表达式以使用全局区域之外的区域设置。