您的位置:首页 > 编程语言 > Go语言

Boost string_algo

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

前缀 i: 表明大小写不敏感

后缀_copy : 算法不变动输入,返回处理结果的复制,否则算法原地处理,输入即输出

后缀_if : 需要一个作为判断式的谓词函数对象,否则使用默认判断准则

大小写转换

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

template void to_upper(T & Input);

template void to_lower(T & Input);

判断式(算法)

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

start_with:检测一个字符串是否以另一个为前缀

end_with : 检测检测一个字符串是否以另一个为后缀

contains: 检测字符串是否包含另一个

equals: 检测两字符串是否相等

all:检测一个字符串中的所有元素是否满足指定的判断式

判断式(函数对象)

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

is_equal: 比较两个对象是否相等

is_less:比较两个对象是否具有小于关系

is_not_greater: 不大于关系

int main()
{
std::string Str1("Samus"), Str2("samus");
assert(!is_equal()(Str1, Str2));
assert(is_less()(Str1, Str2));
}


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

分类

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

is_space:字符是否为空格或制表符

is_alnum:是否为字母和数字字符

is_alpha:是否为字母

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;
}


替换和删除

replace/erase_first:替换/删除一个字符串的第一次出现

replace/erase_lase:替换/删除一个字符串的最后一次出现

replace/erase_nth:替换/删除一个字符串的第N次出现

replace/erase_all:替换/删除一个字符串的所有出现

replace/erase_head:替换/删除输入的开头

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: