用boost::tokenizer分割字符串

孙嘉
2023-12-01
说明:本文是boost::tokenizer类的整理,原文出处为boost的document,此处仅作学习笔记之用。
1、boost::tokenizer
boost::tokenizer提供了一种灵活、易用的方式来将一个字符串分解为一个字符串列表。这是个模板类,类的声明为:
template <
        class TokenizerFunc = char_delimiters_separator<char>, 
        class Iterator = std::string::const_iterator,
        class Type = std::string
  >
  class tokenizer

它的核心包括,
  • TokenizerFunc:决定了字符串分割方式
  • Iterator:确定分割后的字符串的迭代类型
  • Type:需要分割的字符串类型
boost::tokenizer的构造函数有以下两个:
tokenizer(Iterator first, Iterator last,const TokenizerFunc& f = TokenizerFunc()) 
template<class Container>
tokenizer(const Container& c,const TokenizerFunc& f = TokenizerFunc())

其中参数的意义如下:

参数

描述

c一个包含被分解的序列的容器。注:c.begin() 和 c.end() 必须可以转换为模板参数 Iterator.
f一个符合 TokenizerFunction 的函数对象,用于对序列进行分解。
first迭代器,表示被分解序列的开始位置。
last迭代器,表示被分解序列的末尾位置。
tokenizer的使用很简单,以下示例为使用默认参数进行分割字符串,
 
 
#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);
   //tokenizer通过迭代器来访问分割后的字符序列,字符分割是在遍历过程中进行的,而不是构造函数
   for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
       cout << *beg << "\n";
   }
}

 tokenizer中使用的TokenFunc在boost标准中有其他3个实现,它们分别有不同的分割规则: 
  • char_seperator :根据分隔符进行分割,可以包含多个分割字符
  • escaped_list_seperator:用于对csv文件进行分割
  • offset_seperator:根据偏移量进行分割

2、boost::char_seperator

char_separator 类基于字符分隔符来分解一个字符序列,就象 strtok() 所做的那样(但没有不可重入以及输入序列析构的问题)。

char_separator 类与 token_iterator 或 tokenizer 一起使用以执行单词分解。

定义

strtok() 函数在单词输出序列中不包含用于匹配的字符分隔符。但是,在输出序列中显示这些分隔符有时候是有用的,所以 char_separator 将这个功能作为一个选项提供。我们将在输出单词中包含分隔符称为 保留分隔符 ,而将在输出单词中不包含分隔符称为 被弃分隔符

当在输入序列中出现两个连续的分隔符时,有一个问题就是是否要输出一个 空白单词 或是直接跳过。strtok() 的行为是跳过。而 char_separator 类则提供了两个选项。

例子

第一个例子示范如何将 char_separator 作为 strtok() 函数的替代物来使用。我们指定了三个字符分隔符,它们不出现在输出单词中。我们没有指定任何保留分隔符,而且缺省情况是忽略空白单词。

// char_sep_example_1.cpp
#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;
}


输出结果是:
<Hello> <world> <foo> <bar> <yow> <baz> 

下一个例子示范了用两个被弃分隔符 '-' 和 ';' 以及一个保留分隔符 '|' 来进行单词分解。我们还指定了当出现两个连续的分隔符时,要在输出中包含空白单词。

// char_sep_example_2.cpp
#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;
}


输出结果是:
<> <> <Hello> <|> <world> <|> <> <|> <> <foo> <> <bar> <yow> <baz> <|> <>

最后一个例子示范了使用 char_separator 的缺省构造函数,按标点和空格来进行单词分解。

// char_sep_example_3.cpp
#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; // 缺省构造
   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;
}


输出结果是:
<This> <is> <,> <a> <test> 

模板参数

参数 描述 缺省值
Char 单词中的元素类型,通常为 char.

Traits 字符类型的 char_traits . char_traits<char>

3、escaped_list_seperator

escaped_list_separator 类是 TokenizerFunction 的一个实现。escaped_list_separator 对一个 csv (逗号分隔) 格式进行分解。以下是该模式的一些例子。它使用缺省的分隔符、引号和转义符。

Field 1,Field 2,Field 3
Field 1,"Field 2, with comma",Field 3
Field 1,Field 2 with \"embedded quote\",Field 3
Field 1, Field 2 with \n new line,Field 3
Field 1, Field 2 with embedded \\ ,Field 3

字段通常以逗号分隔。如果你想把逗号放入字段中,你就要用引号把它括起来。另外还支持以下三个转义序列

转义序列

结果

<escape><quote> <quote>
<escape>n newline
<escape><escape> <escape>

其中 <quote> 是指定为引号的任意字符,而 <escape> 则是指定为转义字符的任意字符。

例子

// simple_example_2.cpp
#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";
   }
}


 

构造与使用

escaped_list_separator 有两个构造函数。分别如下:

explicit escaped_list_separator(Char e = '\\', Char c = ',',Char q = '\"')

参数

描述

e 指定用作转义的字符。缺省使用 C 风格的 \ (反斜杠)。但是你可以传入不同的字符来覆盖它。你可能会这样做的一个例子是,如果你有很多字段是 Windows 风格的文件名时,路径中的每个 \ 都要转义。你可以使用其它字符作为转义字符。
c 指定用作字段分隔的字符
q 指定用作引号的字符

 

escaped_list_separator(string_type e, string_type c, string_type q):

参数

描述

e 字符串 e 中的字符都被视为转义字符。如果给定的是空字符串,则没有转义字符。
c 字符串 c 中的字符都被视为分隔符。如果给定的是空字符串,则没有分隔符。
q 字符串 q 中的字符都被视为引号字符。如果给定的是空字符串,则没有引号字符。

 

使用这个类时,将它的某个对象传给 Tokenizer 包中需要 TokenizerFunction 的地方。

 

模板参数

参数 描述
Char 单词中的元素类型,通常为 char.
Traits 字符类型的 traits 类,用于比较字符。缺省为 std::char_traits<Char>

4、offset_seperator

offset_separator 类是 TokenizerFunction 概念的一个实现,用于 tokenizer 类进行单词分解。offset_separator 按偏移量将一个字符序列分解为多个字符串。例如,如果你有一个字符串 "12252001" 和偏移量 (2,2,4),则它将该字符串分解为 12 25 2001. 例子如下:

例子

// simple_example_3.cpp
#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";
   }
}


 

构造和使用

offset_separator 有一个有用的构造函数(缺省构造函数只是为了让某些编译器高兴)。声明如下:

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

参数

描述

begin, end 指定整数偏移量序列
bwrapoffsets 指明当所有偏移量用完后是否回绕到偏移量序列的开头继续。例如字符串 "1225200101012002" 用偏移量 (2,2,4) 分解,如果 bwrapoffsets 为 true, 则分解为 12 25 2001 01 01 2002. 如果 bwrapoffsets 为 false, 则分解为 12 25 2001,然后就由于偏移量用完而结束。
breturnpartiallast 指明当被分解序列在生成当前偏移量所需的字符数之前结束,是否创建一个单词,或是忽略它。例如字符串 "122501" 用偏移量 (2,2,4) 分解,如果 breturnpartiallast 为 true,则分解为 12 25 01. 如果为 false, 则分解为 12 25,然后就由于序列中只剩下2个字符不足4个而结束。

使用这个类时,将它的某个对象传入到任何需要 TokenizerFunction 的地方。如果该对象是缺省构造的,则被分解序列中的每个字符将被作为一个单词返回(即缺省值为偏移量 1, 且 bwrapoffsets 为 true)。

 类似资料: