《白话C++》第10章 Page55 10.3.4 string的武器库①

本文介绍了C++标准库中string类的不足以及Boost库如何提供丰富的string算法,着重讲解了大小写转换、去除空白符以及字符分类判断的功能,包括大小写转换函数、去空白符操作及其变体,以及各类字符分类判断的使用方法。
摘要由CSDN通过智能技术生成

10.3.4  string的武器库

C++标准库基本将string当成一个“字符容器”,然后在其上可套用多种通用算法,造成字符串算法严重不足

boost又一次承担了救火员的角色,提供了丰富的字符串算法,并且同时支持string和wstring。

这些扩展字符串算法,在<boost/algorithm/string.hpp>文件中声明,它们并不仅仅适用于string或wstring,也适用于其他一些容器,但这里仍然简单称它们为“string_algo”.

string_algo中的许多算符都有多个版本,通过名字上的修饰字符不同,可做如下识别:

(1)前缀 i: 表示该算法不区分大小写;

(2)后缀 _copy: 表示该算法将复制一份入参,再对复制品修改,不影响原入参;

(3)后缀 _if: 表示该算法将提供一个函数对象,仅当该条件满足才处理过程数据。

和字符串最常相关的处理,无非是:大小写转换去空白符分类判断查找替换删除分割合并

1.大小写转换

//直接转换成大写
void to_upper(T& input); 
//直接转换成小写
void to_lower(T& input); 
//将复制品转换成大写并返回
T to_upper_copy(T const& input); 
//将复制品转换成小写并返回
T to_lower_copy(T const& input); 

这里的T代表std::string或std::wstring甚至其他类型,因此实际实现的都是模板,为了描述方便,我们将它们写成函数的形式。

...
#include <string>
#include <boost/algorithm/string.hpp>
...

namespace str_algo = boost::algorithm;
...
void test_upper_lower()
{
    string s = str_algo::to_upper_copy(string("hello"));
    cout << s << std::endl;
    str_algo::to_lower(s);
    cout << s << std::endl;
}

2.去空白符

当从文件,网络,数据库读入字符串时,往往需要去除其两端的空白字符:
 

//去除Input左边的空白符
void trim_left(T& Input); 
//去除Input右边的空白符
void trim_right(T& Input);
//去除Input两边的空白符
void trim(T& Input);

trim函数同样都已_copy版本,用于在得到去除空白符之后的复制品。

trim函数还提供了_if 版本,可用于去除特定的字符,比如有一个字符串内容为:"123ABC00DE456",若要将其改变成“ABC00DE”,可以他提供一个函数对象,作为判断式传入

bool is_digit(char c)
{
    return (c >= '0' && c <= '9');
}

void test_trim()
{
   string s = "   ABC  DEF ";
   str_algo::trim(s);
   cout << s << endl;

   s = "123ABC00DE456";

   string s2 = str_algo::trim_copy_if(s, is_digit);
   cout << s2 << endl;
}

3.分类判断

前面我们动手写了一个用于判断给定字符是否为数字的判断式:is_digit。所谓“判断式(predicate)”,通常就是一个函数或函数对象,返回值是bool值,而入参则是调用者所要求提供判断的数据,在string_algo中,它是广义上的“字符”类型。

string_algo提供的常用字符分类判断如表10-3所列。

表10-3 字符分类判断式
分类判断式含义备注
is_space是否空白字符至少包括 ' '  '\t'  '\r'  '\n'
is_alnum是否字母或数字
is_alpha是否字母
is_punct是否标点符号
is_lower是否小写字母
is_upper是否大写字母
is_print是否可打印字符
is_digit是否数字(十进制)
is_xdigit是否数字(十六进制)
is_any_of是否是指定字符串中的某个字符
is_form_range是否指定范围内的字符需一对入参表示范围:[from, to]

注意,这些函数若要支持汉字(比如汉字标点符号),需在操作系统环境支持,

mingw下由于没有实现汉字环境的的本地化(locate),所以可知其明确不支持汉字。

下面的调用代码编译不了:

boost::algorithm::is_space('\n');

因为要判断一个字母是不是空白符数字,不是那么简单,我们通常只处理英美的字符,但在法语和德语中,它们的字母表是什么?这就需要前面的本地化工作

is_space()等函数,事实上有一个默认的locate参数,用于传递各国的本地化处理,中国字符由于涉及宽字符等,所以mingw环境下没有实现,但欧洲主要语言的字符的类型判断,确实可以通过本国locate参数实现,如果什么都不传,那么默认其就是纯C的环境,基本可认为就是英美字符体系。

接着,is_space(const std::locale& Loc = std::locale())等函数,事实上创建了另外一个对象(正好也是一个函数对象),然后再调用那个临时对象的括号重载操作;

boost::algorithm::is_space()('\n');//编译通过

也有部分判断式不需要locate信息,但它们采用类似的设计,即通过入参先生成一个中间临时对象,然后再调用临时对象的括号操作符重载函数。比如,is_from_range需要这样调用:

//判断b是否在'A'和'z'之间
boost::algorithm::is_from_range('A', 'z')('b');

而  is_any_of 这么调用:

//判断'B'是不是"ABCDEFG"中的某个字符
cout << str_algo::is_any_of("ABCDEFG")('B');

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值