我输入了该代码块进行作业:
char *tokens[10];
void parse(char* input);
void main(void)
{
char input[] = "Parse this please.";
parse(input);
for(int i = 2; i >= 0; i--) {
printf("%s ", tokens[i]);
}
}
void parse(char* input)
{
int i = 0;
tokens[i] = strtok(input, " ");
while(tokens[i] != NULL) {
i++;
tokens[i] = strtok(NULL, " ");
}
}
但是,看着它,我不确定内存分配是如何工作的。据我所知,我没有定义单个字符串的长度,而是定义字符串数组标记(10)中有多少个字符串。我有这个倒退吗?如果不是,那么编译器是否动态分配每个字符串的长度?需要澄清。
答案 0 :(得分:2)
strtok
是坏公民。
一方面,它会保留状态,就像您在调用strtok(NULL,...)
时所隐式使用的那样-该状态存储在Standard C库的私有内存中,这意味着仅单线程程序可以使用{ {1}}。请注意,某些库中有一个称为strtok
的可重入版本。
要回答另一个问题,请strtok_r
修改其输入。它不会为字符串分配空间。它会在输入字符串中写入NUL字符代替定界符,并在输入字符串中返回一个指针。
您正确的认为strtok
可以返回10个以上的结果。您应该在代码中进行检查,以免超出strtok
的结尾。可靠的程序可以设置上限,例如您的tokens
,并检查上限,如果超出则报告错误,或者动态地将10
数组与tokens
和{{ 1}},如果它太大。当您的内存不足时,就会发生错误。
请注意,在将输入字符串传递给malloc
之前,您还可以通过realloc
来解决strtok
修改输入字符串的问题。然后,在新字符串和指向它的strdup
超出范围后,必须释放新字符串。
答案 1 :(得分:1)
tokens
是一个指针数组。
字符串和指针之间的区别(如果经常模糊的话)。在某些情况下,最好将字符串视为数组,而在其他情况下,最好将其视为指针。
无论如何...在您的示例中,input
是一个数组,而tokens
是一个指向input
中某个位置的指针的数组。
每次调用input
都会更改strtok()
中的数据
所以,一步一步
// input[] = "foo bar baz";
tokens[0] = strtok(input, " ");
// input[] = "foo\0bar baz";
// ^-- tokens[0] points here
tokens[1] = strtok(NULL, " ");
// input[] = "foo\0bar\0baz";
// ^-- tokens[1] points here
tokens[2] = strtok(NULL, " ");
// input[] = "foo\0bar\0baz";
// ^-- tokens[2] points here
// next strtok returns NULL