4.1 C++ Boost 字符串处理库

news2024/11/23 19:08:28

Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量、可移植、高效的C应用程序。Boost库可以作为标准C库的后备,通常被称为准标准库,是C标准化进程的重要开发引擎之一。使用Boost库可以加速C应用程序的开发过程,提高代码质量和性能,并且可以适用于多种不同的系统平台和编译器。Boost库已被广泛应用于许多不同领域的C++应用程序开发中,如网络应用程序、图像处理、数值计算、多线程应用程序和文件系统处理等。

  • Boost库官网:https://www.boost.org/

读者可自行去官方下载对应特定编译器的二进制文件,在官方网站页面中选中More Downloads... (RSS)下载页面,并点击Prebuilt windows binaries则可打开二进制预编译版本的对应页面。

此时读者可根据自己编译器的版本选择适合于自己的库,此处笔者使用的是Visual Studio 2013编译器,所以此处选中的是1.82.0目录下的boost_1_82_0-msvc-12.0-32.exe安装包,下载好以后读者可将该库安装到自定义目录下,此处笔者就安装在默认路径下,当安装成功后读者可看到如下图所示的输出信息,至此安装结束;

在安装完成后,读者可自行打开安装目录,该目录中我们所需要配置的选项只有两个,首先读者需要在VS中引入boost_1_82_0目录,并在类库选项上引入lib32-msvc-12.0即可,如下图所示则是正常引用后的配置参数;

在C语言的早期版本中,对于字符串和文本的处理一直都是最为薄弱的,直到C++98规范的推出才勉强增加了一个std::string的类,虽然在一定程度上弥补了字符串处理的不足,但仍然缺少一些更为强大和丰富的字符串处理和操作工具。

随着Boost库的推出和广泛应用,该库内置了多种用于字符串和文本处理的强大工具,为C程序员提供了强大的库和更全面的支持。Boost库中的字符串处理工具包括字符串分割、替换、转换、截断以及正则表达式等功能。使用Boost库,C程序员现在可以轻松地处理字符串和文本数据,开发更加高效和强大的C应用程序。

1.1 字符串格式转换

lexical_cast是Boost库中用于类型转换的一种强大的工具。它可以将一个类型的对象转换为另一个类型,例如将字符串类型的数据转换为数字类型的数据。它简化了类型转换的代码,并提供了一些错误检查,以确保转换的安全性。在使用lexical_cast时,程序员只需指定需要转换的源数据类型和目标数据类型即可,在大多数情况下,可以自动完成转换,lexical_cast是字符串格式转换的一个重要工具,非常适用于将字符串和数字类型之间进行快速而安全的转换。

但读者需要注意,lexical_cast并不支持自定义类型的转换,例如自定义类或结构体。如果需要进行自定义类型的转换,需要使用Boost库中的其他工具或者自行编写转换函数。

#include <iostream>
#include <string>
#include <boost\lexical_cast.hpp>

using namespace std;
using namespace boost;

int main(int argc, char * argv[])
{
  string str[3] = { "100", "102", "3.14159" };

  // 字符串转换为数值类型
  std::cout << "字符串转为整数: " << lexical_cast<int>(str[0]) << std::endl;
  std::cout << "字符串转为长整数: " << lexical_cast<long>(str[1]) << std::endl;
  std::cout << "字符串转为浮点数: " << lexical_cast<float>(str[2]) << std::endl;

  // 数值类型转化为字符串
  std::cout << "数值转为字符串: " << lexical_cast<string>(100) << std::endl;
  std::cout << "十六进制转为十进制: " << lexical_cast<string>(0x10) << std::endl;

  // 转换后赋值给变量
  try{
    int number = lexical_cast<int>(str[0]);
    std::cout << "转换后赋值给变量: " << number << std::endl;
  }
  catch(bad_lexical_cast&){
    std::cout << "转换失败抛出异常." << std::endl;
  }

  system("pause");
  return 0;
}

此外C++默认库中同样提供了一些可实现字符串与数值之间转换的函数,这些函数包括了atoi,itoa,atof,gcvt,这些内置函数库通常不具有lexical_cast函数所提供的错误检查和异常处理机制,因此在使用时还需要特别注意程序的输出结果。

#include <iostream>
#include <string>
#include <sstream>
#include <boost\lexical_cast.hpp>

using namespace std;
using namespace boost;

int main(int argc, char * argv[])
{
  string str[3] = { "100", "102", "3.14159" };
  int inter[3] = { 100, 45, 7 };

  // atoi
  int number_a = atoi(str[0].c_str());
  std::cout << "字符串转为整数: " << number_a << std::endl;

  // itoa
  char buf1[64] = {0};
  itoa(inter[0], buf1, 16);
  std::cout << "将inter[0]转为16进制并放入buf中: " << buf1 << std::endl;

  // atof
  double number_b = atof(str[2].c_str());
  std::cout << "将字符串转为双精度: " << number_b << std::endl;

  // gcvt
  char buf2[64] = { 0 };
  char *number_c = gcvt(3.54655, 3, buf2);
  std::cout << "将浮点数转为字符串,保留两位(四舍五入): " << buf2 << std::endl;

  // sprintf
  char buf3[64] = { 0 };
  int number_d = 10245;

  sprintf(buf3, "%d", number_d);
  std::cout << "将number_d中的整数转为字符串: " << buf3 << std::endl;

  system("pause");
  return 0;
}

1.2 字符串格式输出

format是Boost库中用于格式化字符串的工具。它提供了一种简单、安全和灵活的方式来生成格式化字符串,并支持广泛的格式标识符和操作符。使用boost::format,程序员可以在字符串中插入变量、数字等内容,并指定它们的格式。在boost::format中,执行的格式化操作使用类似于printf中格式化字符串的方式,以"{n}"形式表示变量的位置,并使用占位符指定变量的类型和格式。例如,以下示例利用boost::format分别实现了四种不同的格式化方法:

#include <iostream>
#include <string>
#include <boost\format.hpp>

using namespace std;
using namespace boost;

int main(int argc, char * argv[])
{
  // 第一种方式: 直接填充字符串
  boost::format fmtA("姓名: %s -> 年龄: %d -> 性别: %s");
  fmtA %"lyshark";
  fmtA % 22;
  fmtA %"男";

  std::string str = fmtA.str();
  std::cout << "第一种输出: " << str << std::endl;

  // 第二种方式: 拷贝的使用
  boost::format fmtB("姓名: %s -> 年龄: %d -> 性别: %s");
  std::cout << "第二种输出: " << format(fmtB) % "lyshark" % 23 % "男" << std::endl;

  // 第三种方式: 拷贝后强转
  std::string str_format = boost::str(boost::format("%d.%d.%d.%d") % 192.%168.%1. % 100);
  std::cout << "第三种输出: " << str_format << std::endl;

  // 第四种方式: 格式化输出
  // %|10s| 输出宽度为10,不足补空格
  // %|06X| 输出宽度为7的大写16进制整数
  boost::format str_tmp("%|10s|\n %|07X|\n");
  str_tmp %"lyshark" % 100;
  string str_format_B = boost::str(str_tmp);
  std::cout << "第四种输出: " << str_format_B << endl;

  system("pause");
  return 0;
}

1.3 字符串大小写转换

字符串大小写转换可使用to_upper()to_lower()这两个函数,这两个函数都是Boost库中的字符串处理函数,它们与C++标准库的同名函数功能类似,但支持更广泛的字符集以满足更多应用场景的需求。boost::to_upper()函数将指定字符串中的字母字符全部转换为大写格式,并返回转换后的新字符串;boost::to_lower()函数则将指定字符串中的字母字符全部转换为小写格式,并返回转换后的新字符串。

以下是使用boost::to_upper()boost::to_lower()进行字符串大小写转换的示例:

#include <iostream>
#include <Windows.h>
#include <string>
#include <vector>
#include <boost\algorithm\string.hpp>

using namespace std;
using namespace boost;

int main(int argc, char * argv[])
{
  vector<string> str_array = { "hello" , "lyshark" , "welcome" , "to" , "my" , "blog" };

  // 循环转换为大写,to_upper_copy不会影响原生字符串
  for (int x = 0; x < str_array.size(); x++)
  {
    string item = to_upper_copy(str_array[x]);
    std::cout << "转换拷贝: " << item << std::endl;
  }

  std::cout << "原始字符串不受影响: " << str_array[1] << std::endl;

  // 如果使用to_upper 则会直接修改原生字符串
  for (int x = 0; x < str_array.size(); x++)
  {
    to_upper(str_array[x]);
  }
  std::cout << "原始字符串受影响: " << str_array[1] << std::endl;
  
  system("pause");
  return 0;
}

在这个示例中,通过调用boost::to_upper()boost::to_lower()函数,将指定字符串中的字母字符全部转换为大写或小写,并输出转换后的新字符串。细心的读者应该还可以观察到to_upper_copy在其后方存在一个COPY字符,当出现拷贝字符时则预示着需要对原始字符串进行拷贝而不是直接更改原始字符串的意思。

1.4 字符串判断与测试

starts_with()ends_with()也是Boost库中的字符串处理函数。这两个函数分别用于检查一个字符串是否以指定字符串开头或结尾,而contains()则可用于测试字符串的属性。

boost::starts_with接收两个参数,第一个参数是待检查的字符串,第二个参数是被检查作为开头的字符串,返回一个bool值表示原始字符串是否以目标字符串开头。

boost::ends_with也是接收两个参数,第一个参数是待检查的字符串,第二个参数是被检查作为结尾的字符串,返回一个bool值表示原始字符串是否以目标字符串结尾。以下是boost::starts_with()boost::ends_with()两个函数的示例:

#include <iostream>
#include <string>
#include <boost\algorithm\string.hpp>

using namespace std;
using namespace boost;

int main(int argc, char * argv[])
{
  string str[6] = { "hello lyshark", "hello LyShark", "readme.txt", "ABC", "FCE", "lyshark" };

  cout << "大小写不敏感判断后缀: " << iends_with(str[0], "lyshark") << endl;
  cout << "大小写敏感判断前缀: " << starts_with(str[1], "Hello") << endl;

  cout << "测试str[0]里面是否包含str[5]: " << contains(str[0], str[5]) << endl;
  cout << "测试前5个字母是否为小写: " << all(str[0].substr(0, 5), is_lower()) << endl;
  cout << "测试前2个字符是否为字母: " << all(str[1].substr(0, 2), is_alpha()) << endl;

  system("pause");
  return 0;
}

1.5 字符串修正与裁剪

boost::replace_first_copy()boost::replace_last_copy()boost::trim()boost::trim_left()boost::trim_right()都是Boost库中的字符串处理函数。

replace_first_copy用于将字符串中第一个匹配的子字符串替换为新的字符串,返回替换后的新字符串并不改变原字符串。

replace_last_copy函数则用于将字符串中最后一个匹配的子字符串替换为新的字符串,同样返回替换后的新字符串且不改变原字符串。

trim()、trim_left和trim_right用于去除字符串两端的空格或指定的字符,返回处理后的新字符串并不改变原字符串。

其中,boost::trim()函数是去除字符串两端的空格,boost::trim_left()函数是去除字符串左端的空格或指定字符,boost::trim_right()函数是去除字符串右端的空格或指定字符。以下是这几个函数的示例:

#include <iostream>
#include <string>
#include <vector>
#include <boost\format.hpp>
#include <boost\algorithm\string.hpp>

using namespace std;
using namespace boost;

int main(int argc, char * argv[])
{
  string str[6] = { "hello lyshark", "hello LyShark", "readme.txt", "ABC", "FCE", "lyshark" };

  // 字符串替换: 替换开头/结尾 字符串hello为lyshark
  std::cout << replace_first_copy(str[0], "hello", "lyshark") << std::endl;
  std::cout << replace_last_copy(str[0], "hello", "lyshark") << std::endl;

  // 字符串删除: 删除字符串结尾的.txt并将其开头部分转换为大写
  vector<char> v(str[2].begin(), str[2].end());
  vector<char> v2 = to_upper_copy(erase_first_copy(v, ".txt"));

  for (auto x : v2)
    std::cout << x;
  std::cout << std::endl;

  // 字符串修剪: 去除字符串中的空格或-
  boost::format fmt("|%s|\n");
  std::string my_string_a = "   hello  lyshark   ";

  cout << "删除两端空格: " << fmt %trim_copy(my_string_a) << endl;
  cout << "删除左端空格: " << fmt %trim_left_copy(my_string_a) << endl;
  cout << "删除左端空格: " << fmt %trim_right_copy(my_string_a) << endl;

  std::string s = "--lyshark--";
  std::cout << "删除左侧所有的-: " << trim_left_copy_if(s, is_any_of("-")) << std::endl;
  std::cout << "删除右侧所有的-: " << trim_right_copy_if(s, is_any_of("-")) << std::endl;
  std::cout << "删除两侧所有的-: " << trim_copy_if(s, is_any_of("-")) << std::endl;

  // 字符串修剪: 去除字符串中的特殊符号
  std::string my_string_b = "2021 happy new Year !!!";
  cout << "删除左端数字: " << fmt %trim_left_copy_if(my_string_b, is_digit()) << endl;
  cout << "删除右端标点: " << fmt %trim_right_copy_if(my_string_b, is_punct()) << endl;
  cout << "删除两端(标点|数字|空格): " << trim_copy_if(my_string_b, is_punct() || is_digit() || is_space()) << endl;

  system("pause");
  return 0;
}

1.6 字符串匹配开头结尾

boost::find_first()boost::find_last()boost::ifind_nth()boost::ifind_last()都是Boost库中的字符串处理函数,用于在字符串中查找指定的子字符串。

find_first函数接收两个参数,第一个参数是待查找的字符串,第二个参数是要查找的目标子字符串,返回指向第一个匹配子字符串的迭代器,如果没有找到,返回末尾迭代器。

find_last函数则是在待查找的字符串中从后向前查找指定子字符串的第一次出现,同样返回指向子字符串的迭代器或末尾迭代器。

ifind_nth和ifind_last函数均利用不区分大小写的方式进行字符串查找,可以根据需要查找一定位置处的指定数量的子字符串。如果找到了目标子字符串,返回一个指向它的迭代器,否则返回一个指向结束迭代器(end)的迭代器。

#include <iostream>
#include <string>
#include <boost\format.hpp>
#include <boost\algorithm\string.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  boost::format fmt("|%s|. pos = %d\n");
  std::string my_string = "Long long ago, there was Ago king as long.";

  // 定义迭代区间
  iterator_range<std::string::iterator> reg;

  // 寻找第一次出现的位置(大小写敏感)
  reg = find_first(my_string, "Ago");
  cout << fmt %reg % (reg.begin() - my_string.begin()) << endl;

  // 寻找最后一次出现的位置(大小写不敏感)
  reg = ifind_last(my_string, "ago");
  cout << fmt %reg % (reg.begin() - my_string.begin()) << endl;

  // 寻找第三次出现long的位置(大小写不敏感)
  reg = ifind_nth(my_string, "long", 2);
  cout << fmt %reg % (reg.begin() - my_string.begin()) << endl;

  // 取前四个字符
  reg = find_head(my_string, 4);
  cout << fmt %reg % (reg.begin() - my_string.begin()) << endl;

  // 取后四个字符
  reg = find_tail(my_string, 4);
  cout << fmt %reg % (reg.begin() - my_string.begin()) << endl;

  // 找不到则输出
  reg = find_first(my_string, "lyshark");
  cout << "flag = " << (reg.empty() && !reg) << endl;

  system("pause");
  return 0;
}

1.7 字符串替换与删除

boost::replace_first()boost::replace_tail()boost::replace_head()、和boost::replace_nth()是Boost库中的字符串处理函数,用于替换指定字符串中的子字符串。

replace_first函数用于在给定字符串中替换第一个匹配的子字符串,接收三个参数,第一个参数是源字符串,第二个参数是查找的目标子串,第三个参数是替换子串,函数返回被处理后的原字符串对象。

replace_tail和replace_head的作用与replace_first类似,但是在字符串的头或尾部查找需要替换的字符串,并进行替换操作。

replace_nth函数用于替换源字符串中的指定位置的子字符串,接收四个参数,第一个参数是源字符串,第二个参数是要替换的子串,第三个参数是替换后的子串,第四个参数是指定要替换的子串的位置(从0开始计数),函数返回被处理后的原字符串对象。

#include <iostream>
#include <string>
#include <boost\format.hpp>
#include <boost\algorithm\string.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  boost::format fmt("|%s|. pos = %d\n");
  std::string my_string = "Long long ago, there was Ago king as long.";

  // 替换开头字符串(两种替换方式)
  std::string str_copy = replace_first_copy(my_string, "long", "LONG");
  cout << "替换后返回字符串: " << str_copy << endl;

  replace_first(my_string, "ago", "AGO");
  cout << "直接替换在原始字符串上: " << my_string << endl;

  // 替换开头或结尾前后5个字符
  replace_tail(my_string, 5, "lyshark");
  cout << "替换结尾5个字符: " << my_string << endl;
  replace_head(my_string, 5, "lyshark");
  cout << "替换开头5个字符: " << my_string << endl;

  // 替换第一次出现long的位置为AGES
  replace_nth(my_string, "long", 0, "AGES");
  cout << "第一次出现位置: " << my_string << endl;

  // 替换所有出现过的位置
  std::string str_copy_a = replace_all_copy(my_string, "lyshark", "LYSSHARK");
  cout << "替换所有位置: " << str_copy_a << endl;
  
  // 删除第1次出现was位置的字符串
  std::string del_str_copy = erase_nth_copy(my_string, "was", 0);
  cout << "删除后的字符串: " << del_str_copy << endl;

  // 删除字符串中所有的LYSSHARK
  erase_all(my_string, "LYSSHARK");
  cout << "删除后的字符串: " << my_string << endl;

  getchar();
  return 0;
}

1.8 字符串切割与合并

boost::split()boost::join()函数都是Boost库中的字符串处理函数,用于分割和连接字符串。

split函数用于将一个字符串按照给定的分隔符拆分成多个子字符串,并将这些子字符串存储到一个容器中。split函数接收三个参数:源字符串、分隔符和存储子字符串的容器。

join函数则是将多个子字符串按照给定的分隔符连接成一个新的字符串,join函数接收两个参数:存储子字符串的容器和分隔符。

#include <iostream>
#include <string>
#include <algorithm>
#include <boost\algorithm\string.hpp>
#include <boost\assign.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  std::string my_string = "lyshark,Link.Zelda:Mario-Ligui+zelda,ZELDA";

  // 查找字符串中的特定字符串
  deque<std::string> deq;

  ifind_all(deq, my_string, "zelda");
  cout << "查找字符串个数(不区分大小写): " << deq.size() << endl;
  if (deq.size() == 3)
  {
    for (auto each : deq)
      cout << "[ " << each << " ]" << endl;
  }

  // 切割字符串(1)
  list<iterator_range<std::string::iterator>> ptr;
  split(ptr, my_string, is_any_of(",.:-+"));
  for (auto each : ptr)
    cout << "[ " << each << " ]" << endl;

  // 切割字符串(2)
  ptr.clear();
  split(ptr, my_string, is_any_of(".:-"), token_compress_on);
  for (auto each : ptr)
    cout << "[ " << each << " ]" << endl;

  // 合并字符串: 用空格将其连接起来
  std::vector<string> vct;

  vct.push_back("hello");
  vct.push_back("lyshark");
  cout << "[ " << join(vct, " ") << " ]"<< endl;

  system("pause");
  return 0;
}

字符串的分割除去上述分割方式外同样可以采用如下方式分割,该方法将字符串放入一个vector::string容器内,并循环每次判断是否为|数显如果是则输出,利用此方式实现字符串的切割。

  std::vector<std::string> vect;
  std::string mystr = "a | b | c | d | e | f";

  boost::split(vect, mystr, boost::is_any_of("|"), boost::token_compress_on);
  for (int i = 0; i < vect.size(); ++i)
  {
    cout << vect[i] << endl;
  }

1.9 整数转字符串并合并

boost::algorithm::join()是Boost库中对于字符串拼接的函数,它可以将一个存储子字符串的容器中的所有字符串用指定的分隔符进行拼接。 该函数的返回值是一个字符串,内容为拼接后形成的新字符串。

该函数不仅仅可用于字符串之间的拼接还可以实现整数浮点数与字符串之间的转换,如下案例中则是先了这两者之间的灵活转换。

#include <iostream>
#include <vector>
#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>

using boost::adaptors::transformed;
using boost::algorithm::join;

int main(int argc, char *argv[])
{
  std::vector<int> vect_int(10);
  std::vector<double> vect_double(10);

  // 随机数填充元素
  std::generate(vect_int.begin(), vect_int.end(), std::rand);
  std::generate(vect_int.begin(), vect_int.end(), std::rand);

  // 转换并连接
  std::string ref_string_int = join(vect_int | transformed(static_cast<std::string(*)(int)>(std::to_string)), ", ");
  std::cout << "整数转为字符串:" << ref_string_int << std::endl;

  // 转换并连接
  std::string ref_string_double = join(vect_int | transformed(static_cast<std::string(*)(double)>(std::to_string)), ", ");
  std::cout << "浮点数转为字符串:" << ref_string_double << std::endl;

  system("pause");
  return 0;
}

1.10 字符串查找/分割迭代器

boost::make_find_iterator()boost::make_split_iterator()都是Boost库中的字符串处理函数,用于生成指向容器和字符串序列的迭代器。

make_find_iterator 用于生成一个指向容器或字符串序列中第一个匹配指定字符串的迭代器,接收两个参数,第一个参数是源容器或字符序列,第二个参数是匹配的子字符串。如果没有匹配到子字符串,返回的迭代器将指向容器或字符串序列的末尾。

make_split_iterator 则用于生成一个分隔符迭代器,可以用于将字符串分割成多个子字符串,接收两个参数,第一个参数是源字符序列或容器,第二个参数是分隔符。使用迭代器可以遍历分割后的字符串序列。

#include <iostream>
#include <string>
#include <algorithm>
#include <boost\algorithm\string.hpp>
#include <boost\assign.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  std::string my_string("hello||lyshark||welcome||link||lyshark");

  // 查找迭代器: 查找字符串中的lyshark
  typedef find_iterator<string::iterator> string_find_iterator;
  string_find_iterator pos, end;
  for (pos = make_find_iterator(my_string, first_finder("lyshark", is_iequal())); pos != end; ++pos)
  {
    cout << "[ " << *pos << " ]" << endl;
  }

  std::cout << "----------------------------" << std::endl;

  // 分割迭代器: 根据||分割字符串
  typedef split_iterator<string::iterator> string_split_iterator;
  string_split_iterator p, endp;
  for (p = make_split_iterator(my_string, first_finder("||", is_iequal())); p != endp; ++p)
  {
    cout << "[ " << *p << " ]" << endl;
  }

  system("pause");
  return 0;
}

除去使用上方的分割器实现字符串切割以外,读者也可以使用Boost中提供的tokenizer分词器实现切割,boost::tokenizer()的使用非常简单,只需定义一个tokenizer对象,指定要分割的字符串和分隔符即可。可以使用多个不同的构造函数来指定不同的分隔符,其中char_separatorboost_regex_separator分别使用字符和正则表达式作为分隔符。

#include <iostream>
#include <boost/tokenizer.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  std::string strTag = "explorer.exe,1024";

  // 定义分词器: 定义分割符号为[逗号,空格]
  boost::char_separator<char> sep(", ");

  typedef boost::tokenizer<boost::char_separator<char>> CustonTokenizer;
  CustonTokenizer tok(strTag, sep);

  // 将分词结果放入vector链表
  std::vector<std::string> vecSegTag;
  for (CustonTokenizer::iterator beg = tok.begin(); beg != tok.end(); ++beg)
  {
    vecSegTag.push_back(*beg);
  }

  // const_case 将string转换为char*
  std::string ref_process = const_cast<char *>(vecSegTag[0].c_str());
  std::string ref_ppid = const_cast<char *>(vecSegTag[1].c_str());

  cout << "进程名: " << ref_process << " 进程PID: " << ref_ppid<< endl;
  cout << "分词数: " << vecSegTag.size() << endl;

  system("pause");
  return 0;
}

1.11 正则分组匹配字符串

boost::regex_match是Boost库中用于正则表达式匹配的函数,用于判断一个字符串是否符合给定的正则表达式模式。使用改函数可以帮助程序员在程序开发中实现高度的正则表达式匹配。在使用boost::regex_match时,需要注意正确理解正则表达式的规则才能有效地应用。

regex_match函数接收两个参数,第一个参数是要匹配的字符串,第二个参数是一个正则表达式对象。在匹配成功时,regex_match函数返回true;否则返回false。

#include <iostream>
#include <string>
#include <algorithm>
#include <boost\algorithm\string.hpp>
#include <boost\xpressive\xpressive.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  using namespace boost::xpressive;

  // 匹配字符串
  std::string String = "hello lyshark ac lyshark";

  sregex start_regx = sregex::compile("^hello.*");
  cout << "匹配开头: " << regex_match(String, start_regx) << endl;

  sregex end_regx = sregex::compile(".*lyshark$");
  cout << "匹配结尾: " << regex_match(String, end_regx) << endl;

  // 数组方式匹配
  cregex_compiler regx;

  regx["regxA"] = regx.compile("a|b|c");
  regx["regxB"] = regx.compile("\\d*");

  cout << "匹配A: " << regex_match("abcdefg", regx["regxA"]) << endl;
  cout << "匹配B: " << regex_match("123123", regx["regxB"]) << endl;

  system("pause");
  return 0;
}

正则模块支持分组匹配模式,通过cregex::compile可用于生成不同的匹配规则,在匹配时读者可根据不同的匹配规则实现对不同字符串的匹配以此来实现分组匹配的目的,需要注意的是,在匹配时C++ 11规范中需要在规则字符串开头结尾加入---横线,而在C++ 98规范中,则需要增加\符号。

#include <iostream>
#include <string>
#include <algorithm>
#include <boost\algorithm\string.hpp>
#include <boost\xpressive\xpressive.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  using namespace boost::xpressive;

  // 使用C++ 11 匹配身份证
  cregex regx11 = cregex::compile(R"---(\d{6}(1|2)\d{3}(0|1)\d[0-3]\d\d{3}(X|\d))---", icase);
  cout << "验证身份证: " << regex_match("513436200002247099", regx11) << endl;

  // 使用C++ 98 匹配身份证
  cregex regx98 = cregex::compile("\\d{6}((1|2)\\d{3})((0|1)\\d)([0-3]\\d)(\\d{3}(X|\\d))", icase);
  cmatch what;

  std::string str = "513436200002247099";
  regex_match(str.c_str(), what, regx98);
  for (auto &each : what)
  {
    cout << "[ " << each << " ]" << endl;
  }
  cout << "生日为: " << what[1] << what[3] << what[5] << endl;

  system("pause");
  return 0;
}

1.12 正则查找替换

regex_search函数用于在一个字符串中查找与指定的正则表达式匹配的任何序列,返回true或false,不像regex_match()函数需要匹配整个字符串。如果匹配成功,可以使用smatch对象的operator[]操作符以及first, second等函数来获取匹配结果。

regex_replace和regex_replace的用法非常相似。它们都可以用指定的正则表达式替换字符串中的部分内容。同样需要一个std::string对象和一个std::regex对象来替换目标字符串中的部分内容。只是boost::regex_replace()需要额外的一个调用参数来指定替换的跟踪处理方式,而std::regex_replace()不需要。

#include <iostream>
#include <string>
#include <algorithm>
#include <boost\algorithm\string.hpp>
#include <boost\xpressive\xpressive.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  using namespace boost::xpressive;

  // 正则查找特定字符串
  char my_stringA[] = "This is power-studio territory";

  cregex regx = cregex::compile("(power)-(.{6})", icase);
  cmatch what;
  regex_search(my_stringA, what, regx);
  if (what.size() != 0)
  {
    for (int x = 0; x < what.size(); x++)
    {
      cout << what[x] << endl;
    }
  }

  // 正则替换特定字符串
  std::string my_stringB = "2020 Happy New Year !!!";

  sregex regxA = sregex::compile("^(\\d| )*");    // 匹配开头数字
  sregex regxB = sregex::compile("!*$");          // 匹配末尾标点符号

  cout << regex_replace(my_stringB, regxA, "2021") << endl;
  cout << regex_replace(my_stringB, regxB, "") << endl;

  system("pause");
  return 0;
}

1.13 正则迭代与分词

boost::sregex_iterator()和boost::cregex_token_iterator()是Boost库中用于正则表达式处理的迭代器,它们可以帮助我们在字符串中查找或分解出与指定的正则表达式模式匹配的子字符串序列。

sregex_iterator 迭代查找一个输入字符串中符合给定正则表达式模式的所有匹配字符串序列。

cregex_token_iterator 迭代器可将输入字符串分解为非匹配部分和与指定的正则表达式模式匹配的子字符串序列。

#include <iostream>
#include <string>
#include <algorithm>
#include <boost\algorithm\string.hpp>
#include <boost\xpressive\xpressive.hpp>
#include <boost\xpressive\regex_iterator.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  using namespace boost::xpressive;

  std::string my_string_a = "power-shell, power-studio,power-engine,super-user";
  char my_string_b[] = "*lyshark*||+administrator+||root!!||metaper";

  // 正则迭代输出
  sregex regxA = sregex::compile("power-(\\w{5})", icase);
  sregex_iterator start_ptr(my_string_a.begin(), my_string_a.end(), regxA);
  sregex_iterator end_ptr;
  for (; start_ptr != end_ptr; ++start_ptr)
  {
    cout << "[ " << (*start_ptr)[0] << " ]" << endl;
  }

  std::cout << "----------------------------------" << std::endl;
  
  // 正则分词: 分出所有的字母
  cregex regxB = cregex::compile("\\w+", icase);
  cregex_token_iterator pos(my_string_b, my_string_b + strlen(my_string_b), regxB);
  for (; pos != cregex_token_iterator(); ++pos)
  {
    cout << "[ " << *pos << " ]" << endl;
  }

  system("pause");
  return 0;
}

1.14 正则切割与过滤

boost::cregex_token_iterator()与boost::regex_replace()都是Boost库中用于正则表达式处理的函数。

cregex_token_iterator,用于将一个字符串分解成子字符串序列,其中根据正则表达式的匹配模式。我们可以使用boost::regex_token_iterator对象迭代访问这些子字符串,每次迭代将获得一个匹配的子字符串。

regex_replace,函数则是用于正则表达式替换的函数,它可以根据正则表达式的匹配模式,在输入字符串中搜索并替换与指定模式匹配的字符串。

#include <iostream>
#include <string>
#include <algorithm>
#include <boost\algorithm\string.hpp>
#include <boost\xpressive\xpressive.hpp>
#include <boost\xpressive\regex_iterator.hpp>

using namespace std;
using namespace boost;

int main(int argc, char const *argv[])
{
  using namespace boost::xpressive;

  char my_string[] = "*lyshark*||+administrator+||root!!||metaper";
  cregex_token_iterator pos;

  // 正则切割
  cregex split_regx = cregex::compile("\\|\\|");
  pos = cregex_token_iterator(my_string, my_string + strlen(my_string), split_regx, -1);
  for (; pos != cregex_token_iterator(); ++pos)
  {
    cout << "[ " << *pos << " ]" << endl;
  }

  // 正则格式化(小写转大写)
  struct formater
  {
    string operator()(cmatch const &m) const
    {
      return boost::to_upper_copy(m[0].str());
    }
  };

  char my_string_b[] = "*lyshark*||+administrator+||root!!||metaper||*lyshark*";
  cregex regxC = cregex::compile("\\w+", icase);
  cout << "小写转大写输出: " << regex_replace(my_string_b, regxC, formater()) << endl;


  // 正则过滤(过滤出所有lyshark)
  struct grep_formater
  {
    string operator()(cmatch const &m) const
    {
      std::cout << m[0].str() << std::endl;

      if (m[0].str() == "lyshark")
      {
        return "SuperUser";
      }
      return boost::to_upper_copy(m[0].str());
    }
  };
  cout << "替换输出: " << regex_replace(my_string_b, regxC, grep_formater()) << endl;

  system("pause");
  return 0;
}

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/5c088cb9.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/893757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker 搭建 ElasticSearch

1、拉取镜像 docker pull elasticsearch:8.8.12、在机器本地新建文件夹并赋予权限 mkdir -p /home/elasticsearch/configmkdir -p /home/elasticsearch/datamkdir -p /home/elasticsearch/pluginschmod 777 /home/elasticsearch/configchmod 777 /home/elasticsearch/datachm…

全开放式耳机什么品牌好?全开放式耳机推荐

​在音乐的世界中&#xff0c;开放式耳机提供了更真实、更通透的音质体验&#xff0c;开放式耳机采用不入耳设计&#xff0c;佩戴更为稳固舒适&#xff0c;还允许外界的声音自由地流入&#xff0c;使你在享受音乐的同时&#xff0c;也能保持对周围环境的感知&#xff0c;户外运…

WebDriver API及对象识别技术

html页面的iframe的切换 定位到客户管理 新增客户 会无法定位到新增客户,因为在另外一个iframe框架之中。 iframe是html中的框架标签,表示文档中可以嵌入文档,或者说是浮动的框架。在selenium中iframe同样如此,如果驱动器对象处于当前iframe框架中,此时驱动器对象是…

商业计划书的写作

商业计划书是一份描述企业发展的文件&#xff0c;是企业经营者素质的体现&#xff0c;是企业拥有良好融资能力、实现跨越式发展的重要条件之一。一份好的商业计划书&#xff0c;是建立投资者、合作者、消费者信心的重要依据&#xff0c;获得、投资、合作的关键。 企业商业计划…

❤ Vue2完整项目进一步配置配置(二)

❤ Vue2完整项目进一步配置配置&#xff08;二&#xff09; &#xff08;1&#xff09;配置自定义端口号&#xff1a;9528 port: 9528, // 端口号autoOpenBrowser: true, //是否自动打开浏览器

《知识图谱互联互通白皮书》正式发布,合合信息携手电子标准院共同推动技术规范化发展

知识图谱是将各种数据和信息进行结构化处理后形成的一种“语义知识库”&#xff0c;也是人工智能的重要组成部分。 为助力知识图谱系统间的互联互通&#xff0c;推进知识要素的规范、有序和可靠流动&#xff0c;近期&#xff0c;中国电子技术标准化研究院依托知识图谱产业推进…

适用于Android™的Windows子系统Windows Subsystem fo r Android™Win11安装指南

文章目录 一、需求二、Windows Subsystem for Android™Win11简介三、安装教程1.查看BIOS是否开启虚拟化2.安装Hyper-V、虚拟机平台3.启动虚拟机管理程序(可选)4.安装适用于Android™的Windows子系统5.相关设置 一、需求 需要在电脑上进行网课APP&#xff08;无客户端只有App&…

零基础学Python,哪些入门知识必学?学习步骤是什么?

众所周知&#xff0c;Python以优雅、简洁著称&#xff0c;入行门槛低&#xff0c;可以从事Linux运维、Python Web网站工程师、Python自动化测试、数据分析、人工智能等职位&#xff0c;薪资待遇呈上涨趋势。很多人都想学习Python&#xff0c;那么零基础学Python应该学习哪些入门…

批次效应分析

写在前面 批次效应分析,在医学芯片研究中,使用不同芯片进行分析时常用的数据处理方式,但是很多同学处理后的数据,存在不满意的情况。因此,到处咨询,各种查教程。今天,使用简短的时间分享该数据处理教程。 最终分析结果 欢迎投稿 小杜一直在分享自己平时学习笔记,因此…

HTTP响应状态码大全:从100到511,全面解析HTTP请求的各种情况

文章目录 前言一、认识响应状态码1. 什么是HTTP响应状态码2. Http响应状态码的作用3. 优化和调试HTTP请求的建议 二、1xx 信息响应1. 认识http信息响应2. 常见的信息响应状态码 三、2xx 成功响应1. 认识HTTP成功响应2. 常见的成功响应状态码 四、3xx 重定向1. 认识http重定向2.…

Cat(7):CAT监控界面介绍

1 DashBoard DashBoard仪表盘显示了每分钟出现错误的系统及其错误的次数和时间。 点击右上角的时间按钮可以切换不同的展示时间&#xff0c;-7d代表7天前&#xff0c;-1h代表1小时前&#xff0c;now定位到当前时间 上方的时间轴按照分钟进行排布&#xff0c;点击之后可以看到该…

elementui表格嵌套上传文件直传到oss服务器(表单上传)

提示&#xff1a;记录项目中遇到的问题&#xff0c;仅供参考 文章目录 前言一、vue代码二、js接口请求代码 前言 项目需求是在表格中嵌套一个上传图片的功能&#xff0c;并且回显选择的图片和已上传的图片&#xff0c;再通过点击操作列中上传按钮才开始上传&#xff0c;使用的…

蓝牙资讯|安卓将加强耳机音量监控,耳机查找功能将更加普遍

为了保护用户的听力健康&#xff0c;Android 14 将增加一项新功能&#xff0c;当用户使用耳机听音乐时&#xff0c;如果音量过高或持续时间过长&#xff0c;系统会发出警告&#xff0c;并自动降低音量。这个功能叫做“耳机音量过高警告&#xff08;headphone loud sound alert&…

蓝奥声智能工业安全用电监测与智慧能源解决方案

能源管理变得越来越重要。如今&#xff0c;能源成本已成为国内预算的核心因素&#xff0c;因此用电监控对大多数现代企业来说都很重要。许多企业在日常能源消耗监控中面临着一些挑战&#xff0c;因为它们的规模庞大&#xff0c;基础设施多样化&#xff0c;灵活性低&#xff0c;…

每天一道leetcode:剑指 Offer 55 - I. 二叉树的深度(适合初学者树图论层次遍历)

今日份题目&#xff1a; 输入一棵二叉树的根节点&#xff0c;求该树的深度。从根节点到叶节点依次经过的节点&#xff08;含根、叶节点&#xff09;形成树的一条路径&#xff0c;最长路径的长度为树的深度。 示例 给定二叉树 [3,9,20,null,null,15,7]&#xff0c; 3/ \9 20…

深入探索智能未来:文本生成与问答模型的创新融合

深入探索智能未来&#xff1a;文本生成与问答模型的创新融合 1.Filling Model with T5 1.1背景介绍 该项目用于将句子中 [MASK] 位置通过生成模型还原&#xff0c;以实现 UIE 信息抽取中 Mask Then Filling 数据增强策略。 Mask Then Fill 是一种基于生成模型的信息抽取数据…

科学规划假期学习,猿辅导《暑假一本通》获用户好评

一直以来&#xff0c;有效利用寒、暑假期查漏补缺、解决偏科问题、初步养成好的自主学习习惯等是很多家长对学生的期望。但当前市面上教辅品类繁多&#xff0c;内容质量却参差不齐。据北京开卷统计数据显示&#xff0c;2022年前三季度零售市场上的教辅图书超过8000种&#xff0…

高级AI赋能Fortinet FortiXDR解决方案

扩展检测和响应 (XDR&#xff1a;Extended Detection and Response) 解决方案旨在帮助组织整合分布式安全技术&#xff0c;更有效地识别和响应活动的威胁。虽然 XDR 是一种新的技术概念&#xff0c;但其构建基础是端点检测和响应 (EDR&#xff1a;Endpoint Detection and Respo…

CW4L2-3A-S电源滤波器

CW4L2-3A-T CW4L2-6A-T CW4L2-10A-T CW4L2-20A-T CW4L2-3A-S CW4L2-6A-S CW4L2-10A-S CW4L2-20A-S 安装位置应靠近电源线入口处&#xff0c;尽可能滤除沿电源线侵入和窜出的电磁干扰。 确保滤波器外壳与设备机箱良好电接触&#xff0c;并接好地线。 滤波器的输入输出…

PoseiSwap 更新质押系统,并将在 8 月18 日开启“Trident ”快照

自 DeFi Summer 后&#xff0c;DeFi 设施整体的形态并未发生本质的变化&#xff0c;我们看到 DeFi 应用仍旧不具向外长期捕获价值、用户的能力&#xff0c;老旧叙事导致 DeFi 赛道整体的发展停滞不前。伴随着行业进入到下行周期&#xff0c;DeFi 赛道的资金、用户不断出逃&…