C++ Boost StringAlgorithms超详细讲解

C/C++
246
0
0
2023-06-18
目录
  • 一、提要
  • 二、简化字符串处理的工具和其库
  • 三、应用Boost.StringAlgrithms库
  • 3.1 字符大小写
  • 3.2 删除字符串内子串
  • 3.3 查找字符串内子串
  • 3.4 合并字符串
  • 3.5 子串替换
  • 3.6 字符串修剪
  • 3.7 创立谓词
  • 3.8 比较
  • 3.9 拆分字符串
  • 3.10 查找字符串
  • 练习

一、提要

boost C++对应的字符串对象也有一套标准操作方法。本文介绍库Boost.StringAlgorithms的若干函数和功能示例。

二、简化字符串处理的工具和其库

  • Boost.StringAlgorithms 定义了许多专门针对字符串的算法。例如,您会找到将字符串转换为小写或大写的算法。
  • Boost.LexicalCast 提供了一个转换运算符来将数字转换为字符串,反之亦然。该库在内部使用字符串流,但可能针对某些类型之间的转换进行了优化。
  • Boost.Format 为 std::printf() 提供了一个类型安全的替代方案。像 Boost.LexicalCast 一样,这个库在内部使用字符串流。如果定义了输出流操作符,Boost.Format 是可扩展的并且支持用户定义的类型。
  • Boost.Regex 和 Boost.Xpressive 是使用正则表达式在字符串中搜索的库。虽然 Boost.Regex 期望将正则表达式写成字符串,但 Boost.Xpressive 允许您将它们写成 C++ 代码。
  • Boost.Tokenizer 使得迭代字符串中的子字符串成为可能。
  • Boost.Spirit 可用于开发基于类似于 Extended Backus-Naur-Form 规则的解析器。

三、应用Boost.StringAlgrithms库

Boost.StringAlgorithms 库为字符串操作提供了许多独立的函数。字符串的类型可以是 std::string、std::wstring 或类模板 std::basic_string 的任何其他实例。这包括 C++11 引入的字符串类 std::u16string 和 std::u32string。

这些函数被分类在不同的头文件中。例如,从大写转换为小写的函数在 boost/algorithm/string/case_conv.hpp 中定义。因为 Boost.StringAlgorithms 包含 20 多个不同的类别和尽可能多的头文件,为了方便起见,boost/algorithm/string.hpp 充当通用头文件,包括所有其他头文件。

3.1 字符大小写

示例1.将字符转化成大写(to_upper_copy)

#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries";
  std::cout << to_upper_copy(s) << '\n';
}

函数 boost::algorithm::to_upper_copy() 将字符串转换为大写,boost::algorithm::to_lower_copy() 将字符串转换为小写。这两个函数都返回输入字符串的副本,转换为指定的大小写。要就地转换字符串,请使用函数 boost::algorithm::to_upper() 或 boost::algorithm::to_lower()。

示例 1 使用 boost::algorithm::to_upper_copy() 将字符串“Boost C++ Libraries”转换为大写。该示例将 BOOST C++ LIBRARIES 写入标准输出。

Boost.StringAlgorithms 中的函数会考虑语言环境。如果没有将语言环境作为参数显式传递,则诸如 boost::algorithm::to_upper_copy() 之类的函数会使用全局语言环境。

示例2.使用语言环境将字符串转换为大写

#include <boost/algorithm/string.hpp>
#include <string>
#include <locale>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ k\xfct\xfcphaneleri";
  std::string upper_case = to_upper_copy(s);
  std::string upper_case = to_upper_copy(s, std::locale{"Turkish"});
  std::locale::global(std::locale{"Turkish"});
  std::cout << upper_case << '\n';
  std::cout << upper_case << '\n';
}

示例 2 调用 boost::algorithm::to_upper_copy() 两次以将土耳其语字符串“Boost C++ kütüphaneleri”转换为大写。第一次调用 boost::algorithm::to_upper_copy() 使用全局语言环境,在本例中为 C 语言环境。在 C 语言环境中,带有变音符号的字符没有大写映射,因此输出将如下所示:BOOST C++ KüTüPHANELERI。

土耳其语语言环境被传递给对 boost::algorithm::to_upper_copy() 的第二次调用。由于此语言环境确实具有变音符号的大写等效项,因此可以将整个字符串转换为大写。因此,对 boost::algorithm::to_upper_copy() 的第二次调用正确地转换了字符串,如下所示:BOOST C++ KÜTÜPHANELERI。

注意:

如果您想在 POSIX 操作系统上运行示例,请将“Turkish”替换为“tr_TR”,并确保安装了土耳其语区域设置。

3.2 删除字符串内子串

示例3.从字符串中删除字符的算法

#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries";
  std::cout << erase_first_copy(s, "s") << '\n';
  std::cout << erase_nth_copy(s, "s",) << '\n';
  std::cout << erase_last_copy(s, "s") << '\n';
  std::cout << erase_all_copy(s, "s") << '\n';
  std::cout << erase_head_copy(s,) << '\n';
  std::cout << erase_tail_copy(s,) << '\n';
}

Boost.StringAlgorithms 提供了几个函数,可用于从字符串中删除单个字符(参见示例 3)。例如, boost::algorithm::erase_all_copy() 将从字符串中删除所有出现的特定字符。要仅删除第一次出现的字符,请改用 boost::algorithm::erase_first_copy()。要在任一端将字符串缩短特定数量的字符,请使用函数 boost::algorithm::erase_head_copy() 和 boost::algorithm::erase_tail_copy()。

3.3 查找字符串内子串

示例4. 查找字串boost::algorithm::find_first()

#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries";
  boost::iterator_range<std::string::iterator> r = find_first(s, "C++");
  std::cout << r << '\n';
  r = find_first(s, "xyz");
  std::cout << r << '\n';
}

函数如 boost::algorithm::find_first()、boost::algorithm::find_last()、boost::algorithm::find_nth()、boost::algorithm::find_head() 和 boost::algorithm::find_tail () 可用于在字符串中查找字符串。

所有这些函数都返回一对 boost::iterator_range 类型的迭代器。这个类源自Boost.Range,它实现了基于迭代器概念的范围概念。由于运算符 operator<< 为 boost::iterator_range 重载,因此单个搜索算法的结果可以直接写入标准输出。示例 4 为第一个结果打印 C++,为第二个结果打印一个空字符串。

3.4 合并字符串

示例.5. 合并字符串boost::algorithm::join()

#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::vector<std::string> v{"Boost", "C++", "Libraries"};
  std::cout << join(v, " ") << '\n';
}

字符串容器作为第一个参数传递给函数 boost::algorithm::join(),该函数将它们连接起来,由第二个参数分隔。示例 5.5 将输出 Boost C++ 库。

3.5 子串替换

示例6.替换字符串中字符的算法

#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries";
  std::cout << replace_first_copy(s, "+", "-") << '\n';
  std::cout << replace_nth_copy(s, "+",, "-") << '\n';
  std::cout << replace_last_copy(s, "+", "-") << '\n';
  std::cout << replace_all_copy(s, "+", "-") << '\n';
  std::cout << replace_head_copy(s,, "BOOST") << '\n';
  std::cout << replace_tail_copy(s,, "LIBRARIES") << '\n';
}

与搜索字符串或从字符串中删除字符的函数一样,Boost.StringAlgorithms 也提供了替换字符串中的子字符串的函数。其中包括以下函数:boost::algorithm::replace_first_copy()、boost::algorithm::replace_nth_copy()、boost::algorithm::replace_last_copy()、boost::algorithm::replace_all_copy()、boost::algorithm ::replace_head_copy() 和 boost::algorithm::replace_tail_copy()。它们可以以与搜索和删除函数相同的方式应用,除了它们需要一个额外的参数 - 替换字符串(参见示例 6)。

3.6 字符串修剪

示例7.修剪字符串的算法

#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "\t Boost C++ Libraries \t";
  std::cout << "_" << trim_left_copy(s) << "_\n";
  std::cout << "_" << trim_right_copy(s) << "_\n";
  std::cout << "_" << trim_copy(s) << "_\n";
}

要删除字符串两端的空格,请使用 boost::algorithm::trim_left_copy()、boost::algorithm::trim_right_copy() 和 boost::algorithm::trim_copy()(参见示例 5.7)。全局语言环境确定哪些字符被视为空格。

Boost.StringAlgorithms 允许您提供谓词作为不同函数的附加参数,以确定函数应用于字符串的哪些字符。带有谓词的版本是:boost::algorithm::trim_right_copy_if()、boost::algorithm::trim_left_copy_if() 和 boost::algorithm::trim_copy_if()。

3.7 创立谓词

示例8.创建谓词1is_any_of

boost::algorithm::is_any_of()
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "--Boost C++ Libraries--";
  std::cout << trim_left_copy_if(s, is_any_of("-")) << '\n';
  std::cout << trim_right_copy_if(s, is_any_of("-")) << '\n';
  std::cout << trim_copy_if(s, is_any_of("-")) << '\n';
}

示例 8 使用另一个名为 boost::algorithm::is_any_of() 的函数,它是一个辅助函数,用于创建一个谓词,用于检查某个字符(作为参数传递给 is_any_of() )是否存在于字符串中。使用 boost::algorithm::is_any_of(),可以指定修剪字符串的字符。示例 5.8 使用连字符。

Boost.StringAlgorithms 提供了许多返回常用谓词的辅助函数。

示例9.创建谓词2(is_digit() )

boost::algorithm::is_digit()
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries123456789";
  std::cout << trim_left_copy_if(s, is_digit()) << '\n';
  std::cout << trim_right_copy_if(s, is_digit()) << '\n';
  std::cout << trim_copy_if(s, is_digit()) << '\n';
}

boost::algorithm::is_digit() 返回的谓词测试字符是否为数字。在示例9 中,boost::algorithm::is_digit() 用于从字符串 s 中删除数字。

Boost.StringAlgorithms 还提供了辅助函数来检查字符是大写还是小写:boost::algorithm::is_upper() 和 boost::algorithm::is_lower()。默认情况下,所有这些函数都使用全局语言环境,除非您将不同的语言环境作为参数传递。

除了验证字符串的单个字符的谓词之外,Boost.StringAlgorithms 还提供了可以处理字符串的函数(参见示例 10)。

3.8 比较

示例10.字符串的比较

#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries";
  std::cout.setf(std::ios::boolalpha);
  std::cout << starts_with(s, "Boost") << '\n';
  std::cout << ends_with(s, "Libraries") << '\n';
  std::cout << contains(s, "C++") << '\n';
  std::cout << lexicographical_compare(s, "Boost") << '\n';
}

boost::algorithm::starts_with()、boost::algorithm::ends_with()、boost::algorithm::contains() 和 boost::algorithm::lexicographical_compare() 函数比较两个单独的字符串。示例 11 引入了一个将字符串拆分为较小部分的函数。

3.9 拆分字符串

示例 11.拆分字符串boost::algorithm::split()

#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries";
  std::vector<std::string> v;
  split(v, s, is_space());
  std::cout << v.size() << '\n';
}

使用 boost::algorithm::split(),可以根据分隔符拆分给定的字符串。子字符串存储在容器中。该函数需要一个谓词作为其第三个参数,该谓词测试每个字符并检查字符串是否应在给定位置拆分。示例 5.11 使用辅助函数 boost::algorithm::is_space() 创建一个谓词,在每个空格字符处分割字符串。

本章介绍的许多函数都有忽略字符串大小写的版本。这些版本通常具有相同的名称,但前导“i”除外。例如,boost::algorithm::erase_all_copy() 的等效函数是 boost::algorithm::ierase_all_copy()。

最后,Boost.StringAlgorithms 的很多函数也支持正则表达式。示例 5.12 使用函数 boost::algorithm::find_regex() 来搜索正则表达式。

3.10 查找字符串

示例12.字符串查找boost::algorithm::find_regex()

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <string>
#include <iostream>
using namespace boost::algorithm;
int main()
{
  std::string s = "Boost C++ Libraries";
  boost::iterator_range<std::string::iterator> r =
    find_regex(s, boost::regex{"\\w\\+\\+"});
  std::cout << r << '\n';
}

为了使用正则表达式,程序会访问一个名为 boost::regex 的类,该类将在第 8 章中介绍。

示例 12 将 C++ 写入标准输出。

练习

创建一个程序,要求用户输入他的全名。程序应该用“Hello”来问候用户,然后是用户名和感叹号。用户的名字和姓氏应以大写字母开头,后跟小写字母。此外,用户的名字和姓氏应该用一个空格隔开。感叹号前不能有空格。