目录

一、lexical_cast

与C语言、C++的对比

二、format

1.format类

2.格式化语法

三、string_ref

1.背景

2.boost::string_ref

3.remove_prefix( )和remove_suffix( )

四、string_algo

1.大小写转换

2.字符串判断

a.函数

b.函数对象

3.分类函数

4.修剪

5.查找

6.替换与删除

7.分割

8.合并

9.查找分割迭代器

五、xpressive


一、lexical_cast

lexical_cast库可以进行字符串与整数\浮点数之间的互相转换。

lexical_cast的标准形式有两个模板参数 template <typename Target, typename Source>,Target需要我们手动指定,是转换后的目标类型,通常是数字类型或 std:: string;而第二个参数Source则不必写出,因为它可以由函数参数推导出来。

字符串转数字时,字符串中只能有数字和小数点,不能出现字母或其他非数字字符 (表示指数的e\E 除外) 。

lexical_cast可以将整型或字符串的0、1转换为bool类型,注意不能使用true\false字面值。

当lexical_cast无法执行转换操作时会抛出异常 bad_lexical_cast,它是std::bad_cast的派生类。我们可以使用try/catch块来保护代码。当然,我们可以使用try_lexical_convert( )安全的转换字面值,避免抛出异常,它以bool返回值来表示是否转换成功。

lexical_cast内部使用了标准库的流操作,因此,对于它的转换对象有以下要求,标准容器和其他自定义类型需满足这些条件,否则不能使用 lexical_cast 。

  • 转换起点对象是可流输出的,即定义了 opreator< < 。
  • 转换终点对象是可流输入的,即定义了 opreator> >。
  • 转换终点对象必须是可默认构造、可拷贝构造的。
#include <boost/lexical_cast.hpp>
void TestLexical_Cast()
{std::string str = boost::lexical_cast<std::string>(0x96);std::cout << str << std::endl;                  //150std::string str1 = boost::lexical_cast<std::string>(30);std::cout << str1 << std::endl;                 //30float pi = boost::lexical_cast<float>("3.141592653");std::cout << pi << std::endl;                   //3.14159//只支持整型、字符串的0、1转boolbool bo = boost::lexical_cast<bool>("0");std::cout << bo << std::endl;try {//错误,待转换的字符串中只能有数字和小数点及指数的e/E,不能有其他的字符int num = boost::lexical_cast<int>("0x96");std::cout << num << std::endl;}catch (boost::bad_lexical_cast e){std::cout << e.what() << std::endl;         //bad lexical cast: source type value could not be interpreted as target}//使用try_lexical_convert安全的转换字面值,避免抛出异常int num;bool is_success = boost::conversion::try_lexical_convert("0x96", num);std::cout << "is_success:" << is_success << ",num:" << num << std::endl;//0,96
}

与C语言、C++的对比

C 语言中的 atoi ( )和 atof( )系列的函数是不对称的,仅可以把字符串转换成数值,不存在把数值转换为字符串的转换。

c++11 增强了字符串与数字的互操作性,提供stoX ( ) 和 to_string ( ) 函数实现了字符串与数字之间的转换。它无需写模板参数,而且允许字符串里出现非数字字符——它们会忽略起始的空格,直到遇到无法转换的字符为止。但如果字符串不是以空格、数字开头,或者超出了数字类型的范围,那么这些函数会抛出 std::invalid_argument 或 std::out_of_range 异常。

    int a = 10;std::string a_str = std::to_string(a);std::cout << a_str << std::endl;                //10int b = std::stoi("12ss");std::cout << b << std::endl;                    //12

二、format

C 语言中经典的 printf ( )使用了 C 语言里的可变参数,缺乏类型安全检查(速度快),但它的语法简单高效,并且被广泛地接受和使用,影响深远。

boost.format 库 " 扬弃 " 了 printf ( ),实现了类似的格式化对象,可以把参数格式化到一个字符串,而且此操作是完全类型安全的(速度慢)。format 模仿了流操作符 "<<"  ,重载了二元操作符operator%作为参数输入符,它同样可以串联任意数量的参数。它已经被收入C ++20 标准。

1.format类

format并不是一个真正的类,而是一个 typedef ,其真正的实现是 basic_format 。

成员函数 str( ) 返回 format 对象内部已经格式化好的字符串(不清空),如果没有得到所有格式化字符串要求的参数则会抛出异常。 format 库还提供一个同名的自由函数 str( ),它位于 boost 名字空间,返回 format 对象内部已格式化好的字符串。

成员函数 size( ) 可以获得已格式化好的字符串的长度,如果没有得到所有格式化字符串要求的参数则会抛出异常。

成员函数 parse ( ) 清空 format 对象的内部缓存,并改用一个新的格式化字符串。如果仅仅想清空缓存,则可以使用 clear ( ),它把 format 对象恢复到初始化状态。这两个函数执行后再调用 str ( )或size( )则会抛出异常,因为此时没有输入格式化参数。

2.格式化语法

format基本继承了 printf 的格式化语法,如%05d、%-8.3f等。除经典的 printf 格式化外,format 还增加了新的格式:

  • %|spec| 增加竖线分割,更好地区分格式化选项与普通字符
  • %N% 标记第N个参数,相当于占位符,不带任何其他的格式化选项
#include <boost/format.hpp>
void TestFormat()
{std::cout << boost::format("%s:%d+%d=%d\n") % "sum" % 1 % 2 % (1 + 2); //sum:1+2=3//对比printfprintf("%s:%d+%d=%d\n", "sum", 1, 2, 1 + 2);                           //sum:1+2=3//%N% 标记第N个参数,相当于占位符,不带任何其他的格式化选项boost::format fmt("(%1%+%2%)*%3%=%4%");                                //预先创建一个format格式化对象fmt % 4 % 6 % 2;                                                       //分多次输入被格式化的参数fmt % ((4 + 6) * 2);std::cout << "格式化字符串:" << fmt.str() << ",字符串长度:" << fmt.size();//格式化字符串:(4+6)*2=20,字符串长度:10                                               //(4+6)*2=20fmt.clear();fmt % 3 % 6 % 4 % ((3 + 6) * 4);std::cout << "格式化字符串:" << fmt.str() << ",字符串长度:" << fmt.size();//格式化字符串:(3+6)*4=36,字符串长度:10//对比printfprintf("(%d+%d)*%d=%d", 4, 6, 2, (4 + 6) * 2);                         //(4+6)*2=20//%|spec| 增加竖线分割,更好地区分格式化选项与普通字符boost::format fmt1("%|05d|-%|-8.3f|-%|10s|-%|05X|");fmt1 % 10 % 3.14%"hello" % 150;std::cout << fmt1.str() << std::endl;//00010-3.140   -     hello-00096
}

三、string_ref

1.背景

在C ++中处理字符串的基本工具是标准字符串std::string,但构造一个 std::string 成本较高, 因为它必须完全持有字符串的内容,极端的时候会有很高的内存拷贝代价,影响程序效率。使用const std::string& 可以避免一些问题,但它在处理 C 字符串、提取子串时却无能为力。总而言之, std::string 显得有些 " 重 ",我们需要一种更 " 轻 " 的字符串工具——boost::string_ref。

2.boost::string_ref

boost::string_ref它只持有字符串的引用,没有内存拷贝代价,所以运行效率很高,是更好的 const std::string &。 它已经被收入 C ++17 标准 ( 但更名为string_view)。

string_ref库定义了 basic_string_ref,它不拷贝字符串,所以也不分配内存,只用两个成员变量 ptr_ 和len_ 标记字符串的起始位置和长度,这样就实现了对字符串的表示。basic_string_ref是一个字符串的“常量视图”,大部分成员函数都是由 const 修饰的,我们只能像const std::string & 那样去观察字符串而无法修改字符串。

由于 string_ref 的接口与 string 完全相同,所以它的一个重要用途是代替 const std::string & 类型作为函数参数或返回值(必须保证被引用的字符串对象可用,尽量避免长期持有或延后使用。在确实需要持有或修改字符串的时候,可以调用成员函数 to_string ( )获得一个拷贝副本来保证安全。),可以完全避免字符串拷贝代价,提高字符串的处理效率。

3.remove_prefix( )和remove_suffix( )

虽然 string_ref 不能直接改变原字符串,但它可以使用remove_prefix( )和remove_suffix( ) 这两个函数调整 string _ ref 内部的字符串指针和长度,达到变动字符串引用的目的——但原始字符串仍然没有被修改。

#include <boost/utility/string_ref.hpp>
void TestStringRef()
{const char* ch = "Study C++ in library";std::string str(ch);                            //标准字符串,有拷贝成本boost::string_ref str_ref(ch);                  //零拷贝if (str_ref == str){std::cout << "两个字符串相等" << std::endl;   //两个字符串相等}std::cout << "第一个字符:" << str_ref.front() << std::endl;              //第一个字符:Sstd::cout << "最后一个字符:" << str_ref[str_ref.length()-1] << std::endl;//最后一个字符:yint index = str_ref.find('+');std::cout << "+索引" << index << std::endl;     //+索引7boost::string_ref substr = str_ref.substr(6, 3);std::cout << substr << std::endl;              //C++std::string str2 = str_ref.to_string();if (str2 == str&& str_ref==str2){std::cout << "三个字符串相等" << std::endl;  //三个字符串相等}str_ref.remove_prefix(6);std::cout <<"移除前6个字符:"<< str_ref << std::endl;  //移除前6个字符:C++ in librarystr_ref.remove_suffix(8);std::cout << "移除后8个字符:" << str_ref << std::endl;//移除后8个字符:C++ in
}

四、string_algo

string_algo 库的出现改变了这个局面。它是一个非常全面的字符串算法库,提供了大量的字符串操作函数,如大小写转换、字符串判断、去空格、查找替换、分割与合并等, string_algo 库可以在不使用正则表达式的情况下处理大多数字符串的相关问题。

string_algo 库中的算法命名遵循了标准库的惯例,算法名均为小写形式,并使用不同的词缀来区分不同的版本,命名规则如下。

  • 前缀 i :大小写不敏感(忽略大小写);否则是大小写敏感的。
  • 后缀 _copy :不变动输入,返回处理结果的拷贝;否则原地处理,输入即输出。
  • 后缀 _if :需要一个作为判断式的谓词函数对象;否则使用默认的判断准则。

1.大小写转换

  • to_upper() 、to_upper_copy()
  • to_lower()、to_lower_copy()
#include <boost/algorithm/string.hpp>std::string str("c://test/readme.json");
//大小写转换
std::cout << boost::to_upper_copy(str) << std::endl; //结果 C://TEST/README.JSON

2.字符串判断

a.函数

  • lexicographical_compare、ilexicographical_compare :根据字典顺序检测一个字符串是否小于另一个字符串。
  • starts_with、istarts_with:检测字符串是否以另一个字符串为前缀。
  • ends_with、iends_with:检测字符串是否以另一个字符串为后缀。
  • contains、icontains:检测字符串是否包含另一个字符串。
  • equals、iequals :检测两个字符串是否相等。
  • all :检测字符串是否满足指定的判断式。
    std::string str("c://test/readme.json");if (boost::ends_with(str, "json")){std::cout << "是个json文件" << std::endl;         //是个json文件}if (boost::icontains(str, "C://"))//忽略大小写{std::cout << "文件在C盘中" << std::endl;          //文件在C盘中}if (boost::all(str.substr(9, 6), boost::is_lower())){std::cout << "文件名是小写" << std::endl;         //文件名是小写}

b.函数对象

  • is_equal :与 equals 算法类似,比较两个对象是否相等。
  • is_less :比较两个对象是否具有小于关系。
  • is_not_greater :比较两个对象是否具有不大于关系。
    if (boost::is_equal()("hello", "hello")){std::cout << "两个字符串相同" << std::endl;       ///两个字符串相同}if (boost::is_less()("hello", "world")){std::cout << "hello小于world" << std::endl;     ///hello小于world}if (boost::is_not_greater()("hello", "Hello")){std::cout << "两个字符串具有不大于关系" << std::endl;///两个字符串具有不大于关系}

注意函数对象名称后的两个括号,第一个括号调用了函数对象的构造函数,产生了一个临时对象,第二个括号才是真正的函数调用操作符operator ( ) 。

3.分类函数

string_algo 提供一组分类函数,可以用于检测一个字符是否符合某种特性,主要用于搭配其它算法 ,如字符串判断中的 all 算法。string_algo 库的分类函数有下列数种。

需要注意的是这些函数并不真正地检测字符,而是返回一个类型为 detail::is_classifiedF 的函数对象,这个函数对象的 operator ( )才是真正的分类函数(因此,这些函数都属于工厂函数)。函数对象 is_classifiedF 重载了逻辑运算符||、&&和!,可以使用逻辑运算符把它们组合成逻辑表达式,以实现更复杂的条件判断。

  • is_space : 字符是否为空格或制表符 ( tab )。
  • 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 :字符是否位于指定区间内,即from < = ch < = to 。

4.修剪

修剪算法可以删除字符串开头或结尾部分的空格:

  • trim()、trim_if()、trim_copy()、trim_copy_if()
  • trim_left()、trim_left_if()、trim_left_copy()、trim_left_copy_if()
  • trim_right()、trim_right_if()、trim_right_copy()、trim_right_copy_if()
std::string str2("  hello world | ");
boost::trim_if(str2, boost::is_space() || boost::is_punct());//修建开头、结尾部分的空格、标点符号
std::cout << str2 << std::endl;                    ///hello worldstd::string str3("  hello world | ");
boost::trim(str3);//修建开头、结尾部分的空格
std::cout << str3 << std::endl;                   ///hello world |

5.查找

string_algo 提供的查找算法包括下列几种:

  • find_first、ifind_first:查找字符串在输入中第一次出现的位置。
  • find_last、ifind_last:查找字符串在输入中最后一次出现的位置。
  • find_nth、ifind_nth:查找字符串在输入中的第 N 次 ( 从 0 开始计数 ) 出现的位置。
  • find_head:取一个字符串开头 N 个字符的子串,相当于 substr (0,n)。
  • find_tail:取一个字符串末尾 N 个字符的子串。
    std::string str4("D://tal/ABC.txt");    boost::iterator_range<std::string::iterator> range = boost::find_first(str4, "tal");    boost::format fmt("%1%.pos=%2%");fmt %range % (range.begin() - str4.begin());std::cout << fmt.str() << std::endl;//tal.pos=4std::cout << str4.substr(str4.find_last_of('/') + 1, str4.find_last_of('.') - str4.find_last_of('/') - 1) << std::endl;///ABC 

6.替换与删除

替换、删除操作与查找算法非常接近,是在查找到结果后再对字符串进行处理,所以它们的算法名称很相似,具体如下。

  • replace/erase_first :替换 / 删除字符串在输入中的第一次出现。(支持i_、 _copy)
  • replace/erase_last :替换 / 删除字符串在输入中的最后一次出现。(支持i_、 _copy)
  • replace/erase_nth :替换 / 删除字符串在输入中的第 n 次出现。(支持i_、 _copy)
  • replace/erase_all :替换 / 删除字符串在输入中的所有出现。(支持i_、 _copy)
  • replace/erase_head :替换 / 删除输入的开头。(支持 _copy)
  • replace/erase_tail :替换 / 删除输入的末尾。(支持 _copy)
    std::string str("c://test/readme.json");boost::replace_first(str, "readme", "test");std::cout << str << std::endl;                       ///C://Test/test.jsonboost::ierase_first(str, "test");std::cout << str << std::endl;                       ///c:///test.jsonstd::cout << boost::erase_first_copy(str, ".json") << std::endl;///c:///test

7.分割

  • find_all()、ifind_all()
  • split() :只支持以字符分割,不支持以字符串进行分割

boost中find_all因为其功能而被归类为分割算法,但经过我测试,它并不能分割,而是查找所有匹配的字符串并将其加入容器。

split()支持四个参数,最后一个参数token_compress_mode_type eCompress 是个枚举对象,可以取值为token_compress_on(常用,当两个分隔符连续出现时,她们将被视为一个分隔符)、token_compress_off(默认,两个连续的分隔符标记了一个空字符串)

    std::string split_str("textLily,Mary,Sarisy,text chinese food");std::vector<std::string> name_vector;boost::find_all(name_vector, split_str, "text");for (auto a : name_vector){std::cout << a << std::endl;//name_vector:两个text}name_vector.clear();boost::split(name_vector, split_str, boost::is_any_of(","));for (auto a : name_vector){std::cout << a << std::endl;//name_vector:四个元素:textLily、Mary、Sarisy、text chinese food}

8.合并

合并算法 join 是分割算法的逆运算,它把存储在容器中的字符串连接成一个新的字符串,并且可以指定连接的分隔符。join()、join_if()

    std::vector<std::string> join_str{ "I", "am","a","chinese" };std::string joinStr = boost::join(join_str, " ");std::cout << joinStr << std::endl;//I am a chinese

9.查找分割迭代器

除通用的 find_all 或 split 之外, string_algo 库还提供了两个查找迭代器 find_iterator 和
split_iterator ,它们可以在字符串中像迭代器那样遍历匹配,执行查找或分割,无须使用容器来容
纳。这里要特别注意分割迭代器的运用,它可以以任意长度的字符串作为分隔符进行分割,而普通的 split算法则只能以字符作为分隔符。

使用查找迭代器首先要声明迭代器对象find_iterator 或 split_iterator ,它们的模板类型参数是一个迭代器类型,如 string::iterator 或char * 。

为了获得迭代器的起始位置,我们需要先调用first_finder函数,它用于判断匹配的对象,再用 make_find_iterator 或 make_split_iterator 来真正地创建迭代器。同族的查找函数还有last_finder 、 nth_finder 、 token_finder 等,它们的含义与查找算法类似,从不同的位置开始查找返回迭代器。

初始化工作完成后,我们就可以像使用标准迭代器或指针那样,不断地遍历迭代器对象,使用解引用操作符获取查找的内容,直到找不到匹配的对象。

    std::string sss = "I||am||a||chinese,I||love||China";boost::find_iterator<std::string::iterator> pos = boost::make_find_iterator(sss, boost::first_finder("||"));for (pos; !pos.eof(); ++pos){std::cout << *pos << std::endl;}boost::split_iterator<std::string::iterator> pos1, end1;for (pos1 = boost::make_split_iterator(sss, boost::first_finder("||", boost::is_iequal())); pos1 != end1; ++pos1){std::cout << *pos1 << std::endl;}
//结果
||
||
||
||
||
I
am
a
chinese,I
love
China

五、xpressive

xpressive是一个灵活且功能强大的正则表达式解析库,它可以构建小型语法,同时提供动态方式与静态方式两种用法。借助正则表达式的强大能力,xpressive能够轻松解决文本处理领域绝大多数的问题,它基本可以替代 string_algo 库。

但正则表达式本身是一门复杂的技术,要考虑它的调试和维护成本。解决同样的问题, string_algo 可能速度更快,编写的代码也易于理解,所以只有当它们确实无法解决问题时才应该使用正则表达式。

boost I 字符串与文本处理相关推荐

  1. Boost:字符串转换实例

    Boost:字符串转换实例 实现功能 C++实现代码 实现功能 字符串 统一转为大写,统一转为小写 C++实现代码 #include <string> #include <vecto ...

  2. Boost:字符串查找子串测试实例

    Boost:字符串查找子串测试实例 实现功能 C++实现代码 实现功能 字符串查找子串测试实例 C++实现代码 #include <string> #include <iostrea ...

  3. Boost:字符串Predicate的测试实例

    Boost:字符串Predicate的测试实例 实现功能 C++实现代码 实现功能 字符串Predicate的测试实例 C++实现代码 #include <string> #include ...

  4. Boost:字符串分割Split的测试程序

    Boost:字符串分割Split的测试程序 实现功能 C++实现代码 实现功能 字符串分割Split的测试程序 C++实现代码 #include <string> #include < ...

  5. Boost:字符串正则表达式的测试程序

    Boost:字符串正则表达式的测试程序 实现功能 C++实现代码 实现功能 字符串正则表达式的测试程序 C++实现代码 #include <string> #include <ios ...

  6. Boost:字符串替换的测试程序

    Boost:字符串替换的测试程序 实现功能 C++实现代码 实现功能 字符串替换的测试程序 C++实现代码 #include <string> #include <iostream& ...

  7. Boost:字符串的RLE压缩的测试程序

    Boost:字符串的RLE压缩的测试程序 实现功能 C++实现代码 实现功能 字符串的RLE压缩的测试程序 C++实现代码 #include <string> #include <i ...

  8. Boost:字符串裁剪Trim的测试程序

    Boost:字符串裁剪Trim的测试程序 实现功能 C++实现代码 实现功能 字符串裁剪Trim的测试程序 C++实现代码 #include <string> #include <i ...

  9. c++ string分割字符串split_python 字符串和文本处理

    字符串和文本处理 字符串是一种重要的数据形式,有价值的程序都会涉及到对于字符串的处理.幸运的是,强大的python内置了很多函数,来帮助我们解析和处理字符串.本文会涉及到字符串编码,简单的字符串处理函 ...

最新文章

  1. Java解码网站post字符串(swich case用法和乱码判断)
  2. Silverlight, B/S or C/S?
  3. 讲师征集| .NET Conf China 2021正式启动!
  4. linux查看内核分区,如何根据bootloader中MTD分区信息修改linux内核中的MTD分区
  5. cml sml区别_如何简单清晰地描述 CAPM 在投资学中的运用,以及 CAL、CML 和 SML 的关系和区别?...
  6. linux上python升级_Linux下安装升级python
  7. 高精度三维扫描仪用于运动鞋逆向建模
  8. 数学建模--偏最小二乘法
  9. javaBean本质
  10. A N S I五个预定义的宏名
  11. 公司天天开会,是不是浪费生命呢?
  12. elasticsearch collapse
  13. xp如何在电脑上设置无线网络连接服务器,xp电脑怎么设置wifi
  14. STM32CubeIDE+FREERTOS踩坑记录
  15. GoJS去除水印方法
  16. 中国传媒大学计算机课程表,中国传媒大学播本课表.pdf
  17. 从Flink SQL doesn't support consuming update and delete changes 错误谈起
  18. CheckBoxList复选框例子
  19. AD快捷键、常见问题汇总
  20. 双开应用和主分身空间

热门文章

  1. 多线程与自动任务的一场悲剧的风花雪月
  2. ai怎么做波普风圆点_Illustrator绘制波普艺术风格人像教程分享
  3. 鲜血中竟然可以看到无数米粒大小的冰块
  4. windows键失灵,偶尔重启也没用的解决办法(机械键盘),从FN+F1到FN+F12都按了一遍还是没反应   FN+鼠标左右键都一样
  5. mysql取出的emoji表情是乱码_解决MySQL emoji表情乱码问题
  6. 几种流行编程语言概述
  7. 沪指突破5000点创七年新高 建筑有色板块领涨
  8. iOS中使用第三方字体
  9. LFU缓存--基于哈希和双链表的实现
  10. 273、隐藏个人信息