65.9K
CodeProject 正在变化。 阅读更多。
Home

Token Iterator

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.50/5 (2投票s)

2000年5月4日

viewsIcon

126721

downloadIcon

676

Token 迭代器提供了一种易于使用、熟悉且可自定义的方式来遍历字符串中包含的标记。

  • 下载源代码文件 - 6 Kb
  • Token 迭代器的目的是提供一种易于使用、熟悉且可自定义的方式来遍历字符串中包含的标记。 我们的假设示例是将一个字符串分解成单词,并将单词作为列表输出。 这是代码。

    #include <iostream>
    #include <iterator>
    #include <string>
    #include <algorithm>
    #include "tokenizer.h"
    
    
    int main(){
    	
    	using namespace std;
    	using namespace jrb_stl_extensions;
    	
    	// Separate a string into words
    	string s;
    	cout << "Please enter a string with punctuation\n";
    	getline(cin,s);
    	TokenIterator<string> begin(s), end;
    	copy(begin,end,ostream_iterator<string>(cout,"\n"));
    
    }
    

    解释几句话。 所有这个类和支持类都打包在 jrb_stl_extensions 命名空间中。

    易于使用。 只有 2 行完成了实际工作。

    让我们分析一下。 TokenIterator 有一个默认的模板参数,它指定了 TokenizerFunc,它是一个 STL 风格的仿函数。 默认值是 PunctSpaceTokenizer,它将基于空格和标点符号进行标记化。 构造函数具有此签名

    PunctSpaceTokenizer(bool returnPunct = false, StringType p = WT_Punctuation1, 
                        StringType w = WT_Whitespace)

    returnPunct - 告诉我们是否要返回标点符号。 返回标点符号可能很重要,例如当构建数学表达式解析器时,虽然我们想跳过空格,但我们不想跳过 + 和 -。

    p - 标点符号。 有两个常量称为 WT_Punctuation1,它是标准美国键盘上的所有标点符号。 WT_Punctuation2 与 WT_Punctuation1 相同,除了它没有 -(连字符/破折号) 或 '(撇号/单引号)。 这样做的原因是某些单词带有连字符或撇号(如 can't),我们希望将它们保留为一个标记。

    w - 空格。 空格和标点符号之间的区别在于,可以使用 returnPunct 标志返回标点符号。 WT_Whitespace 是一个具有标准空格的常量。

    现在,让我们看看熟悉的部分。 TokenIterator 是一个 STL 前向迭代器,可以与任何可以接受它的 STL 算法一起使用,例如 copy。 此外,复制 TokenIterator 不会复制整个字符串。 由于字符串从未被修改,因此引用计数指针在所有引用特定字符串的 TokenIterator 之间共享。

    关于可定制性。 PunctSpaceTokenizer 可能无法满足您的所有需求。 别担心,TokenIterator 很容易为 TokenizerFunc 定制。

    以下是 TokenizerFunc 的要求。

    1. Typedefs - TokenType
      这将引用标记的类型。 对于我们的示例,这是一个字符串。 这将是 operator*() 的返回类型。 需要多个字符串标记的示例可能是一个解析器,它返回一个包含字符串和其他识别信息的对象。
    2. operator()(...)
      这具有以下原型
      iter operator()(iter* pTokEnd,iter end,TokenType& tToken)
      返回值 - 这将返回字符串中下一个标记的开始位置。
      pTokEnd - 这应该设置为标记在字符串中的 STL 风格结束位置(即,超过结尾)
      end - 这是字符串的结束位置,并传递给仿函数
      tToken - 这应该设置为当前标记。 TokenType 为字符串,将是 [retval,pTokEnd)

    如果您想要一个例子,请研究 CSVTokenizer 仿函数。

    我们将检查使用 CSVTokenizerCSVTokenizer 将字符串分解为 C(即逗号)分隔的字段。 逗号是一个模板参数,可以是任何字符。 假设逗号是参数,则字符串将被分解为由逗号分隔的字段,除非逗号位于引号内。 此外,构造函数接受一个字符,默认为 \ ('\\' 在 C 语法中)。 该字符就像 C 中的相同字符,即转义字符。 例如,\" 意味着字面上的 ",\\ 意味着字面上的 \

    也许一个例子会有所帮助

    John \"Big John\" Doe,"1111 Anytown, USA 12345" 将被分解为
    John "Big John" Doe
    1111 Anytown, USA 12345
    

    使用它的一个例子如下。 在我们之前的示例下面添加以下几行。

    // Here is some code that will break up a entries formatted like this
    // "field1","field3","field5,5"
    // it uses c-like escape codes for quotes namely \" for " and \\ for \ 
    // a comma is the field separator unless it is embedded inside quotes
    cout << "Please enter a comma separated line of fields\n";
    getline(cin,s);
    TokenIterator<string,CSVTokenizer<string> > begin2(s),end2;
    copy(begin2,end2,ostream_iterator<string>(cout,"\n"));
    

    这将输出字段。

    好了,这就是我对 TokenIterator 的概述。 我希望您喜欢使用这个类。

    注意:当使用 MSVC 6 编译该示例时,生成的警告是关于 main 中没有返回值的,以及模板导致标识符在调试中被截断为 255 个字符。

    John Bandela
    版权所有 2000 John R. Bandela

    © . All rights reserved.