Token Iterator






3.50/5 (2投票s)
2000年5月4日

126721

676
Token 迭代器提供了一种易于使用、熟悉且可自定义的方式来遍历字符串中包含的标记。
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 的要求。
- Typedefs - TokenType
这将引用标记的类型。 对于我们的示例,这是一个字符串。 这将是 operator*() 的返回类型。 需要多个字符串标记的示例可能是一个解析器,它返回一个包含字符串和其他识别信息的对象。 operator()(...)
这具有以下原型iter operator()(iter* pTokEnd,iter end,TokenType& tToken)
返回值 - 这将返回字符串中下一个标记的开始位置。
pTokEnd - 这应该设置为标记在字符串中的 STL 风格结束位置(即,超过结尾)
end - 这是字符串的结束位置,并传递给仿函数
tToken - 这应该设置为当前标记。TokenType
为字符串,将是 [retval,pTokEnd)
如果您想要一个例子,请研究 CSVTokenizer
仿函数。
我们将检查使用 CSVTokenizer
。 CSVTokenizer
将字符串分解为 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