boost的字符串处理函数——stringalgorithm
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的设计还是以性能为主的。⽽程序天然没有返回值拷贝带来的开销,可以采取那种更简洁的接⼝形式。
PS:我觉得可以像那样,在堆变量中保存结果,然后通过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");
pty())
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
它要求先把参数放到容器⾥,不像的那样可以直接传⼊动态参数那样好⽤,如果能写成这样的重载形式会更好点(当然,⾃⼰封⼀个也不难):
join("-", "hello", "world", "123", …)
其它
其它还有⼀些条件函数,主要配合算法使⽤。如前⾯已经见过的、常⽤的还有、、、等,这⾥就不多介绍了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论