C语言不调用预制函数按空白符分割字符串为单词数组问题排查
ft_split_whitespaces 实现问题排查
需求说明
- 编写函数将输入字符串按空白符分割为多个单词,返回存储这些单词的数组
- 分割函数内仅可使用
malloc作为预制函数 - 函数签名必须为
char **ft_split_whitespaces(char *str)
问题现象
当前运行输出:
d this is me s is me s me r
预期输出:
Hello World This Is Me
现有实现代码
#include <stdio.h> #include <stdlib.h> int count_words(char *str) { int i; int word; i = 0; word = 1; while(str[i]!='\0') { if(str[i]==' ' || str[i]=='\n' || str[i]=='\t' || str[i]=='\f' || str[i]=='\r' || str[i]=='\v') word++; i++; } return (word); } char **ft_split_whitespaces(char *str) { int index; int size; int index2; char **arr; index = 0; index2 = 0; size = count_words(str); arr = (char **)malloc(size * sizeof(char)); if (arr == NULL) return ((char **)NULL); while (str[index]) { if(str[index] == ' ') { index++; value++; index2++; } else *(arr+index2) = (char*) malloc(index * sizeof(char)); *(arr+index2) = &str[index]; index++; } **arr = '\0'; return (arr); } int main() { char a[] = "Hello World This Is Me"; char **arr; int i; int ctr = count_words(a); arr = ft_split_whitespaces(a); for(i=0;i < ctr;i++) printf("%s\n",arr[i]); return 0; }
存在的问题
count_words计数逻辑错误:初始值设为1不合理,连续空白符、首尾空白符都会导致计数偏大,应该仅在「当前字符非空白且前一个字符是空白」的时候计数+1- 指针数组分配错误:
arr = (char **)malloc(size * sizeof(char));应该用sizeof(char*),指针数组每个元素是字符指针,占4/8字节不是1字节 - 未定义变量:
ft_split_whitespaces中使用了未声明的value变量,属于语法错误 - 分隔符判断不全:仅判断了空格作为分隔符,没有匹配
count_words中定义的其他空白符(换行、制表、换页等) - 分支逻辑错误:else分支没有加花括号,导致
*(arr+index2) = &str[index];无论if条件是否成立都会执行 - 字符串未独立拷贝:直接把指针指向原字符串地址,没有拷贝单词内容,也没有在单词末尾加
\0,会导致输出时连带后续字符串 - 单词内存分配错误:分配单词内存时用全局遍历的
index作为长度,不是当前单词的实际长度 - 末尾操作逻辑错误:
**arr = '\0';直接把第一个单词的首字符设为终止符,导致第一个单词输出为空
修复后完整代码
#include <stdio.h> #include <stdlib.h> // 判断是否是空白符的辅助函数 int is_whitespace(char c) { return c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r' || c == '\v'; } int count_words(char *str) { int i = 0; int word = 0; int in_word = 0; while(str[i] != '\0') { if (!is_whitespace(str[i]) && !in_word) { word++; in_word = 1; } else if (is_whitespace(str[i])) { in_word = 0; } i++; } return word; } char **ft_split_whitespaces(char *str) { int index = 0; int word_idx = 0; int word_len = 0; int size = count_words(str); // 多分配一个位置存NULL作为数组结束标记 char **arr = (char **)malloc((size + 1) * sizeof(char*)); if (arr == NULL) return NULL; while(str[index]) { // 跳过空白符 while (str[index] && is_whitespace(str[index])) { index++; } if (!str[index]) break; // 计算当前单词长度 word_len = 0; while (str[index + word_len] && !is_whitespace(str[index + word_len])) { word_len++; } // 分配单词内存:+1存终止符 arr[word_idx] = (char*)malloc((word_len + 1) * sizeof(char)); if (arr[word_idx] == NULL) return NULL; // 拷贝单词内容 for (int i = 0; i < word_len; i++) { arr[word_idx][i] = str[index + i]; } arr[word_idx][word_len] = '\0'; word_idx++; index += word_len; } arr[word_idx] = NULL; return arr; } int main() { char a[] = "Hello World This Is Me"; char **arr = ft_split_whitespaces(a); int i = 0; while(arr[i]) { printf("%s\n", arr[i]); i++; } // 生产环境可在此处添加内存释放逻辑避免泄漏 return 0; }
内容的提问来源于stack exchange,提问作者Alsakka
相关产品推荐
相关产品推荐

