boost 字符串处理(1)
2015-10-27 12:03
1031 查看
字符串算法
头文件 include
1.首先讨论最简单的一个参数token_compress_on,为一个枚举类型
token_compress_on 为压缩方式,如果在str1中遇到连续的’-‘,’*’则压缩成一个
该参数下结果如下:
+ &SplitVec 0x005dfa9c [3](“hello abc”,”ABC”,”aBc goodbye”)
token_compress_off 为非压缩凡是,和上面的相反结果为:
+ &SplitVec 0x0059fc88 [7](“hello abc”,”“,”“,”ABC”,”“,”“,”aBc goodbye”)
当然这个不是重点,重点是以上的枚举类型写法,通过using方式将algorithm空间中的变量提升到boost空间中,这种方法比较常用,可避免枚举类型的冲突。
2.is_any_of(“-*”)
该函数返回一个is_any_of的struct对象,该对象为仿函数。
这些类似的仿函数生成函数,还提供几个
这样就好理解了,在执行split过程中,调用is_any_of(),仿函数来判断是否需要切割,如果返回true则切割,false则继续查找。
当然每一次的切割结果放入SplitVec容器中。理解这个之后,自己也可以写这个仿函数了。
split
Split input into parts
iter_split
Use the finder to find matching substrings in the input and use them as separators to split the input into parts
split的内部是调用iter_split,iter_split是使用迭代器方式的。下面来看下iter_split中的具体实现:
在iter_split将Input转换为迭代器,也就是lit_input。然后使用make_transform_iterator转换函数,转换为split_iterator迭代器。这时候split_iterator的begin指向了字符串的首地址。在split_iterator类中实现了
迭代器中的++操作。在match_type结构中有两个指针,begin和end用来指向当前迭代器中的有效部分,每一次do_find就可以将两个指针向后移动。
那么do_find函数从何而来呢?
可以看一下,split_iterator 类的派生关系,可以看到这个类:detail::find_iterator_base,do_find就是来自这个类。
现在来看下do_find函数,其中的m_Finder就是iter_split的最后一个参数FinderT Finder,也就最后用来传递给split_iterator的。m_Finder也就是::boost::algorithm::token_finder( Pred, eCompress )生成的仿函数对象。
在token_finder中又包含了一层,这样来看的话token_finderF的才是仿函数的名字了。
template< typename PredicateT >
inline detail::token_finderF
token_finder(
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off )
{
return detail::token_finderF( Pred, eCompress );
}
看下token_finderF仿函数实现
ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
就是查找的重点了,m_Pred 就是is_any_of(“-*”),
当遇到”-*”中的任意一个返回true的仿函数。
这样的话就可以通过token_finderF的仿函数返回满足m_Pred条件的区域了。
在boost::algorithm中,主要包括以下几类算法的实现,
算法:
1. to_upper to_lower 字符串大小写的转换
2. trim_left trim_right trim 字符串左右空白字符的裁剪
3. starts_with ends_with contains …等 字符串包含关系
4. find 字符串查找
5. replace 字符串替换
6. split 字符串切割
7. join 字符串拼接
详细查看
http://www.boost.org/doc/libs/1_55_0/doc/html/string_algo/quickref.html
头文件 include
一.从split开始
string str1("hello abc-*-ABC-*-aBc goodbye"); vector<string> SplitVec; //结果 split(SplitVec, str1, is_any_of("-*"), token_compress_on);
1.首先讨论最简单的一个参数token_compress_on,为一个枚举类型
namespace boost { namespace algorithm { //! Token compression mode /*! Specifies token compression mode for the token_finder. */ enum token_compress_mode_type { token_compress_on, //!< Compress adjacent tokens token_compress_off //!< Do not compress adjacent tokens }; } // namespace algorithm // pull the names to the boost namespace using algorithm::token_compress_on; using algorithm::token_compress_off; } // namespace boost
token_compress_on 为压缩方式,如果在str1中遇到连续的’-‘,’*’则压缩成一个
该参数下结果如下:
+ &SplitVec 0x005dfa9c [3](“hello abc”,”ABC”,”aBc goodbye”)
token_compress_off 为非压缩凡是,和上面的相反结果为:
+ &SplitVec 0x0059fc88 [7](“hello abc”,”“,”“,”ABC”,”“,”“,”aBc goodbye”)
当然这个不是重点,重点是以上的枚举类型写法,通过using方式将algorithm空间中的变量提升到boost空间中,这种方法比较常用,可避免枚举类型的冲突。
2.is_any_of(“-*”)
该函数返回一个is_any_of的struct对象,该对象为仿函数。
这些类似的仿函数生成函数,还提供几个
// pull names to the boost namespace using algorithm::is_classified; using algorithm::is_space; using algorithm::is_alnum; using algorithm::is_alpha; using algorithm::is_cntrl; using algorithm::is_digit; using algorithm::is_graph; using algorithm::is_lower; using algorithm::is_upper; using algorithm::is_print; using algorithm::is_punct; using algorithm::is_xdigit; using algorithm::is_any_of; using algorithm::is_from_range;
这样就好理解了,在执行split过程中,调用is_any_of(),仿函数来判断是否需要切割,如果返回true则切割,false则继续查找。
当然每一次的切割结果放入SplitVec容器中。理解这个之后,自己也可以写这个仿函数了。
二.split拓展
先给一个大致的流程图split
Split input into parts
iter_split
Use the finder to find matching substrings in the input and use them as separators to split the input into parts
template< typename SequenceSequenceT, typename RangeT, typename PredicateT > inline SequenceSequenceT& split( SequenceSequenceT& Result, RangeT& Input, PredicateT Pred, token_compress_mode_type eCompress=token_compress_off ) { return ::boost::algorithm::iter_split( Result, Input, ::boost::algorithm::token_finder( Pred, eCompress ) ); }
split的内部是调用iter_split,iter_split是使用迭代器方式的。下面来看下iter_split中的具体实现:
template< typename SequenceSequenceT, typename RangeT, typename FinderT > inline SequenceSequenceT& iter_split( SequenceSequenceT& Result, RangeT& Input, FinderT Finder ) { BOOST_CONCEPT_ASSERT(( FinderConcept<FinderT, BOOST_STRING_TYPENAME range_iterator<RangeT>::type> )); iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); typedef BOOST_STRING_TYPENAME range_iterator<RangeT>::type input_iterator_type; typedef split_iterator<input_iterator_type> find_iterator_type; typedef detail::copy_iterator_rangeF< BOOST_STRING_TYPENAME range_value<SequenceSequenceT>::type, input_iterator_type> copy_range_type; input_iterator_type InputEnd=::boost::end(lit_input); typedef transform_iterator<copy_range_type, find_iterator_type> transform_iter_type; transform_iter_type itBegin= ::boost::make_transform_iterator( find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ), copy_range_type() ); transform_iter_type itEnd= ::boost::make_transform_iterator( find_iterator_type(), copy_range_type() ); SequenceSequenceT Tmp(itBegin, itEnd); Result.swap(Tmp); return Result; }
在iter_split将Input转换为迭代器,也就是lit_input。然后使用make_transform_iterator转换函数,转换为split_iterator迭代器。这时候split_iterator的begin指向了字符串的首地址。在split_iterator类中实现了
迭代器中的++操作。在match_type结构中有两个指针,begin和end用来指向当前迭代器中的有效部分,每一次do_find就可以将两个指针向后移动。
void increment() { match_type FindMatch=this->do_find( m_Next, m_End ); if(FindMatch.begin()==m_End && FindMatch.end()==m_End) { if(m_Match.end()==m_End) { // Mark iterator as eof m_bEof=true; } } m_Match=match_type( m_Next, FindMatch.begin() ); m_Next=FindMatch.end(); }
那么do_find函数从何而来呢?
可以看一下,split_iterator 类的派生关系,可以看到这个类:detail::find_iterator_base,do_find就是来自这个类。
template<typename IteratorT> class split_iterator : public iterator_facade< split_iterator<IteratorT>, const iterator_range<IteratorT>, forward_traversal_tag >, private detail::find_iterator_base<IteratorT>
现在来看下do_find函数,其中的m_Finder就是iter_split的最后一个参数FinderT Finder,也就最后用来传递给split_iterator的。m_Finder也就是::boost::algorithm::token_finder( Pred, eCompress )生成的仿函数对象。
// Find operation match_type do_find( input_iterator_type Begin, input_iterator_type End ) const { if (!m_Finder.empty()) { return m_Finder(Begin,End); } else { return match_type(End,End); } }
在token_finder中又包含了一层,这样来看的话token_finderF的才是仿函数的名字了。
template< typename PredicateT >
inline detail::token_finderF
token_finder(
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off )
{
return detail::token_finderF( Pred, eCompress );
}
看下token_finderF仿函数实现
ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
就是查找的重点了,m_Pred 就是is_any_of(“-*”),
当遇到”-*”中的任意一个返回true的仿函数。
这样的话就可以通过token_finderF的仿函数返回满足m_Pred条件的区域了。
template< typename ForwardIteratorT > iterator_range<ForwardIteratorT> operator()( ForwardIteratorT Begin, ForwardIteratorT End ) const { typedef iterator_range<ForwardIteratorT> result_type; ForwardIteratorT It=std::find_if( Begin, End, m_Pred ); if( It==End ) { return result_type( End, End ); } else { ForwardIteratorT It2=It; if( m_eCompress==token_compress_on ) { // Find first non-matching character while( It2!=End && m_Pred(*It2) ) ++It2; } else { // Advance by one position ++It2; } return result_type( It, It2 ); } }
三、split之外
在split中可见,boost中对字符串的处理,几乎是采用迭代器模式。在boost::algorithm中,主要包括以下几类算法的实现,
算法:
1. to_upper to_lower 字符串大小写的转换
2. trim_left trim_right trim 字符串左右空白字符的裁剪
3. starts_with ends_with contains …等 字符串包含关系
4. find 字符串查找
5. replace 字符串替换
6. split 字符串切割
7. join 字符串拼接
详细查看
http://www.boost.org/doc/libs/1_55_0/doc/html/string_algo/quickref.html
相关文章推荐
- 用dnSpy破解某旅游系统5.2版。
- 修改服务器22端口, 以防止暴力破解
- Android命名规范
- WayOS路由器电信网通双线的设置方法
- php 常用经验
- FreeRTOS 使用指南(转)
- javascript(二)构造函数
- 端口监听
- 深入理解java虚拟机之java内存模型与线程,主要参考《深入理解java虚拟机》
- U盘安装centos6.5教程(两种实现方法)
- Android编程简单实现雷达扫描效果
- 四种第三方登录(附源码)
- hibernate4性能之并发和锁机制
- Android开发报错汇总(一)
- 微信平台公众号推送文章撰写建议
- 纯CSS代码实现各类气球泡泡对话框效果的代码解析
- zabbix监控windows
- 矩阵快速幂模板
- Android 解决在页面底部置输入框,软键盘遮挡部分输入框的问题
- LightOJ 1100