Boost string_algo

Boost提供了字符串处理算法,如大小写无关比较,修剪,特定模式的子串查找等。而且它处理的对象不一定是string,可以是符合boost.range要求的容器。string_algo 还有一些命名规则:

  1. 前缀 i: 表明大小写不敏感
  2. 后缀_copy : 算法不变动输入,返回处理结果的复制,否则算法原地处理,输入即输出
  3. 后缀_if : 需要一个作为判断式的谓词函数对象,否则使用默认判断准则

大小写转换

string_algo可以高效的大小写转换,包括两组算法:

  1. template void to_upper(T & Input);
  2. template void to_lower(T & Input);

判断式(算法)

判断式算法检测两个字符串之间的关系是根据字典序比较大小。

  1. start_with:检测一个字符串是否以另一个为前缀
  2. end_with : 检测检测一个字符串是否以另一个为后缀
  3. contains: 检测字符串是否包含另一个
  4. equals: 检测两字符串是否相等
  5. all:检测一个字符串中的所有元素是否满足指定的判断式

判断式(函数对象)

string_algo允许不同的参数类型进行比较,并提供大小写无关的形式:

  1. is_equal: 比较两个对象是否相等
  2. is_less:比较两个对象是否具有小于关系
  3. is_not_greater: 不大于关系
int main()
{
    std::string Str1("Samus"), Str2("samus");
    assert(!is_equal()(Str1, Str2));
    assert(is_less()(Str1, Str2));
}

注意函数对象有两个括号,第一个括号调用了构造函数,第二个括号才是真正的函数调用操作符operator()。

分类

分类函数,提高一个字符是否符合某种特性,主要用于搭配其他算法

  1. is_space:字符是否为空格或制表符
  2. is_alnum:是否为字母和数字字符
  3. is_alpha:是否为字母
  4. is_any_of:字符是否为参数字符序列中的任意字符

如果想自定义专用的判断式,定义一个返回值的bool函数对象就可以。比如,判断字符是否为0或1:

struct is_zero_or_one
{
    bool operator()(char x)
    {
        return x=='0' || x=='1';
    }
};

修剪

修剪算法三个算法:trim_left,trim_right,trim,分别对应删除左端,右端和两段的空格。可以删除字符串开头或结尾部分的空格,有_if或_copy两种后缀。_if接受一个判断式IsSpace,将所有判断为空格的字符删除。

boost::format fmt("|%s| \n");
std::string Str = "2012 Happy new year!!!";
std::cout << fmt % boost::trim_left_copy_if(Str, boost::is_digit()); //删除左端数字
std::cout << fmt % boost::trim_right_copy_if(Str, boost::is_punct()); //删除右端标点
std::cout << fmt % boost::trim_copy_if(Str, boost::is_digit() || boost::is_punct() || boost::is_space());

查找

string_algo使用了boost.range库的iterator_range返回查找的整个区间,便于算法串联和其他处理(比如根据iterator_range的两个迭代器将原字符串拆分3份)

iterator_range在概念上类似std::pair

//***********************************************************
//FUNCTION:: string_algo find algorithm
void string_algo_find()
{
    boost::format fmt("|%s|. pos = %d \n");
    std::string Str = "Long long ago, there was a king.";
    //迭代器区间
    boost::iterator_range<std::string::iterator> Range = boost::find_first(Str, "long"); 
    std::cout << fmt % Range % (Range.begin() - Str.begin()) << std::endl;
}

替换和删除

  1. replace/erase_first:替换/删除一个字符串的第一次出现
  2. replace/erase_lase:替换/删除一个字符串的最后一次出现
  3. replace/erase_nth:替换/删除一个字符串的第N次出现
  4. replace/erase_all:替换/删除一个字符串的所有出现
  5. replace/erase_head:替换/删除输入的开头
  6. replace/erase_tail:替换/删除输入的结尾

分割

string_algo提供了两个字符串分割算法,find_all和spilt,可以使用某种策略把字符串分割成若干部分,并将分割后的字符串复制到指定的容器中。其要求是必须持有查找结果的的复制或引用,因此容器元素类型是string或者iterator_range,容器是vector,list,deque等标准容器。

//***********************************************************
//FUNCTION:: string_algo spilt algorithm
void string_algo_split()
{
    std::string StrSpilt = "SamusLink.Zelda::Mario-Luigi+zelda";
    std::deque<std::string> Deque;
    //搜索所有匹配字符串,加入到容器中,i忽略大小写
    boost::ifind_all(Deque, StrSpilt, "zELDA");
    for (auto e : Deque)
    {
        std::cout << "[" << e << "] ";
    }
    std::cout << std::endl;

    std::list<boost::iterator_range<std::string::iterator> > List;
    //spilt使用判断Pred确定分割依据,如果字符ch满足判断式,那么就是一个分隔符,将字符串从这里分开
    boost::split(List, StrSpilt, boost::is_any_of(",.:-+"));
    for (auto e : List)
    {
        std::cout << "[" << e << "] ";
    }
    std::cout << std::endl;

    List.clear();
    //token_compress_on表示如果两个分隔符连续出现,视为1个
    boost::split(List, StrSpilt, boost::is_any_of(",.:-+"), boost::token_compress_on);
    for (auto e : List)
    {
        std::cout << "[" << e << "] ";
    }
    std::cout << std::endl;
}

合并

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

//***********************************************************
//FUNCTION:: string_algo join
void string_algo_join()
{
    std::vector<std::string> Vec = boost::assign::list_of("Samus")("Link")("Zelda")("Mario");
    std::cout << boost::join(Vec, "+") << std::endl;

    struct is_contains_a 
    {
        bool operator()(const std::string& x)
        {
            return boost::contains(x , "a");
        }
    };

    //接受一个判断式,只有满足判断式的字符串才能参与合并
    std::cout << boost::join_if(Vec, "**", is_contains_a()) << std::endl;
}

查找(分割)迭代器

在通用的find_all或split之外,string_algo还提供两个查找迭代器find_iterator和split_iterator,可以像迭代器一样遍历匹配,查找或者分割,无需使用容器来容纳。

//***********************************************************
//FUNCTION:: String_algo find split iterator 
void string_algo_find_split()
{
    std::string Str = "Samus||samus||mario||||Link";

    //find_iterato模板参数为string::iterator或者char*
    typedef boost::find_iterator<std::string::iterator> string_find_iterator;
    string_find_iterator Pos, End;

    //first_finder判断匹配对象,获得迭代器起始位置,再用make_find_iterator真正创建迭代器对象
    for (Pos=boost::make_find_iterator(Str, boost::first_finder("samus", boost::is_equal())); Pos!=End; Pos++)
    {
        std::cout << "[" << *Pos << "] ";
    }
    std::cout << std::endl;

    typedef boost::split_iterator<std::string::iterator> string_split_iterator;
    string_split_iterator Begin, EndP;

    for (Begin=boost::make_split_iterator(Str, boost::first_finder("||", boost::is_equal())); Begin!=EndP; Begin++)
    {
        std::cout << "[" << *Begin << "] ";
    }
    std::cout << std::endl;
}

注意分割迭代器可以以任意长度的字符串作为分隔符,而普通spilt算法只能以字符作为分隔符。

【参考资料】
【1】Boost 库完全开发指南
【2】http://zh.highscore.de/cpp/boost/stringhandling.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值