C++ Tokenizer 复杂性与 strtok_r

标签 c++ c tokenize strtok

我提出这个问题是因为我将分词器从 strtok_r 移到了 C++ 中的等效版本。我必须使用 strtok_r 代替 strtok,因为大部分时间我有 2 个嵌套标记化要执行。

strtok_r 算法是这样的:

char *end_token, *token, *word ;
// fill 'word'
token = strtok_r (word, " ", &end_token) ;
while (token != NULL) {
  // do something
  token = strtok_r (NULL, " ", &end_token) ;
}

而 C++ 版本是这样的(取自这里的另一篇文章):

string mystring, token ;
size_t next_token ;
// fill 'mystring'
while (token != mystring) {
    next_token = mystring.find_first_of (" ") ;
    token = mystring.substr (0, next_token) ;
    mystring = mystring.substr (next_token + 1) ;
    // do something
}

现在的问题是:为什么 C++ 版本对 C 版本如此重视? 对于长字符串,使用 C++ 版本我必须等待大约 10 秒,而使用相同字符串的 C 版本是即时的。 所以,似乎 C++ 版本具有更高的复杂性...... 你怎么看?

最佳答案

strtok()修改字符串,用空终止符替换标记定界符。如果您的长字符串有 n 个标记,该函数只是遍历字符串,将 n 个字符更改为 null,速度非常快。

在您的 C++ 替代方案中,您正在制作 2*n 个字符串拷贝,这意味着可能有 2*n 个分配操作,加上(很长)剩余字符串的纯粹拷贝,这比第一个替代方案重得多。不同之处在于您没有义务更改原始字符串。

您可以通过保持正在迭代的字符串不变来改进,例如使用偏移量进行搜索:

string mystring, token ;
size_t cur_token=0, next_token ;
// fill 'mystring'
do {
    next_token = mystring.find_first_of (" ", cur_token) ;
    token = mystring.substr (cur_token, next_token-cur_token);  // next_token-(nex_token==string::npos ? 0:cur_token) would be cleaner
    if (next_token!=string::npos) 
        cur_token = next_token+1; 
    // do something with token;
} while (next_token!=string::npos);

Live demo

关于C++ Tokenizer 复杂性与 strtok_r,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32102180/

相关文章:

perl - 在语法中分离 G0 和 G1 规则的问题

elasticsearch - Elasticsearch 中的词根替换原始字符串

c++ - QTreeWidget 子类,停止放置指示器显示给定的不需要的 dropIndicatorPosition

C++ 模板蒯因

c - C 编译器如何实现返回大型结构的函数?

c++ - Makefile 无法找到 *.o 文件来生成 .exe

C,通过标记字符串填充二维数组

c++ - 如何使用一些完全用 C\C++ 编程语言编写的库将 pcm 音频转换为文本?

c++ - 在 Eigen 中按列计算 lpNorm

c++ - 将负角度转换为正角度 : Involves invalid operand use