我编写了以下程序来解析多个目录名的路径
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *
tokenizer(char *path, char **name){
char s[300];
char *buffer;
memcpy(s, path, strlen(path)+1);
printf("%s\n",s); // PROBLEM
int i=0;
while(s[i] == '/'){
i++;
}
if (i == strlen(path)){
return NULL;
}
*name = strtok_r(s, "/", &buffer);
return buffer;
}
int main(void){
char str[300];
char *token, *p;
scanf("%s",str);
p = tokenizer(str, &token);
if (p != NULL)
printf("%s\n",token);
else
printf("Nothing left\n");
while((p=tokenizer(p, &token)) != NULL){
printf("%s\n",token);
}
}
上述程序的输出
Input: a/b/c
Output: a/b/c
a/b/c
a
b/c
b
c
c
如果我评论标记为问题的行
Input: a/b/c
Output: Some garbage value
有人可以解释一下这种奇怪行为的原因吗?
注意:
我已经意识到s
是一个堆栈分配变量,它在函数main()
中不再存在,但为什么程序在我使用printf()
时有效?
答案 0 :(得分:3)
您正在将指针返回到堆栈分配的字符串(buffer
指向s
); <{1}}返回后,s
的记忆力不再有意义。
答案 1 :(得分:3)
除了geekasaur所说的内容:
strtok_r
的第三个参数使用不正确,有两种方式:
1.在第一次调用之前应将其初始化为NULL
2.不应以任何方式使用它(将其返回给调用者)。它应该只传递给另一个strtok_r
电话。
答案 2 :(得分:1)
你不能这样做
char s[300];
char *buffer;
...
*name = strtok_r(s, "/", &buffer);
return buffer;
此处buffer
是指向s[300]
位置的指针。 s[300]
是在调用函数时在堆栈上分配的函数局部变量,并在函数返回时销毁。
所以你没有返回有效的指针,你不能将该指针用在函数之外。
答案 3 :(得分:0)
除了观察到您返回指向本地变量的指针之外,我认为值得注意的是您的tokenizer
几乎100%没有意义。
tokenizer
所做的大部分内容都会在调用/
之前跳过任何前导strtok_r
个字符 - 但您已经过了&#39; /&#39;作为strtok_r
的分隔符,它将自动跳过任何前导分隔符字符。
相当简单的代码足以打印出没有分隔符的路径组件:
char path[] = "a/b/c";
char *pos = NULL;
char *component = strtok_r(path, "/", &pos);
while (NULL != component) {
printf("%s\n", component);
component = strtok_r(NULL, "/", &pos);
}
答案 4 :(得分:0)
试试这个:
char*
token(char * path, char ** name){
static char * obuffer = NULL;
char * buffer = NULL, * p, * q;
if(path == NULL) {
buffer = realloc(buffer, strlen(obuffer) + 1);
p = obuffer;
} else {
buffer = malloc(257);
p = path;
}
if(!buffer) return NULL;
q = buffer;
if(!p || !*p) return NULL;
while(*p != '\0') {
if(*p == '/') {
p++; /* remove the / from string. */
break;
}
*q ++ = *p++;
}
*q ++ = '\0';
obuffer = p;
*name = buffer;
return buffer;
}
int main(void)
{
char * s = "foo/baa/hehehe/";
char * name = NULL;
char * t = token(s, &name);
while(t) {
printf("%s\n", name);
t = token(NULL, &name);
}
return 0;
}
输出:
foo
baa
hehehe
但你基本上是“重新发明”strtok()
功能......