strtok_r保存状态行为

时间:2019-02-20 20:47:22

标签: c tokenize strtok strsep

使用strtok_r的{​​{3}}方法如下:

char* str = strdup(string);
char* save;
char* ptr = strtok_r(str, delim, &save);
while(ptr) {
  puts(ptr);
  ptr = strtok_r(NULL, delim, &save);
}

当尝试检查save中实际存储的内容时,我发现它只是未解析的字符串的其余部分。因此,我试图使第二个呼叫看起来像第一个,并编写了如下的包装器。

char* as_tokens(char** str, const char* const delim) {
  return strtok_r(NULL, delim, str);
}

可以像下面这样使用,它的详细程度要低得多。我们不必区分首次呼叫和休息。

char* str = strdup(string);
char* ptr;
while(ptr = as_tokens(&str, delim))
  puts(ptr);

这种方法是否有缺点?我会引起任何不确定的行为吗?我尝试了一些极端情况,并且两种方法的工作方式相似。

在线编译器:correct

P.S。为简便起见,请忽略内存泄漏。


更新

已经存在几乎与我的as_tokenshttps://wandbox.org/permlink/rkGiwXOUtzqrbMpP类似的功能。 在存在连续的定界符的情况下,情况有所不同。 strsep返回一个空字符串,而as_tokens(即strtok_r)将它们视为一个空字符串。

1 个答案:

答案 0 :(得分:0)

  

这种方法是否有缺点?

是的,它丢失了str的原始值,因此(在这种情况下)无法释放它。因此,您有内存泄漏。可以通过保留单独的指针副本来解决,但是归结为与您的第一个代码几乎相同的事情。

此外,正如注释中所观察到的那样,它不符合strtok_r的规范,因为仅在第一个参数strtok_r中调用NULL的行为先前对strtok_r的调用的上下文,该调用提供了第三个参数指向的值。

此外,它与惯用的,易于理解的strtok_r用法不同,甚至可以将其隐藏在其他功能中。正常的习语并不繁重,众所周知且已广为人知。聪明地使代码难以维护。

  

我是否引起任何未定义的行为?

是的,就“未定义的行为”而言,与明确定义为 un 的行为相反。但是相关标准对这些替代品也具有相同的意义。见上文。