我误解了win32(也许是libc)strtok()

时间:2011-06-29 04:33:53

标签: c strtok

在某些CGI代码中,我需要编码很少发生的'&','<'和'>'字符。在编码功能中,如果输入字符串中没有这样的字符,我想立即离开。因此,在参赛作品时,我尝试使用strtok( )来查找:

char *
encode_amp_lt_gt ( char *in ) {
  ...
  if ( NULL == strtok( in, "&<>" )) {
    return in;
  }
  ...
}

但是,即使没有任何分隔符,strtok( )也会返回指向in的第一个字符的指针。

如果字符串中没有delims,我希望它返回NULL。

我的代码错了,还是我的期望错了?我不想为了消除通常的情况而三次调用strchr()。

谢谢!

2 个答案:

答案 0 :(得分:4)

您可能不希望strtok开头,因为它无法确定消除了哪个字符(除非您有字符串的备用副本)。

strtok不是一个简单的API,很容易误解。

引用manpage

 The strtok() and strtok_r() functions return a pointer to the beginning of
 each subsequent token in the string, after replacing the token itself with
 a NUL character.  When no more tokens remain, a null pointer is returned.

您的问题可能意味着您已经陷入了算法的默默无闻。假设这个字符串:

char* value = "foo < bar & baz > frob";

第一次拨打strtok

char* ptr = strtok(value, "<>&");

strtok会返回value指针,除了它会将字符串修改为:

"foo \0 bar & baz > frob"

您可能会注意到,它将<更改为NUL。但是,现在,如果您使用value,则会获得"foo ",因为在途中会有NUL

strtokNULL的后续调用将继续通过字符串,直到您到达字符串的末尾,此时您将获得NULL

char* str = "foo < bar & frob > nicate";
printf("%s\n", strtok(str, "<>&")); // prints "foo "
printf("%s\n", strtok(NULL, "<>&")); // prints " bar "
printf("%s\n", strtok(NULL, "<>&")); // prints " frob "
printf("%s\n", strtok(NULL, "<>&")); // prints " nicate"
assert(strtok(NULL, "<>&") == NULL); // should be true

编写一个用strtok替换内容的函数是相当简单的,既可以自己处理辛苦的工作,也可以从strpbrkstrcat获得帮助。

答案 1 :(得分:3)

您想要的功能是strpbrk,而不是strtok。更大的问题是 - 当你替换东西时,返回的字符串是如何被分配的,以及调用函数如何知道它是否应该释放它?