boost tokenizer
tokenizer:
tokenizer库是一个专门用于分词(token)的字符串处理库,可以使用简单易用的方法把一个字符串分解成若干个单词;
#include<boost/tokenizer.hpp>
uning namespace boost;
tolenizer类是tokenizer库的核心,它以容器的外观提供分词的序列。
类摘要:
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接受三个模板类型参数:
【1】TokenizerFunc:tokenizer库专门的分词函数对象,默认是使用空格和标点分词;
【2】Iterator:字符序列的迭代器类型;
【3】Type:保存分词结果的类型;
这三个模板类型都提供了默认值,但通常只有前两个模板参数可以变化,第三个类型一般只能选择std::string或者std::wstring,这也是它位于模板参数列表最后的原因.
tokeninzer的构造函数接受要进行分词的字符串,可以以迭代器的区间形式给出,也可以是一个有begin()和end()成员函数的容器.
assign()函数可以重新指定要分词的字符串,用于再利用tokenizer
tokenizer具有类似标准容器的接口,begin()函数使用tokenizer开始执行分词功能,返回第一个分词的迭代器,end()函数表明迭代器已经到达分词序列的末尾,分词结束。
用法:
tokenizer的用法很像string_algo的分割迭代器,可以像使用一个容器那样使用它,向tokenizer传入一个欲分词的字符串构造,然后用begin()获得迭代器反复迭代,就可以完成分词功能。
示例:
#include <assert.h>
#include <iostream>
#include <vector>
#include <boost/assign.hpp>
#include <boost/tokenizer.hpp>
#include <boost/typeof/typeof.hpp>
using namespace boost;
using namespace std;
int main()
{
string str("Link raise the master-sword.");
tokenizer<> tok(str); //使用缺省模板参数创建分词对象
//可以像遍历一个容器一样使用for循环获得分词结果
for (BOOST_AUTO(pos, tok.begin()); pos != tok.end(); ++pos)
cout<< "[" << *pos<<"]";
cout<<endl;
system("pause");
return 0;
}
注意:tokenizer默认把所有的空格和标点作为分隔符,因此分割出的只是单词,这与string_algo::split的算法含义(分割字符串)有所差别.
分词函数对象:
tokenizer作为分词的容器本身的用法很简单,它的真正威力在于第一个模板类型参数TokenizerFunc, TokenizerFunc是一个函数对象,它决定如何进行分词处理,TokenizerFunc同时也是一个规范,只要具有合适的operator()和reset()语义的函数对象,都可以用于tokenizer分词.
tokenizer库提供预定义好的四个分词对象,它们是:
【1】char_delimiters_separator:使用标点符号分词,是tokenizer默认使用的分词函数对象,但它已经被声明废弃,应当尽量不使用它;
【2】char_separator:它支持一个字符集合作为分隔符,默认的行为与char_delimiters_separator类似;
【3】escaped_list_separator:用csv格式(逗号分隔)的分词;
【4】offset_separator:使用偏移量来分词,在分解平文件格式的字符串时很有用。
char_separator:
char_separator使用了一个字符集合作为分词依据,行为很类似split算法,它的构造函数声明是:
char_separator(const char* dropped_delims, const char * kept_delims = 0, empty_token_policy empty_tokens = drop_empty_tokens);
构造函数中的参数含义如下:
【1】第一个参数dropped_delims是分隔符集合,这个集合中的字符不会作为分词的结果出现;
【2】第二个参数kept_delims也是分隔符集合,但其中的字符会保留在分词结果中;
【3】第三个参数empty_tokens类似split算法eCompress参数,处理连续出现的分隔符,如为keep_empty_tokens则表示连续出现的分隔符标识了一个空字符串,相当与split算法的token_compress_off值,如为drop_empty_tokens,则空白单词不会作为分词的结果。
如果使用默认的构造函数,不传入任何参数,则其行为等同于char_separator(" ", 标点符号, drop_empty_tokens),以空格和标点符号分词,保留标点符号,不输出空白单词;
示范:
#include <assert.h>
#include <iostream>
#include <vector>
#include <boost/assign.hpp>
#include <boost/tokenizer.hpp>
#include <boost/typeof/typeof.hpp>
using namespace boost;
using namespace std;
template<typename T>
void print(T &tok)
{
//可以像遍历一个容器一样使用for循环获得分词结果
for (BOOST_AUTO(pos, tok.begin()); pos != tok.end(); ++pos)
cout<< "[" << *pos<<"]";
cout<<endl;
}
int main()
{
char* str("Link ;; the <master-sword>.zelda");
char_separator<char> sep; //一个char_separator对象
//传入char_separator构造分词对象
tokenizer<char_separator<char>, char*> tok(str, str + strlen(str), sep);
print(tok);
tok.assign(str, str + strlen(str)); //重新分词
char_separator<char>(" :-", "<>");
print(tok);
tok.assign(str, str + strlen(str)); //重新分词
char_separator<char>(" :-", "", keep_empty_tokens);
print(tok);
system("pause");
return 0;
}
这段代码对tokenizer的模板参数稍微做了一下改变,第二个参数改为char*,这使得tokenizer可以分析c风格的字符串数组,同时构造函数也必须变为传入字符串的首末位置,不能仅传递一个字符串首地址,因为字符串数组不符合容器的概念。
第一次分词使用char_separator的缺省构造,以空格和标点分词,保留标点作为单词的一部分,并抛弃空白单词,第二次分词使用";-"和"<>"共5个字符分词,保留<>作为单词的一部分,同样抛弃空白单词;最后一次分词同样使用" ;-<>"分词,但都不作为单词的一部分,并且保留空白单词.
escaped_list_separator:
escaped_list_separator是专门处理CSV格式(Comma Split Value,逗号分隔值)的分词对象,它的构造函数声明是:
escaped_list_separator(char e = '\\', char c = ',', char q = '\"')
escaped_list_separator的构造函数参数一般都是取默认值,含义如下:
【1】第一个参数e指定了字符串中转义字符,默认是斜杠\;
【2】第二个参数是分隔符,默认是逗号;
【3】第三个参数是引号字符,默认是";
示范:
#include <assert.h>
#include <iostream>
#include <vector>
#include <boost/assign.hpp>
#include <boost/tokenizer.hpp>
#include <boost/typeof/typeof.hpp>
using namespace boost;
using namespace std;
template<typename T>
void print(T &tok)
{
//可以像遍历一个容器一样使用for循环获得分词结果
for (BOOST_AUTO(pos, tok.begin()); pos != tok.end(); ++pos)
cout<< "[" << *pos<<"]";
cout<<endl;
}
int main()
{
string str = "id,100,name.Name;易做图,\"mario\"";
escaped_list_separator<char> sep;
tokenizer<escaped_list_separator<char>> tok(str, sep);
print(tok);
system("pause");
return 0;
}
offset_separator:
offset_separator与前两种分词函数对象不用,它分词的功能不基于查找分隔符,而是使用偏移量的概念,在处理某些不使用分隔符而使用固定字段宽度的文本时很有用,构造函数声明:
template<typename Iter>
offset_separator(Iter
补充:综合编程 , 其他综合 ,