将字符串拆分为 C 中的双指针
Split a string into double pointer in C
我正在尝试将字符串(示例:"hey there mister")转换为指向句子中每个单词的双指针。
所以:split_string->|pointer1|pointer2|pointer3|其中 pointer1->"hey"、pointer2->"there" 和 pointer3->"mister".
char **split(char *s) {
char **nystreng = malloc(strlen(s));
char str[strlen(s)];
int i;
for(i = 0; i < strlen(s); i++){
str[i] = s[i];
}
char *temp;
temp = strtok(str, " ");
int teller = 0;
while(temp != NULL){
printf("%s\n", temp);
nystreng[teller] = temp;
temp = strtok(NULL, " ");
}
nystreng[teller++] = NULL;
//free(nystreng);
return nystreng;
}
我的问题是,为什么这不起作用?
有两件事你需要做 -
char str[strlen(s)]; //size should be equal to strlen(s)+1
额外 1
'[=12=]'
。现在你将 str
(未以 '[=12=]'
终止)传递给 strtok
,这会导致 undefined behavior 。
第二件事,你还需要为nystring
的每个指针分配内存,然后使用strcpy
而不是指向temp
(不要忘记space 表示 nul 终止符 )。
您的代码有多个问题。其中:
char **nystreng = malloc(strlen(s));
就是错的。您需要的 space 的大小是 char *
的大小乘以字符串将被分割成的块数加一(对于 NULL 指针终止符)。
你用从 strtok()
操作 local 数组 str
获得的指针填充 *nystreng
。这些指针仅在 str
的生命周期内有效,该生命周期在函数 returns.
时结束
你没有为str
中的字符串终止符分配space,你也没有写一个,但你把它传递给strtok()
就好像它是一个终止的字符串。
您不会在标记化循环内递增 teller
,因此每个标记指针都会覆盖前一个。
这里你有一个根本问题,你不知道在拆分字符串之前会有多少部分。尽管如此,您仍然可以通过计算分隔符的数量并加 1 来获得上限。然后您可以为那么多 char
指针加一个分配 space。或者,您可以构建一个链表来处理标记化的片段,然后仅在知道有多少片段后才分配结果数组。
至于str
,如果你想return指向它,就像你所做的那样,那么它也需要动态分配。如果您的平台提供 strdup()
那么您可以使用
char *str = strdup(s);
否则,您需要检查长度,分配足够的 space 和 malloc()
(包括终止符 space),并将输入字符串复制到分配的 space,大概是 strcpy()
。通常你会想在之后释放字符串,但如果你 returning 指向那个 space.
则不能这样做
另一方面,您可能会考虑 return 可以 单独 释放的字符串数组。为此,您必须单独分配每个子字符串(strdup()
将再次成为您的朋友,如果您有的话),在这种情况下,您可能希望释放正在工作的 space(或允许它被清理如果您使用 VLA,则自动执行)。
我正在尝试将字符串(示例:"hey there mister")转换为指向句子中每个单词的双指针。 所以:split_string->|pointer1|pointer2|pointer3|其中 pointer1->"hey"、pointer2->"there" 和 pointer3->"mister".
char **split(char *s) {
char **nystreng = malloc(strlen(s));
char str[strlen(s)];
int i;
for(i = 0; i < strlen(s); i++){
str[i] = s[i];
}
char *temp;
temp = strtok(str, " ");
int teller = 0;
while(temp != NULL){
printf("%s\n", temp);
nystreng[teller] = temp;
temp = strtok(NULL, " ");
}
nystreng[teller++] = NULL;
//free(nystreng);
return nystreng;
}
我的问题是,为什么这不起作用?
有两件事你需要做 -
char str[strlen(s)]; //size should be equal to strlen(s)+1
额外 1
'[=12=]'
。现在你将 str
(未以 '[=12=]'
终止)传递给 strtok
,这会导致 undefined behavior 。
第二件事,你还需要为nystring
的每个指针分配内存,然后使用strcpy
而不是指向temp
(不要忘记space 表示 nul 终止符 )。
您的代码有多个问题。其中:
char **nystreng = malloc(strlen(s));
就是错的。您需要的 space 的大小是char *
的大小乘以字符串将被分割成的块数加一(对于 NULL 指针终止符)。你用从
strtok()
操作 local 数组str
获得的指针填充*nystreng
。这些指针仅在str
的生命周期内有效,该生命周期在函数 returns. 时结束
你没有为
str
中的字符串终止符分配space,你也没有写一个,但你把它传递给strtok()
就好像它是一个终止的字符串。您不会在标记化循环内递增
teller
,因此每个标记指针都会覆盖前一个。
这里你有一个根本问题,你不知道在拆分字符串之前会有多少部分。尽管如此,您仍然可以通过计算分隔符的数量并加 1 来获得上限。然后您可以为那么多 char
指针加一个分配 space。或者,您可以构建一个链表来处理标记化的片段,然后仅在知道有多少片段后才分配结果数组。
至于str
,如果你想return指向它,就像你所做的那样,那么它也需要动态分配。如果您的平台提供 strdup()
那么您可以使用
char *str = strdup(s);
否则,您需要检查长度,分配足够的 space 和 malloc()
(包括终止符 space),并将输入字符串复制到分配的 space,大概是 strcpy()
。通常你会想在之后释放字符串,但如果你 returning 指向那个 space.
另一方面,您可能会考虑 return 可以 单独 释放的字符串数组。为此,您必须单独分配每个子字符串(strdup()
将再次成为您的朋友,如果您有的话),在这种情况下,您可能希望释放正在工作的 space(或允许它被清理如果您使用 VLA,则自动执行)。