一、包含
include <boost/tokenizer.hpp>
using namespace boost;
二、摘要
TokenizerFunc : tokenizer库专门的分词函数对象,默认是使用空格和标点分词;
Iterator : 字符序列的迭代器类型;
Type : 保存分词结果的类型;
这三个模板类型都提供了默认值,但通常只有前两个模板参数可以变化,第三个类型一般只能选择std::string或者std::wstring,这也是它位于模板参数列表最后的原因.
tokenizer的构造函数接受要进行分词的字符串,可以以迭代器的区间形式给出,也可以使一个有begin()和end()成员函数的容器.
五、分词函数对象
tokenizer的真正威力在于第一个模板类型参数TokenizerFunc。TokenizerFunc是一个函数对象,它决定如何
进行分词处理。TokenizerFunc同时也是一个规范,只要具有合适的operator()和reset()语言的函数对象都可
用于tokenizer分词。
四个分词对象:
char_delimiters_separator : 使用标点符号分词,是tokenizer默认使用的分词函数对象。但已废弃,尽量不使用它.
char_sparator : 它支持一个字符集合作为分隔符,默认的行为与char_delimiters_sparator类似.
escaped_list_separator : 用于CSV格式(逗号分隔)的分词.
offset_separator : 使用偏移量来分词,在分解平文件格式的字符串时很有用.
【tokenizer缺陷】
它只支持使用单个字符进行分词,如果要分解如"||"等多个字符组成的分隔符则无能为力,只能自己定义分词函数对象.
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缺陷】
它只支持使用单个字符进行分词,如果要分解如"||"等多个字符组成的分隔符则无能为力,只能自己定义分词函数对象.