一起学习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;

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

  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

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
}

原文地址:https://www.cnblogs.com/wqliceman/p/8799324.html

时间: 2024-10-08 07:03:33

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

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

今天接续介绍有关字符串表示相关的两个boost库: lexical_cast 将数值转换成字符串 format 字符串输出格式化 首先,介绍下lexical_cast ,闻其名,知其意.类似C中的atoi 函数,可以进行字符串与整数/浮点数之间的字面转换 Boost::lexical_cast库 前期准备 lexical_cast库位于boost命名空间下,使用需要引入头文件 #include <boost/lexical_cast.hpp> using namespace boost; 函数

boost标准库开发环境搭建

1.下载boost相关的库的安装包 网址:http://www.boost.org/ 其中1.55.0版本的下载地址是:http://sourceforge.net/projects/boost/files/boost/1.55.0/ 截图: 2.boost开发相关的软件: boost_1_55_0.tar.gz  Linux平台下面的boost源码包 boost_1_55_0.zip    Windows平台下面的boost源码包 boost_1_55_0-bin-msvc-all-32-64

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

许多时候,我们需要为容器初始化或者赋值,填入大量的数据; STL容器仅提供了容纳这些数据的方法,但是填充的步骤是相当地麻烦(insert.push_back); 于是,boost::assign出现了,其重载了+= ,()等运算符,用难以想象的简洁对STL容器初始化或赋值. +=很好用,但是仅适用于STL的标准容器,对于boost新容器却无能为力; ()可以更灵活实现对容器的初始化; 容器构造的时候就对数据进行填充list_of等. C++ Code 1234567891011121314151

C++ 三大库boost、loki、stlport

C++ 三大库boost.loki.stlport 在C++中,库的地位是非常高的.C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论.现实中,C++的库门类繁多,解决的问题也是极其广泛,库从轻量级到重 量级的都有.不少都是让人眼界大开,亦或是望而生叹的思维杰作.由于库的数量非常庞大,而且限于笔者水平,其中很多并不了解.所以文中所提的一些库都是比较著名的大型库. 标准库 标准库中提供了C++程序的基本设施.虽然C++标准库随着C++标准折腾了许

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

介绍 程序参数项(program options)是一系列name=value对,program_options 允许程序开发者获得通过命令行(command line)和配置文件(config file)获取这些参数项. 为什么需要这样一个库?为什么比你手工写代码分解命令行参数要好? 使用更容易.定义参数处理的语法简单,库自身很小.像转换参数值到指定的类型和保存参数值到变量的事情都是自动处理. 错误报告更友好.可报告错误的命令行参数.另外这个库能自动生成使用帮助,避免手工更新使用帮助导致的不一

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

boost_array_bind_fun_ref Array.cpp #include<boost/array.hpp> #include <iostream> #include <string> using namespace std; using namespace boost; void mainA () { array <int, 5> barray = { 1, 2, 3, 4, 5 }; barray[0] = 10; barray.at(4)

VS2008下编译BOOST 1.39的ASIO库

由于全部编译BOOST库需要的时间太长,而且耗费空间,况且我只需要用ASIO库,所以就没有必要全部编译了. boost库到www.boost.org上下载. 编译很简单,假设你的boost存放的目录是D:/BOOST_139. 1.运行VS2008的命令提示行,进入D:/BOOST_139/tools/jam;执行build_dist.bat,这样就产生了bjam.exe,该文件位于/tools/jam/stage/bin.ntx86 2.为了方便,将bjam.exe拷贝到D:/BOOST_13

VS2010编译Boost 1.57 静态链接库

0.前提 Boost库版本 1.57.0 下载地址 http://www.boost.org/users/history/version_1_57_0.html,选择windows版 编译器:VS2010 编译目标:静态链接库 C/C++运行库链接方式: /MT  /MTd   /MD   /MDd 官网给出的windows平台编译器测试包括 Windows: GCC, mingw: 4.4.0, 4.4.7. 4.5.4, 4.6.3, 4.7.2, 4.7.3, 4.8.0, 4.8.2,

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

boost_array_bind_fun_ref Array.cpp #include<boost/array.hpp> #include <iostream> #include <string> using namespace std; using namespace boost; void mainA () { array <int, 5> barray = { 1, 2, 3, 4, 5 }; barray[0] = 10; barray.at(4)