Boost库的字符串处理算法

C++中的字符串类型

说起C++中的字符串类型当仁不让的自然就是std::stringstd::string是模板std::basic_string的一个实例化,另外还有三个实例化std::wstringstd::u16stringstd::u32string,不过不是很常用。

 
 
std::basic_string<T>
std::string std::basic_string<char>
std::wstring std::basic_string<wchar_t>
std::u16string std::basic_string<char16_t>
std::u32string std::basic_string<char32_t>

具体可以参考:http://en.cppreference.com/w/cpp/string/basic_string

std::string

标准库中,std::string的成员函数和相关的算法特别多,从上面给出的链接里的内容,粗略计算一下,包括所有的重载函数,也有百余个了。但是在实际的工作使用中,很多时候,总是会感觉,C++对字符串的处理支持实在是弱爆了……感觉这个具有百余个方法的“巨”类用起来总是捉襟见肘。

std::string中的很多操作都是基于迭代器的——这样的话,很多操作,我们都需要先调用find拿到操作区间的迭代器,然后再进行实际的操作。成员函数中:inserterasereplace都是基于迭代器的操作。

同时,std::string也没有提供一些常用的字符串处理的方法,比如:简单的大小写转换,字符串连接,字符串分割等。

注:
std::string提供了数字和字符串相互转换的算法。

  1. 字符串==>数字
    stoi string to int
    stol string to long
    stoll string to long long
    stoul string to unsigned long
    stoull string to unsigned long long
    stof string to float
    stod string to double
    stold string to long double

  2. 数字==>字符串
    to_string
    to_wstring

Boost中的字符串处理

素有C++准标准库之称的Boost库通过算法的形式,提供了一些处理C++字符串的函数,虽然比起Java或者其它一些动态语言还是略显不足,但也算在一定程度上方便了我们对C++的字符串处理。

除了字符串处理算法,Boost库还提供了一个正则表达式的函数库Boost.Regex。Boost.Regex已经被纳入到C++11的标准之中,但是我们常用的gcc4.8的C++标准库还没有实现正则表达式。实际上,gcc4.8已经定义了标准库正则表达式的类型和接口,但是只是占了个坑,并没有真正实现……结果可以编译通过,但是运行一直抛出异常。gcc4.9才真正实现了标准库的正则表达式(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 )。

这篇文章暂时只介绍Boost库的字符串处理算法。实际上,Boost库的正则表达式库和标准库的正则表达式库,除了命名空间不一样(一个是boost,一个是std),其它用法都是一样的。

Boost提供的字符串算法

  • Boost库的字符串算法的头文件:#include <boost/algorithm/string.hpp>
  • 字符串大小写转换

    • C++标准库竟然连一个字符串大小写的转换函数都没有提供,还好Boost库提供了。
    • boost::algorithm::to_upper()boost::algorithm::to_lower()直接修改传入的字符串,将其转换为对应字符串的大写或小写。
    • boost::algorithm::to_upper_copy()boost::algorithm::to_lower_copy()返回一个新的大写或小写字符串。
    • Boost的很多修改字符串的算法都提供了'直接修改传入字符串,名字不带copy'和'返回一个新的字符串,名字带copy'两个版本。下同。
    • 例子:
           
           
      #include <boost/algorithm/string.hpp>
      #include <string>
      #include <iostream>
      using namespace std;
      int main()
      {
      std::string s("AbCdefG123 HijkLmn");
      cout << boost::algorithm::to_upper_copy(s) << endl;
      boost::algorithm::to_lower(s);
      cout << s << endl;
      }
      输出结果:
      ABCDEFG123 HIJKLMN
      abcdefg123 hijklmn
  • 子串删除。

    • std::string提供了几个erase成员函数:
      • basic_string& erase(size_type index = 0, size_type count = npos);
      • iterator erase(iterator position);
      • iterator erase(const_iterator position);
      • iterator erase(iterator first, iterator last);
      • iterator erase(const_iterator first, const_iterator last);
    • std::string::erase系列的函数的参数都是基于"字符串的位置"的----要么是index,要么是迭代器。
    • STL提供的关于删除的算法:
      • ForwardIt remove(ForwardIt first, ForwardIt last, const T& value);
      • ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p);
      • OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first, const T& value);
      • OutputIt remove_copy_if(InputIt first, InputIt last, OutputIt d_first, UnaryPredicate p);
    • STL提供的remove系列的算法,由于其需要与其他容器通用,其删除时的比较函数只能是一个字符之间的比较(std::string中的一个字符相当于vector中的一个元素)。
    • Boost提供的删除字符串子串的算法。
      • erase_all() 删除主串中所有相等的子串。
      • erase_first() 删除主串中第一个相等的子串。
      • erase_nth() 删除主串中的第n个子串。注意这里的n是从0开始的。
      • erase_head() 删除主串的前n个字符。
      • erase_tail() 删除组成的后n个字符。
      • erase系列的copy版本
 
 
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace std;
int main()
{
std::string s("AbCdefG123 HijkLmn");
s += s;
s += s;
string s0 = s;
cout << "Input String: " << s0 << endl;
cout << boost::algorithm::erase_all_copy(s0, "AbC") << endl;
cout << boost::algorithm::ierase_all_copy(s0, "ABC") << endl;
cout << boost::algorithm::erase_first_copy(s0, "defG123") << endl;
cout << boost::algorithm::ierase_first_copy(s0, "DEFG123") << endl;
cout << boost::algorithm::erase_nth_copy(s0, "HijkLmn", 1) << endl;
cout << boost::algorithm::ierase_nth_copy(s0, "HIJKLMN", 1) << endl;
cout << boost::algorithm::erase_head_copy(s0, 3) << endl;
cout << boost::algorithm::erase_tail_copy(s0, 5) << endl;
}
输出结果:
Input String: AbCdefG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmn
defG123 HijkLmndefG123 HijkLmndefG123 HijkLmndefG123 HijkLmn
defG123 HijkLmndefG123 HijkLmndefG123 HijkLmndefG123 HijkLmn
AbC HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmn
AbC HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmn
AbCdefG123 HijkLmnAbCdefG123 AbCdefG123 HijkLmnAbCdefG123 HijkLmn
AbCdefG123 HijkLmnAbCdefG123 AbCdefG123 HijkLmnAbCdefG123 HijkLmn
defG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmn
AbCdefG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 HijkLmnAbCdefG123 Hi
  • Boost提供的字符串子串查找算法
    • 说明: Boost的这些字符串的find算法的返回值都是boost::iterator_range类型的一对迭代器。
    • find_first() 查找第一个匹配的子串。std::string::find能实现一样的功能。find_first的实现应该是封装了这个成员函数,不过个人感觉这个算法用起来更方便。
    • find_last() 查找最后一个匹配的子串。std::string::rfind能实现一样的功能。
    • find_nth() 查找第n(n>=0)个匹配的字符串。
    • find_head(s, n) 返回字符串的前n个字符。
    • find_tail(s, n) 返回字符串的最后n个字符。
    • 例子:
 
 
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace std;
int main()
{
std::string s("AbCdefG123 HijkLmn");
s += s;
s += s;
cout << "Input String: " << s << endl;
boost::iterator_range<std::string::iterator> itRange = boost::algorithm::find_first(s, "123");
cout << itRange << endl;
cout << itRange.begin() - s.begin() << endl;
cout << itRange.end() - s.begin() << endl;
itRange = boost::algorithm::find_last(s, "123");
cout << itRange << endl;
cout << itRange.begin() - s.begin() << endl;
cout << itRange.end() - s.begin() << endl;
itRange = boost::algorithm::find_nth(s, "123", 1);
cout << itRange << endl;
cout << itRange.begin() - s.begin() << endl;
cout << itRange.end() - s.begin() << endl;
itRange = boost::algorithm::find_head(s, 5);
cout << itRange << endl;
cout << itRange.begin() - s.begin() << endl;
cout << itRange.end() - s.begin() << endl;
itRange = boost::algorithm::find_tail(s, 5);
cout << itRange << endl;
cout << itRange.begin() - s.begin() << endl;
cout << itRange.end() - s.begin() << endl;
}
输出结果:
123
7
10
123
61
64
123
25
28
AbCde
0
5
jkLmn
67
72
  • 连接字符串
    • Boost库提供了join()算法接受一个字符串容器作为第一个参数,根据第二个参数将这些字符串连接起来。
    • 例子:
 
 
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<string> sVec{"ABC", "def", "GHIJK", "123456"};
cout << boost::algorithm::join(sVec, "+**+") << endl;
}
输出结果:
ABC+**+def+**+GHIJK+**+123456
  • 替换字符串
    • std::string提供的replace成员函数的重载很多,但是都只提供了基于位置(index或iterator)的替换操作 (http://en.cppreference.com/w/cpp/string/basic_string/replace), 没有基于子串比较再替换的操作。Boost提供了基于比较的子串替换算法。
    • replace_first 替换第一个匹配的字符串。
    • replace_nth 替换第n(n>=0)个匹配的字符串。
    • replace_last 替换最后一个匹配的字符串。
    • replace_all 替换所有匹配的字符串。
    • replace系列的copy版本。
    • 例子:
 
 
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string s("AbcDeFGHIJklmn");
s += s;
s += s;
cout << "Input String: " << s << endl;
cout << boost::algorithm::replace_all_copy(s, "AbcD", "**") << endl;
cout << boost::algorithm::replace_first_copy(s, "AbcD", "**") << endl;
cout << boost::algorithm::replace_last_copy(s, "AbcD", "**") << endl;
cout << boost::algorithm::replace_nth_copy(s, "AbcD", 1, "**") << endl;
}
输出结果:
Input String: AbcDeFGHIJklmnAbcDeFGHIJklmnAbcDeFGHIJklmnAbcDeFGHIJklmn
**eFGHIJklmn**eFGHIJklmn**eFGHIJklmn**eFGHIJklmn
**eFGHIJklmnAbcDeFGHIJklmnAbcDeFGHIJklmnAbcDeFGHIJklmn
AbcDeFGHIJklmnAbcDeFGHIJklmnAbcDeFGHIJklmn**eFGHIJklmn
AbcDeFGHIJklmn**eFGHIJklmnAbcDeFGHIJklmnAbcDeFGHIJklmn
  • 消除字符串两端的特殊字符
    • 很多时候,我们会希望删除字符左右两边的空白字符。Boost提供了几个算法来实现这个功能。
    • trim_left() 删除字符串左边的空白。
    • trim_right() 删除字符串右边的空白。
    • trim() 删除字符串左右两边的空白。
    • trim系列的copy版本。
    • 有时候,我们想要删除的不仅仅是字符串左右两边的空白,而是其它一下特定的字符。
    • trim_left_if()
    • trim_right_if()
    • trim_if()
    • trim_if系列的copy版本,如果trim_left_copy_if...
    • Boost库的if系列算法通常传入一个"谓词参数", 如:
      • is_any_of
      • is_space 是否是空白字符。
      • is_alnum 是否是字母或数字。
      • is_alpha 是否时字母。
      • is_cntrl 是否控制字符。
      • is_digit 是否十进制数字。
      • is_graph 是否图形字符。
      • is_lower 是否小写字母。
      • is_print 是否可打印字符。
      • is_punct 是否标点符号。
      • is_upper 是否大写字符。
      • is_xdigit 是否十六进制数字。
      • is_from_range(from, to) 是否from <= ch <= to。
      • 上面这些都可以通过&&,||,!组合起来。
    • 例子:
 
 
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string s(" AbcDeF GHIJklmn ");
cout << "Input String: <" << s << '>' << endl;
cout << '<' << boost::algorithm::trim_left_copy(s) << '>' << endl;
cout << '<' << boost::algorithm::trim_right_copy(s) << '>' << endl;
cout << '<' << boost::algorithm::trim_copy(s) << '>' << endl;
cout << endl;
string s1("==ABCD Efgh=IJK==-== ");
cout << "Input String: <" << s1 << '>' << endl;
cout << '<' << boost::algorithm::trim_copy_if(s, boost::algorithm::is_any_of(" -=")) << '>' << endl;
}
输出结果:
Input String: < AbcDeF GHIJklmn >
<AbcDeF GHIJklmn >
< AbcDeF GHIJklmn>
<AbcDeF GHIJklmn>
Input String: <==ABCD Efgh=IJK==-== >
<AbcDeF GHIJklmn>
  • 匹配比较
    • starts_with(s, sub) s是否以sub开头, 即前缀。
    • ends_with(s, sub) s是否以sub结尾, 即后缀。
    • contains(s, sub) s是否包含sub。
    • 例子
 
 
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string s("abcdefGHIJKLMN");
cout << boost::algorithm::starts_with(s, "abcd") << endl;
cout << boost::algorithm::starts_with(s, "abcD") << endl;
cout << boost::algorithm::ends_with(s, "MN") << endl;
cout << boost::algorithm::ends_with(s, "mn") << endl;
cout << boost::algorithm::contains(s, "efG") << endl;
cout << boost::algorithm::contains(s, "WWW") << endl;
}
输出结果:
1
0
1
0
1
0
  • 分割字符串
    • Boost库提供了split算法,根据指定的字符集合对字符串进行分割。
    • 例子:
 
 
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string s("abc 123 cde");
vector<string> sVec;
boost::algorithm::split(sVec, s, boost::algorithm::is_space());
for (auto& str : sVec)
{
cout << str << endl;
}
cout << "--------分割线--------" << endl;
s = " abc 123 cde ";
boost::algorithm::split(sVec, s, boost::algorithm::is_space());
for (auto& str : sVec)
{
cout << str << endl;
}
cout << "--------分割线--------" << endl;
s = "--abc 123--cde-";
boost::algorithm::split(sVec, s, boost::algorithm::is_any_of(" -"));
for (auto& str : sVec)
{
cout << str << endl;
}
}
输出结果:
abc
123
cde
--------分割线--------
//空行
abc
123
cde
//空行
//空行
//空行
--------分割线--------
//空行
//空行
abc
123
//空行
cde
//空行
  • 注: boost的很多(但不是全部)字符串算法都带有忽略大小写的版本,相差只是以'i'开头。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值