一起学习Boost标准库--Boost.StringAlgorithms库
概述
在未使用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;
注: 该库遵循标准库的命名规范,使用小写形式,同时通过不同前后缀来区分不同版本,具体规则如下
- 前缀i:忽略大小写
- 后缀_copy: 不改变当前字符串,返回处理后的拷贝结果,否则就是在原字符串上进行调整操作
- 后缀_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库的更多相关文章
- 一起学习Boost标准库--Boost.texical_cast&format库
今天接续介绍有关字符串表示相关的两个boost库: lexical_cast 将数值转换成字符串 format 字符串输出格式化 首先,介绍下lexical_cast ,闻其名,知其意.类似C中的at ...
- c++学习书籍推荐《超越C++标准库:Boost库导论》下载
<超越C++标准库Boost库导论>不仅介绍了Boost库的功能.使用方法及注意事项,而且还深入讨论了Boost库的设计理念.解决问题的思想和技巧以及待处理的问题.因此,本书是一本了解Bo ...
- boost实用工具:assign库了解学习
许多时候,我们需要为容器初始化或者赋值,填入大量的数据; STL容器仅提供了容纳这些数据的方法,但是填充的步骤是相当地麻烦(insert.push_back); 于是,boost::assign出现了 ...
- C++三大库boost、loki、stlport
转: STL是一个标准,各商家根据这个标准开发了各自的STL版本.而在这形形色色的STL版本中,SGI STL无疑是最引人瞩目的一个.这当然是因为这个STL产品系出名门,其设计和编写者名单中,Alex ...
- [Boost]图形处理库Boost::Polygon
Background 工作中经师傅指导学习应用到了Boost::Polygon这个库,相对于Boost::Geometry,Polygon出自Intel.抽象于芯片流程,于是更贴近于芯片设计流程应用. ...
- [C++Boost]程序参数项解析库Program_options使用指南
介绍 程序参数项(program options)是一系列name=value对,program_options 允许程序开发者获得通过命令行(command line)和配置文件(config fi ...
- VS2010编译Boost 1.57 静态链接库
http://www.cnblogs.com/cuish/p/4175491.html 0.前提 Boost库版本 1.57.0 下载地址 http://www.boost.org/users/his ...
- Dev-C++安装第三方库boost
Dev-C++安装第三方库boost 转 https://www.jianshu.com/p/111571e4d6f5?utm_source=oschina-app 之前鉴于codeblocks界面 ...
- 【C/C++学院】0904-boost智能指针/boost多线程锁定/哈希库/正則表達式
boost_array_bind_fun_ref Array.cpp #include<boost/array.hpp> #include <iostream> #includ ...
随机推荐
- 【详解】GrantedAuthority(已授予的权限)
前言 这篇是很久之前学习Spring Security整理的博客,发现浏览量都1000多了,一个赞都没有,那说明写得确实不怎么样,哈哈.应该很多初学者对这个接口存在疑问,特别是如果学习这个框架之前还了 ...
- redis学习(七)redis主从复制
redis主从复制 1.redis主从复制的作用 redis的定位是一个高可用的数据服务器,可是在实际生产环境下,单机的redis服务器是无法满足真正意义上的高可用性的. 第一,单机的redis服务器 ...
- 使用whiptail开发linux环境交互式对话框
#!/bin/bash oem=$(/bin/cat /opt/jdwa/etc/oem) systype=$(/bin/cat /opt/jdwa/etc/systype) export selec ...
- RocketMQ专题2:三种常用生产消费方式(顺序、广播、定时)以及顺序消费源码探究
顺序.广播.定时任务 前插 在进行常用的三种消息类型例子展示的时候,我们先来说一说RocketMQ的几个重要概念: PullConsumer与PushConsumer:主要区别在于Pull与Pus ...
- (原)SQL Server 代理作业执行持续时间简述
本文目录列表: 1.SQL Server 代理作业概述2.获取代理作业执行时间方法一 3.获取代理作业执行时间方法二4.总结语 5.参考目录清单列表 正文: 1.SQL Server 代理作业概述 ...
- ASP.NET 之 EntityFramework实体框架搭建
前段时间接触了EntityFramework,对ORM框架也是有了初步的认识,现在对其进行一点小总结. 一.ORM简介 对象关系映射(Object Relational Mapping,简称ORM)模 ...
- ionic 混合应用开发
windows下安装配置 npm install -g ionic npm install -g cordova ionic start myproject cd myproject ionic pl ...
- Java基础部分回顾(为自己)
最近,学到集合框架.感觉有些蒙圈儿.知道这一块很重要很重要,不敢疏忽.自学遇到的拦路虎,想着是不是前面的基础知道还没有夯实,对一些概念没有真正的理解到位呢?!所以,停下来.开始找一些视频,做一下回顾. ...
- 并发修改异常(ConcurrentModificationException)
并发修改异常(ConcurrentModificationException) 这个异常,使用集合的时候应该很常见,这个异常产生的原因是因为java中不允许直接修改集合的结构. 先贴上个有趣的例子,给 ...
- RocketMQ 概述
Rocket 火箭 MQ的作用:同步转异步(异步解耦). 难点:如何确保消息一定被消费,而且仅消费一次. 1.消息架构:生产者.服务器.消费者.路由发现. 2.消息顺序:严格按照消息到达服务器的顺序进 ...