概述

在未使用Boost库时,使用STL的std::string处理一些字符串时,总是不顺手,特别是当用了C#/Python等语言后trim/split总要封装一个方法来处理。如果没有形成自己的common代码库,那就悲剧了,每用一次都要写一次,虽然难度不大,但是每次重复这样工作也还是比较费劲。一般通过STL进行封装如下:

// trim from start
inline std::string &LeftTrim(string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::pointer_to_unary_function<int, int>(isspace))));
return s;
} // trim from end
inline std::string &RightTrim(string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::pointer_to_unary_function<int, int>(isspace))).base(), s.end());
return s;
} // trim from both ends
inline tstring &Trim(tstring &s)
{
return LeftTrim(RightTrim(s));
} inline std::vector<string> &Split(const string &s, char delim,
std::vector<string> &elems, bool bKeepEmpty=false)
{
stringstream ss(s);
string item;
while(std::getline(ss, item, delim)) {
if(item.empty() && !bKeepEmpty)
continue;
elems.push_back(item);
}
return elems;
} inline std::vector<string> Split(const string &s, char delim) {
std::vector<tstring> elems;
return Split(s, delim, elems);
}

同时我还是那种没有common代的一类懒汉。当开始使用Boost的时候,特别是看到Boost.StringAlgorithms库时,我可以说,我内心是激动的吗?居然有一个这么顺手的工具,过去我居然没有用,为什么STL这个标准库不加上它呢?废话不多说,谨记习大大箴言:撸起袖子,就是干!

STL标准库中std::string有一些成员函数可以查找子串/访问字符和执行基本的字符串功能。std::string可以把它看成是char类型的序列容器(标准库定义如下代码),可以使用标准库中的算法进行处理,但是毕竟这些算法不是专门未字符串而写,故有时候就稍显‘笨拙‘

typedef std::basic_string<char> std::string;
typedef std::basic_string<wchar_t> std::wstring;

Boost.Boost.StringAlgorithms库的出现改变了这个局面,其内包含了非常全面的字符串算法库,提供了大量的方法来操作字符串,比如:分割/修剪/特定模式字符串查找等等一些列方法。

虽然Boost.StringAlgorithms是被设计用来处理字符串的,但是它还有更强悍的功能,并不一定是string,wstring或者任何以basic_string的模版类,可以是符合boost.range(后面回专门讲解)要求的容器,他可以是容器对象如:vector/deque/list等,不过本文主要还是定位到字符串的处理。

首先Boost.StringAlgorithms库需要包含头文件"boost/algorithm/string.hpp"中,位于命名空间boost::algorithm,但是被using语句引入到了boost命名空间。可通过如下代码进行引入:

#include <boost/algorithm/string.hpp>
using namesapce boost;

注: 该库遵循标准库的命名规范,使用小写形式,同时通过不同前后缀来区分不同版本,具体规则如下

  1. 前缀i:忽略大小写
  1. 后缀_copy: 不改变当前字符串,返回处理后的拷贝结果,否则就是在原字符串上进行调整操作
  2. 后缀_if: 需要一个作为判断式的谓词函数对象

本文从如下几个方面进行介绍:

  • 大小写转化
  • 判断式
  • 分类
  • 修剪
  • 查找及迭代器
  • 替换和删除
  • 分割与合并

大小写转化

Boost.StringAlgorithms库可以快速高效的将字符串进行大小写转换,主要使用如下两个方法,带后缀_copy的方法把输入转换后进行输出

to_upper();	//字符串转化成大写形式
to_lower(); //字符串转换成小写形式

测试代码:

void test_to_case()
{
string str = "The C++ Boost Libraries";
cout << str << endl;
cout << to_upper_copy(str) << endl;
cout << str << endl;
to_lower(str);
cout << str << endl;
}

输出结果如下:

The C++ Boost Libraries
THE C++ BOOST LIBRARIES
The C++ Boost Libraries
the c++ boost libraries

判断式

判断式算法可以检测两个字符串之间的关系,包括一下几种,此处我将函数对象也罗列到一起:

lexicongraphical_compare(str1, str2)	//按照字典顺序判断字符串大小
starts_with(str1, str2) //判断字符串是否以另一个开始
ends_with(str1, str2) //判断字符串是否以另一个结束
contains(str1, str2) //判断字符串是否包含另一个
equals(str1, str2) //两个字符串是否相等
all(str, pred) //检测字符串中所有元素是否满足指定谓词
is_equal()(str1,str2) //函数对象,判断字符串是否相等
is_less()(str1, str2) //函数对象,判断字符串str1是否小于str2
is_not_greater()(str1,str2) //函数对象,判断字符串str1是否不大于str2

注: 函数对象后面有两对括号,第一对括号是创建一个临时对象;第二对括号是调用操作符operator()

测试代码如下:

void test_compare_string()
{
string str = "Boost C++ Libraries";
cout.setf(std::ios::boolalpha);
cout << starts_with(str, "Boost") << endl; // true
cout << ends_with(str, "Libraries") << endl; // true
cout << contains(str, "C++") << endl; // true
cout << equals(str, to_lower_copy(str)) << endl; // false
cout << all(str, is_lower()) << endl; // false string str2 = "STL C++ Libraries";
cout << is_equal()(str, str2) << endl; // false string str3 = to_upper_copy(str);
cout << is_less()(str, str3) << endl; // false
}

分类

Boost.StringAlgorithms提供一组分类函数(谓词对象),检测一个字符是否符合某种特性。

is_space()	// 字符是否为空格或制表符
is_alnum() // 字符是否为字母或数字
is_alpha() // 字符是否为字母
is_cntrl() // 字符是否为控制字符
is_digit() // 字符是否为十进制数字
is_graph() // 字符是否为图形字符
is_lower() // 字符是否为小写字符
is_print() // 字符是否为可打印字符
is_punct() // 字符是否为表点字符
is_upper() // 字符是否为大写字符
is_xdigit() // 字符是否为十六进制字符
is_any_of() // 字符是否为字符序列中任意字符
if_from_range() // 字符是否位于指定区间中

这些函数并不真正检测字符,而是返回一个函数对象,通过调用函数对象的operator()来进行分类判断,内部实现如下:

 inline detail::is_classifiedF
is_alpha(const std::locale& Loc=std::locale())
{
return detail::is_classifiedF(std::ctype_base::alpha, Loc);
}

示例代码:

void test_classified()
{
std::string s = "Boost C++ Libraries";
std::vector<std::string> vs;
split(vs, s, is_space());
std::cout << vs.size() << endl; // 3
}

修剪

Boost.StringAlgorithms提供三个修剪函数,如前文我们一般实现的代码,分别修剪字符串开头或结尾的空格(该方法的_if版本可接收其他谓词对象,如上文提到的分类)

trim_left()
trim_right()
trim()

示例代码如下:

void test_trim()
{
std::string s = " Boost C++ Libraries!!!--166";
cout << trim_left_copy(s) << endl; //默认去除空格
cout << trim_right_copy_if(s, is_digit() || is_space()) << endl;//通过||组合去除数字和空格
cout << trim_copy_if(s, is_space() || is_punct() || is_digit()) << endl;
cout << trim_copy_if(s, is_any_of("! -61B")) << endl;
}

此处调用is_any_of谓词方法,生成谓词以验证作为参数传入的字符是否在给定的字符串中存在

结果如下:

Boost C++ Libraries!!!--166
Boost C++ Libraries!!!--
Boost C++ Libraries
oost C++ Libraries

查找

以下方法返回一个迭代器的pair对象boost::iterator_range,其内部定义为:std::pair<iterator, iterator>可以通过begin和hend进行访问,其实就是返回一个容器区间

find_first()	//查找字符串再输入中第一次出现的位置
find_last() //查找字符串再输入中最后一次出现的位置
find_nth() //查找字符串再输入中第N次出现的位置(其中N的索引从0开始)
find_head() //取一个字符串的N个开头,和string的substr(0,N)取字串类似
find_tail() //取一个字符串的末尾N个字符子串
find_iterator() //内部定义如下
template<typename Range1T, typename Range2T>
inline iterator_range find_first(Range1T& Input, const Range2T& Search) template<typename Range1T, typename Range2T>
inline iterator_range find_nth(Range1T& Input, const Range2T& Search, int Nth) template<typename Range1T, typename Range2T>
inline iterator_range find_head(RangeT& Input, int N)

测试代码如下:

void test_find()
{
std::string s = "Boost C++ Libraries";
iterator_range<std::string::iterator> iter = ifind_first(s, "c++");
cout << iter << endl; //C++
cout << "begin: " << *iter.begin() << ", end: " << *--iter.end() << endl; //begin: C, end: + iter = find_head(s, 5);
cout << iter << endl; //Boost
}

替换和删除

Boost.StringAlgorithms提供方法对字符串进行替换或删除操作与查找字符串方法很类似,是再查找后再对其进行替换删除操作,

replace/erase_first()	// 替换/删除一个字符串再输入中第一次出现
replace/erase_last() // 替换/删除一个字符串再输入中最后一次出现
replace/erase_nth() // 替换/删除一个字符串再输入中第N次出现
replace/erase_all() // 替换/删除一个字符串再输入中所有出现
replace/erase_head() // 替换/删除输入的开头
replace/erase_tail() // 替换/删除输入结尾

测试代码如下:

void test_replace()
{
std::string s = "Boost C++ Libraries";
cout << replace_first_copy(s, "+", "-") << endl;
cout << replace_nth_copy(s, "+", 1, "-") << endl;
cout << replace_head_copy(s, 5, "STL") << endl;
replace_last(s, "s", "s ");
cout << replace_tail_copy(s, 1, " is very good") << endl; cout << erase_first_copy(s, "C++") << endl;
cout << erase_all_copy(s, " ") << endl;
}

结果如下:

Boost C-+ Libraries
Boost C+- Libraries
STL C++ Libraries
Boost C++ Libraries is very good
Boost Libraries
BoostC++Libraries

分割与合并

Boost.StringAlgorithms提供了两个分割字符串的方法,find_all和split使用某种策略把字符串分隔成若干部分,并将分割后的字符串存入指定的容器。其中split需要给定一个谓词作为第三个参数以判断应该在字符串的哪个位置分割,find_all类似于普通的查找方法,它搜索所有匹配的字符串,加入到容器。

join是分隔算法的逆运算,它吧存储再容器中的字符串,通过指定的分隔符练成一个新的字符串

find_iterator和split_iterator可以再字符串中像迭代器那样遍历容器,执行操作或分隔

find_all()
split()
find_iterator()
split_iterator()
join()

示例代码如下:

void test_split_and_join()
{
std::string s = "Boost C++ Libraries BOOST c++ libraries LIBRARIES LIBraries";
vector<std::string> vs;
ifind_all(vs, s, "boost");
cout << vs.size() << endl; //2 list<iterator_range<string::iterator>> items;
split(items, s, is_space());
cout <<"size: "<< items.size() //size: 9
<< " the first: " << *items.begin() << endl; // the first: Boost list<std::string> ls = assign::list_of("Boost")("C++")("Libraries");
cout << join(ls,"*") << endl; //Boost*C++*Libraries
}

一起学习Boost标准库--Boost.StringAlgorithms库的更多相关文章

  1. 一起学习Boost标准库--Boost.texical_cast&format库

    今天接续介绍有关字符串表示相关的两个boost库: lexical_cast 将数值转换成字符串 format 字符串输出格式化 首先,介绍下lexical_cast ,闻其名,知其意.类似C中的at ...

  2. c++学习书籍推荐《超越C++标准库:Boost库导论》下载

    <超越C++标准库Boost库导论>不仅介绍了Boost库的功能.使用方法及注意事项,而且还深入讨论了Boost库的设计理念.解决问题的思想和技巧以及待处理的问题.因此,本书是一本了解Bo ...

  3. boost实用工具:assign库了解学习

    许多时候,我们需要为容器初始化或者赋值,填入大量的数据; STL容器仅提供了容纳这些数据的方法,但是填充的步骤是相当地麻烦(insert.push_back); 于是,boost::assign出现了 ...

  4. C++三大库boost、loki、stlport

    转: STL是一个标准,各商家根据这个标准开发了各自的STL版本.而在这形形色色的STL版本中,SGI STL无疑是最引人瞩目的一个.这当然是因为这个STL产品系出名门,其设计和编写者名单中,Alex ...

  5. [Boost]图形处理库Boost::Polygon

    Background 工作中经师傅指导学习应用到了Boost::Polygon这个库,相对于Boost::Geometry,Polygon出自Intel.抽象于芯片流程,于是更贴近于芯片设计流程应用. ...

  6. [C++Boost]程序参数项解析库Program_options使用指南

    介绍 程序参数项(program options)是一系列name=value对,program_options 允许程序开发者获得通过命令行(command line)和配置文件(config fi ...

  7. VS2010编译Boost 1.57 静态链接库

    http://www.cnblogs.com/cuish/p/4175491.html 0.前提 Boost库版本 1.57.0 下载地址 http://www.boost.org/users/his ...

  8. Dev-C++安装第三方库boost

    Dev-C++安装第三方库boost  转 https://www.jianshu.com/p/111571e4d6f5?utm_source=oschina-app 之前鉴于codeblocks界面 ...

  9. 【C/C++学院】0904-boost智能指针/boost多线程锁定/哈希库/正則表達式

    boost_array_bind_fun_ref Array.cpp #include<boost/array.hpp> #include <iostream> #includ ...

随机推荐

  1. C++ 各种继承

    博客园首页博问闪存新随笔联系订阅 管理随笔- 文章- 评论- C++继承:公有,私有,保护 公有继承(public).私有继承(private).保护继承(protected)是常用的三种继承方式. ...

  2. core Animation之CAAnimationGroup(动画群组)

    可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行 属性解析: animations:用来保存一组动画对象的NSArray 默认情况下,一组动画对象 ...

  3. 微信开发(一)基于Wx-java的微信分享功能

    最近在做微信服务号开发,简单总结一下,便于自己学习积累和分享给大家: 环境介绍: Spring+ Spring MVC +Mybatis 开发语言: JAVA 微信公众平台的开发中,微信只公布了一个基 ...

  4. 访问 .obj文件,由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射

    一.错误描述 HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加 MIME 映射. 最可能的原因: 可 ...

  5. Postman中使用post方式调用接口

    选择body-row,输入data

  6. C# Hadoop学习笔记(一)—环境安装

    一.安装环境 1,前期准备:官网下载“NuGet Package Manager”,按自己已有的VS环境下载对应版本: 2,利用NuGet下载Hadoop For .NET SDK,地址“http:/ ...

  7. git命令学习总结

    学习git 主要是因为github官网共享的资源很有学习价值.最近转型JAVA,所有特意去学习了下git软件.git软件可以去官网下载最新版本. 进入 git 仓库目录 右击 选中 Git Bash ...

  8. EasyUI 添加一行的时候 行号出现负数的解决方案

    原因是:在jquery_easyui.js 看方法 insertRow : function(_736, _737, row) 以下小代码算行号,if (opts.pagination) { _73c ...

  9. [bug]不包含“AsNoTracking”的定义

    摘要 在使用ef做查询优化的时候我们会用到AsNoTracking方法,但如果不引入命名空间,你就会出现不包含“AsNoTracking”的定义的错误. 解决办法 引入命名空间:System.Data ...

  10. 【转】classpath和环境变量设置

    http://www.360doc.com/content/12/0722/14/820209_225797366.shtml 在没有设置环境变量之前,我们可以通过直接在应用程序中加带相关信息来运行我 ...