C ++ Tokenizer Complexity vs strtok_r

时间:2015-08-19 17:42:52

标签: c++ c tokenize strtok

我正在提出这个问题,因为我将我的tokenizer从strtok_r移到了C ++中的等效版本。我必须使用strtok_r代替strtok,因为我有大约2个嵌套的标记来执行。

strtok_r算法是这样的:

phpize
./configure
make
make test
make install

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

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 ++版本对C版本如此重视? 对于长字符串,我必须使用C ++版本等待大约10秒,而C版本是瞬时使用相同的字符串。 因此,似乎C ++版本具有更高的复杂性...... 你怎么看?

1 个答案:

答案 0 :(得分:1)

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