我的代码中似乎发生了一些奇怪的事情。当注释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;
}
答案 0 :(得分:3)
这是一个经典的错误。令牌是本地的。返回它会产生不可预测的结果。你可能会在printf中得到它,如果它没有被覆盖,但是不能保证你不应该这样做。最重要的是,在函数终止时,局部变量超出范围,技术上不再存在于编译器或运行时。
malloc并将令牌复制到它(并在main中释放它)或将其作为out参数传递给函数,例如
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 for re-entrant)的函数给出,其中实现为每个调用使用本地缓冲区,因此可以从多个线程轻松调用。
答案 1 :(得分:1)
不是使用malloc而是花费免费的开销,你也可以这样工作......
#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;
}
答案 2 :(得分:0)