BOOST库 之 tokenizer 字符串的分解

来源:互联网 发布:chrome linux版 编辑:程序博客网 时间:2024/05/18 15:54
一、包含
include <boost/tokenizer.hpp>
using namespace boost;

二、摘要

tokenizer库是一个专门用于分词(token)的字符串处理库,可以使用简单易用的方法把一个字符串分解成若干个单词。


三、类型说明

template< typename TokenizerFunc = char_delimiters_separator<char>,typename Iterator = std::string::const_iterator,typename Type = std::string >class tokenizer{tokenizer( Iterator first, Iterator last, const TokenizerFunc & f );tokenizer( const Container & c, const TokenizerFunc & f );void assign( Iterator first, Iterator last );void assign( const Container& c );void assign( const Container& c, const TokenizerFunc& f );iterator begin() const;iterator end() const;}
tokenizer接受三个模板类型参数,分别是:

 TokenizerFunc  : tokenizer库专门的分词函数对象,默认是使用空格和标点分词;
 Iterator       : 字符序列的迭代器类型;
 Type           : 保存分词结果的类型;

这三个模板类型都提供了默认值,但通常只有前两个模板参数可以变化,第三个类型一般只能选择std::string或者std::wstring,这也是它位于模板参数列表最后的原因.

tokenizer的构造函数接受要进行分词的字符串,可以以迭代器的区间形式给出,也可以使一个有begin()和end()成员函数的容器.

四、用法:
tokenizer的用法很像 string_algo 的分割迭代器,但要简单一些。可以像使用一个容器那样使用它,
向tokenizer传入一个欲分词的字符串构造,然后用begin()获得迭代器反复迭代,就可以轻松完成分词功能.

{std::string str( "Link raise the master-sword." );boost::tokenizer<> tok( str ); //使用缺省目标参数创建分词对象(默认是使用空格和标点分词);//可以像遍历一个容器一样使用for循环获得分词结果;for ( BOOST_AUTO( pos, tok.begin() ); pos != tok.end(); ++pos ){cout << "[" << *pos << "]";}//运行结果;//[Link][raise][the][master][sword]//【注】//tokenizer默认把所有的空格和标点符号作为分隔符,因此分割出的只是单词。}

五、分词函数对象
tokenizer的真正威力在于第一个模板类型参数TokenizerFunc。TokenizerFunc是一个函数对象,它决定如何
进行分词处理。TokenizerFunc同时也是一个规范,只要具有合适的operator()和reset()语言的函数对象都可
用于tokenizer分词。

    四个分词对象:
 char_delimiters_separator  : 使用标点符号分词,是tokenizer默认使用的分词函数对象。但已废弃,尽量不使用它.
 char_sparator              : 它支持一个字符集合作为分隔符,默认的行为与char_delimiters_sparator类似.
 escaped_list_separator     : 用于CSV格式(逗号分隔)的分词.
 offset_separator           : 使用偏移量来分词,在分解平文件格式的字符串时很有用.

template<typename T>void print( T & tok ){for ( BOOST_AUTO(pos, tok.begin()); pos != tok.end(); ++pos ){cout << "[" << *pos << "]";}cout << endl;}

//①char_sparator//构造声明char_separator( const char * droppen_delims,const char * kept_delims = 0,empty_token_policy empty_tokens = drop_empty_tokens );//参数说明://第一个参数 droppen_delims 是分隔符集合,这个集合中的字符不会作为分词结果出现;//第二个参数 kept_delims 也是分隔符集合,但其中的字符会保留在分区结果中;//第三个参数 empty_tokens 类似split算法的eCompress参数,处理两个连续出现的分隔符。//如为 keep_empty_tokens 则表示连续出现的分隔符标识了一个空字符串,相当于split//算法的token_compress_off值;如为drop_empty_tokens,则空白单词不会作为分词的结果.//如果使用默认的构造函数,不传入任何参数,则其行为等同于 char_separator( "", 标点符号字符, drop_empty_tokens )//以空格和标点符号分词,保留标点符号,不输出空白单词.char * str = "Link ;; <master-sword> zelda";boost::char_separator<char> sep; //一个char_separator对象;boost::tokenizer<boost::char_separator<char>, char*> tok( str, str + strlen(str), sep ); //传入char_separator构造分词对象print( tok ); //分词并输出//重新分词tok.assign( str, str + strlen(str), boost::char_separator<char>(" ;-", "<>") );print( tok );//重新分词tok.assign( str, str + strlen(str), boost::char_separator<char>(" ;-<>", "", keep_empty_tokens) );print( tok );//对tokenizer的目标参数做了改变,第二个参数改为 char*,这使得tokenizer可以分析C风格的字符串数组。同时构造函数也必须变为//传入字符串的首末位置,不能仅传递一个字符串首地址,因为字符串数组不符合容器的概念.//第一次分词我们使用 char_separator的缺省构造,以空格和标点分词,保留标点作为单词的一部分,并抛弃空白单词;//第二次分词我们使用" ;-"和"<>"共5个字符分词,保留<>作为单词的一部分,同样抛弃空白单词;//最后一次分词我们同样使用" ;-<>"分词,但它们都不作为单词的一部分,并且我们保留空白单词.//程序运行结果://[Link][;][;][<][master][-][sword][>][zelda]//[Link][<][master][sword][>][zelda]//[Link][][][][][master][sword][][zelda]

//②escaped_list_sparator//专门处理CSV格式(Comma Split Value,逗号分隔值)的分词对象.//构造声明escaped_list_separator( char e = '\\', char c = ',', char q = '\"' );//一般都取默认值,含义如下://第一个参数 e 指定了字符串中的转义字符,默认是斜杠/;//第二个参数是分隔符,默认是逗号;//第三个参数是引号字符,默认是";std::string str = "id,100,name,\"mario\"";boost::escaped_list_separator<char> sep;boost::tokenizer<escaped_list_separator<char>> tok( str, sep );print( tok );//程序运行结果//[id][100][name][mario]

//③offset_sparator//其与前两种分词函数对象不同,它分词的功能不基于查找分隔符,而是使用偏移量的概念,//在处理某些不使用分隔符而使用固定字段宽度的文本时很有用。//构造声明template <typename Iter>offset_separator( iter begin, iter end, bool wrap_offsets = true, bool return_partial_last = true );//offset_separator的构造函数接收两个迭代器参数(也可以使数组制作)begin和end,指定分词用的整数偏移量序列,//整数序列的每个元素是分词字段的宽度.//bool参数bwrapoffsets,决定是否在偏移量用完后继续分词。bool参数return_partial_last决定在偏移量序列//最后是否返回分词不足的部分。这两个附加参数的默认值都是true.std::string str = "2233344445";int offsets[] = {2,3,4};boost::offset_separator sep( offsets, offsets + 3, true, false );boost::tokenizer<boost::offset_separator> tok( str, sep );print( tok );tok.assign( str, boost::offset_separator(offsets, offsets + 3, false) );print( tok );str += "56667";tok.assign( str, boost::offset_separator(offsets, offsets + 3, true, false) );print( tok );//代码中我们用一个数组offsets指定了三个偏移量,要求分割出3个长度分别为2、3、4的单词//结果如下://[22][333][4444][5]//[22][333][4444]//[22][333][4444][55][666]//请注意输出的第一部分和最后一部分,两者的分词都设置了 return_partial_last 为false,但输出却略不同.//这是因为 return_partial_last 只影响偏移量序列的最后一个元素( 即代码中的 offersets[2] = 4 ),对于//序列中的其他元素则不起作用,无论是否分词不足均输出。所以输出中第一部分的[5]因为它对于偏移量序列的第一个元素,//所以总能输出,而最后一部分字符串末尾原本应该有输出[7],但因为 return_partial_last 为false 且它对应//偏移量序列的最后一个元素,所以不被输出.

【tokenizer缺陷】
它只支持使用单个字符进行分词,如果要分解如"||"等多个字符组成的分隔符则无能为力,只能自己定义分词函数对象.



原创粉丝点击