[英]return value is not displayed if printf in the other method is commented
在下面的代码中似乎发生了一些奇怪的事情。 当对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;
}
这是一个经典的错误。 令牌是本地的。 返回它会产生不可预测的结果。 如果尚未覆盖它,可以在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的函数可重入),其中实现为每个调用使用本地缓冲区,因此可以从多个线程轻松地调用。
不用使用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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.