2

我下面的代码中似乎发生了一些奇怪的事情。当 nthtoken() 中的任何 printf 被注释时,main() 中不会显示任何标记,但是当取消注释 nthtoken() 中的任何 printf 时,main() 中会显示标记。

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 char *nthtoken (char *origStr, char *delimiters, int nth);

 int main (void) {

      char *str = "in principio creavit deus caelum et terram";
      char *delims = " ";

      char *tok = nthtoken (str, delims, 3);
      printf ("token: %s\n", tok);

      return (EXIT_SUCCESS);
 }

 char *nthtoken (char *origStr, char *delimiters, int nth) {

      char str[strlen (origStr)];
      strncpy (str, origStr, strlen (origStr) + 1);

      char *token = NULL;
      token = strtok (str, delimiters);
      // printf ("first token: %s\n", token);

      int i = 0;
      for (i = 0; i < nth; i++) {
           token = strtok (NULL, delimiters);
           //printf ("token inside the loop: %s\n", token); 
      }
      // printf ("token before returning to main(): %s\n", token);
      return token;
 }
4

3 回答 3

3

这是一个经典的错误。令牌是本地的。退回它会产生不可预知的结果。如果它没有被覆盖,你可能会在 printf 中得到它,但它不能保证,你不应该这样做。底线是,在函数终止时,局部变量超出范围,技术上不再存在于编译器或运行时。

例如,malloc 并将令牌复制到它(并在 main 中释放它)或将其作为输出参数传递给函数

char * ret_string = malloc(MAX_SIZE); // ensure this is always sufficiently large
strcpy(ret_string, token);
return ret_string;

不要忘记释放 main 中的 malloc 内存。

编辑:线程安全说明- 正如@grhegde 建议的那样,仅作记录, strtok 不是线程安全的。如果您处于多线程环境中,那么您最好找到替代方案。

为了进一步解释这一点,strtok 使用一个全局缓冲区来跟踪标记,这意味着当一个字符串被标记时,不能调用它来标记另一个字符串 。执行此操作的标准解决方案通常使用名为 strtok_r 的函数(r 表示可重入),其中实现对每个调用使用本地缓冲区,因此可以从多个线程轻松调用。

于 2012-11-02T05:26:51.140 回答
1

除了使用 malloc 并占用 free 开销之外,您也可以以这种方式工作......

#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 char *nthtoken (char *str, char *delimiters, int nth);

 int main (void) {

      char str[] = "in principio creavit deus caelum et terram";
      char *delims = " ";

      char *tok = nthtoken (str, delims, 3);
      printf ("token: %s\n", tok);

      return (EXIT_SUCCESS);
 }

 char *nthtoken (char *str, char *delimiters, int nth) {

      char *token = NULL;
      token = strtok (str, delimiters);
      // printf ("first token: %s\n", token);

      int i = 0;
      for (i = 0; i < nth; i++) {
                token = strtok (NULL, delimiters);
               //printf ("token inside the loop: %s\n", token); 
      }
      // printf ("token before returning to main(): %s\n", token);
       return token;
}
于 2012-11-02T05:58:35.313 回答
0

这称为悬空指针问题。

{
  char *token = NULL;
  ....

  return token;
} 

http://en.wikipedia.org/wiki/Dangling_pointer

于 2012-11-02T05:30:01.807 回答