博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
boost的字符串处理函数——string algorithm
阅读量:5258 次
发布时间:2019-06-14

本文共 3042 字,大约阅读时间需要 10 分钟。

c++在stl库中提供了一个string类用以代替c语言的char*来实现字符串功能,不过stl的string只提供了一个连接字符串和查找的功能,其它的常用函数几乎一律没有,就连字符串替换都得自己来实现,和c#的字符串函数比起来简直弱爆了。

boost库在头文件<boost/algorithm/string.hpp>中提供了不少字符串处理函数,用以帮助我们实现基本的字符串处理功能,极大程度上缓解了字符串函数不够用的问题。

    string str1("hello abc-*-ABC-*-aBc goodbye");

    vector<string> SplitVec; // #2: Search for tokens
    split(SplitVec, str1, is_any_of("-*"), token_compress_on); // SplitVec == { "hello abc","ABC","aBc goodbye" }

上述代码就提供了一个split的功能,不过和c#的版本相比,还是不够简洁,如果设计成这样就更加好用了:

    auto SplitVec = split(str1, is_any_of("-*"), token_compress_on);

之所以不以这种形式设计,貌似是因为如果在split函数里构造返回值的话,会有一次数据拷贝的开销。从中也可以看出,boost的设计还是以性能为主的。而.net程序天然没有返回值拷贝带来的开销,可以采取那种更简洁的接口形式。

PS:我觉得可以像.net那样,在堆变量中保存结果,然后通过auto_ptr封装后作作为返回值。即有简洁的接口形式,又没有数据拷贝的开销,堆变量也能通过auto_ptr自动释放。

同样,也是出于性能方向的考虑,对于会产生新字符串的函数,往往会有一个xxx和xxx_copy两个版本,例如tolower就有to_lower和to_lower_copy两个版本:一个是直接变更本身的值,一个是构造新字符串,具体选取那个根据实际场景来考虑。

另外,字符串比较函数中,往往有区分大小写和不区分大小写的算法。在boost中并不是通过参数来控制,而是直接提供xxx和ixxx两个版本,其中i就表示ignor case。如equals和iequals。还有的需要和条件函数一并使用的,这时就会提供一个xxx_if的版本。

由于提供的字符串函数比较多,这里我只按每类列举几个常用的函数和示例,如果同一个算法有xxx_copy的版本或ixxx版本,也只列举基本的形式。其它的情参看。

Case Conversion

大小写转换涉及到四个函数:、以及xxx_copy的版本。基本用法如下:

    cout << to_upper_copy(string("hello world")) << endl;

Trimming

Trimming函数主要有、、和他们的xxx_copy和xxx_if版本。用于去除字符串首位的空白字符:

    cout << trim_copy(std::string(" hello world")) << endl;

当然,也不限于只去掉空白字符:

    cout << trim_copy_if(std::string(",,,hello world"), is_any_of(" ,.:")) << endl;

Predicates

Predicates函数主要有: 、 、 、 、 、以及他们的ixxx版本。基本上从名字里就可以看出怎么用了:

    cout << (ends_with("hello world", "world") ? "true" : "false") << endl;

Find algorithms

查找算法有好几种:、、 、、、、。常见的用法如下:

    auto result = find_first("hello world", "world");

    if(result.empty())
        cout << "can't find result" << endl;
    else
        cout << result << endl;

其中result是一个boost::iterator_range类型的对象,可以用它来构造子串。

    string s("hello world");

    cout << s.substr(find_first(s, "wo").begin() - s.begin()) <<endl;

或者来个更复杂点的:

    string str1("abc-*-ABC-*-aBc");

    for(auto it = make_find_iterator(str1, first_finder("abc", is_iequal())); !it.eof(); ++it)
    {
        cout << copy_range<std::string>(*it) << endl;
    }

Erase/Replace

boost把erase和replace函数分开来列了,这样的好处是命名比较清晰,但不好的地方时函数变得非常多,不如重载的形式那么好记。

replace的函数有 、、  以及它们的变体,加上erase,共有20多种,这里就不一一列举了。

    cout << replace_all_copy(string("hello world"), "l", "-") << endl;

Split

split函数的用法前面以及介绍过:

    string str1("hello abc-*-ABC-*-aBc goodbye");

    vector<string> SplitVec;
    split(SplitVec, str1, is_any_of("-*"),
token_compress_on);

需要注意的是这里的token_compress_on参数,它可以吧连续多个分隔符当一个,默认没有打开,当用的时候一般是要打开的。

另外,boost把find_all函数也分到split一类里面去了,它们的用法到也确实类似。

    string str1("hello abc-*-ABC-*-aBc goodbye");

    typedef vector<iterator_range<string::iterator>> find_vector_type;
    find_vector_type FindVec;
    ifind_all( FindVec, str1, "abc" );

Join

Join函数则是和split相反,用于把多个字符串拼接起来。

    std::array<string, 3> k = {

"hello", "world", "123"};
    cout << join(k, "-");        //
输出结果为: hello-world-123

它要求先把参数放到容器里,不像.net的那样可以直接传入动态参数那样好用,如果能写成这样的重载形式会更好点(当然,自己封一个也不难):

    join("-", "hello", "world", "123", …)

其它

其它还有一些条件函数,主要配合算法使用。如前面已经见过的、常用的还有、、、等,这里就不多介绍了。

转载于:https://www.cnblogs.com/TianFang/archive/2013/02/04/2891538.html

你可能感兴趣的文章
多线程《三》进程与线程的区别
查看>>
linux sed命令
查看>>
html标签的嵌套规则
查看>>
[Source] Machine Learning Gathering/Surveys
查看>>
HTML <select> 标签
查看>>
类加载机制
查看>>
tju 1782. The jackpot
查看>>
湖南多校对抗赛(2015.03.28) H SG Value
查看>>
hdu1255扫描线计算覆盖两次面积
查看>>
hdu1565 用搜索代替枚举找可能状态或者轮廓线解(较优),参考poj2411
查看>>
bzoj3224 splay板子
查看>>
程序存储问题
查看>>
Mac版OBS设置详解
查看>>
优雅地书写回调——Promise
查看>>
android主流开源库
查看>>
AX 2009 Grid控件下多选行
查看>>
PHP的配置
查看>>
Struts框架----进度1
查看>>
Round B APAC Test 2017
查看>>
MySQL 字符编码问题详细解释
查看>>