关于 Tokenizer 库

什么是tokenizer

Tokenizer 库是 boos t中的一个库,主要功能:把字符串拆成一组记号的方法。

Boost 库是为 C++ 语言标准库提供扩展的一些 C++ 程序库的总称。

boost 中的定义如下:

1
2
3
4
5
6
template <
class TokenizerFunc = char_delimiters_separator<char>,
class Iterator = std::string::const_iterator,
class Type = std::string
>
class tokenizer

Tokenizer 提供了一种把字符序列转换成一组 Token 的能力,也可以定义 Tokenizer Function 来自定义序列的切分符号,如果不指定,默认是以空格为分割,去掉一些标点符号。

例子

直接引用boost官网的一个例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// simple_example_1.cpp
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>

int main(){
using namespace std;
using namespace boost;
string s = "This is, a test";
tokenizer<> tok(s);
for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}

输出:

This
is
a
test

tokenizer的分割器

tokenizer 有三种分割器。分割器用于指定字符串的分割规则,如果不指定任何分割器,则 tokenizer 默认将字符串以空格和标点为边界分割。

char_separator

char_separator 是默认的分割器,它以一组特定的字符来分割字符串。

构造函数为:

1
explicit char_separator(const Char* dropped_delims, const Char* kept_delims = "", empty_token_policy empty_tokens = drop_empty_tokens);

其中:

  • dropped_delimskept_delims:是两个字符数组,这两个数组中的每个字符都是一个分割符。不同的是,dropped_delims 中的分割符本身被丢弃,而 kept_delims 中的分割符本身作为一个单独的记号被保留在迭代器中。默认构造函数的 dropped_delims 为空格符,kept_delims 为标点符号。

  • empty_tokens:是否保留长度0的记号。它有两个可选值,keep_empty_tokens 表示要保留空记号,而默认的 drop_empty_tokens 表示丢弃空记号。默认构造函数的 empty_tokensdrop_empty_tokens

boost 官网的例子说明:

以‘-’、‘:’、‘|’三个字符分割;没有定义保留分隔符,默认值保留标点符号;没有定义保留空记号,默认丢弃。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>

int main()
{
std::string str = ";;Hello|world||-foo--bar;yow;baz|";
typedef boost::tokenizer<boost::char_separator<char> >
tokenizer;
boost::char_separator<char> sep("-;|");
tokenizer tokens(str, sep);
for (tokenizer::iterator tok_iter = tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
std::cout << "\n";
return EXIT_SUCCESS;
}

输出:

1
<Hello> <world> <foo> <bar> <yow> <baz>

以‘-’、‘:’、‘|’三个字符分割;定义保留分割符‘|’;定义保留空记号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>

int main()
{
std::string str = ";;Hello|world||-foo--bar;yow;baz|";
typedef boost::tokenizer<boost::char_separator<char> >
tokenizer;
boost::char_separator<char> sep("-;", "|", boost::keep_empty_tokens);
tokenizer tokens(str, sep);
for (tokenizer::iterator tok_iter = tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
std::cout << "\n";
return EXIT_SUCCESS;
}

输出:

1
<> <> <Hello> <|> <world> <|> <> <|> <> <foo> <> <bar> <yow> <baz> <|> <>

默认构造函数;默认保留标点符号,默认不保留空记号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>

int main()
{
std::string str = "This is, a test";
typedef boost::tokenizer<boost::char_separator<char> > Tok;
boost::char_separator<char> sep; // default constructed
Tok tok(str, sep);
for(Tok::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
std::cout << "\n";
return EXIT_SUCCESS;
}

输出:

1
<This> <is> <,> <a> <test>

offset_separator

offset_separator 用于解析长度和格式都固定的字符串,如身份证或电话号码等。

构造函数为:

1
template<typename Iter> offset_separator(Iter begin,Iter end,bool bwrapoffsets = true, bool breturnpartiallast = true);

其中:

  • beginend:指向一个整数容器开始和末尾的迭代器,其中每个元素表示要分割的字段的字符数。

  • bwrapoffsets: 如果字符串长度大于整数容器中所有字段长度的和,是否重复解析字符串。

  • breturnpartiallast: 当字符串解析到末尾剩余部分的长度(注意:包括结尾的空字符)小于字段长度时,是保留还是丢弃剩余部分。

boost 官网的例子说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>

int main(){
using namespace std;
using namespace boost;
string s = "12252001";
int offsets[] = {2,2,4};
offset_separator f(offsets, offsets+3);
tokenizer<offset_separator> tok(s,f);
for(tokenizer<offset_separator>::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}

输出:

1
2
3
12
25
2001

escaped_ list_ separator

escaped_ list_ separator 用于解析包含转义符、分隔符和引号的字符串。

构造函数为:

1
2
explicit escaped_list_separator(Char e = '\\', Char c = ',',Char q = '\"');
explicit escaped_list_separator(string_type e, string_type c, string_type q);

其中:

  • e:为单个转义符或包含多个转义符的串。转义符后跟引号表示引号,转义符后跟n表示换行,连续两个转义符表示作为普通字符的转义符本身。

  • c:为单个分割符或包含多个分割符的串,字符串以该分隔符为边界进行分割。

  • q:为单个引号或包含多个引号的串,两个引号中间出现的分隔符不再作为分割标志,而是作为普通字符处理。

boost 官网的例子说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>

int main(){
using namespace std;
using namespace boost;
string s = "Field 1,\"putting quotes around fields, allows commas\",Field 3";
tokenizer<escaped_list_separator<char> > tok(s);
for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}

输出:

1
2
3
Field 1
putting quotes around fields, allows commas
Field 3

参考:
Table Of Contents
Boost库之tokenizer的使用/文:胡健
C++字符串分词/:董波