C语言字符串动态分配求助:用户输入句子的单词内存分配实现
解决动态分配内存存储输入单词的问题
我来帮你搞定这个问题~你现在的代码存在几个关键问题,导致无法正确完成动态内存分配和单词的存储:
- 每次循环里重新定义
char *words,会覆盖之前的指针,不仅没法保存所有单词的地址,还会造成内存泄漏(之前malloc的内存再也找不到了) - 没有一个动态扩展的指针数组来存储每个单词的地址,毕竟我们没法提前知道用户会输入多少个单词
- 没有处理
malloc失败的情况,也没有完整的函数结构来返回单词数量或错误码
下面是修正后的完整实现,我会逐部分解释:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 函数返回单词数量,失败返回-1;words指针会被赋值为存储单词的指针数组 int getInputWords(char ***words) { // 初始化存储单词指针的数组,初始容量设为4 size_t capacity = 4; *words = (char **)malloc(capacity * sizeof(char *)); if (*words == NULL) { perror("Failed to allocate memory for words array"); return -1; } char str[50]; int wordCount = 0; // 循环读取每个单词,直到EOF(输入Ctrl+D/Ctrl+Z) while (scanf("%49s", str) != EOF) { size_t len = strlen(str); // 为当前单词分配内存(+1是给终止符'\0'留位置) char *wordPtr = (char *)malloc((len + 1) * sizeof(char)); if (wordPtr == NULL) { perror("Failed to allocate memory for word"); // 内存分配失败,要释放已经分配的所有内存,避免泄漏 for (int i = 0; i < wordCount; i++) { free((*words)[i]); } free(*words); *words = NULL; return -1; } // 复制单词到分配的内存 strcpy(wordPtr, str); // 检查指针数组是否已满,满了就扩容(通常扩为原来的2倍) if (wordCount >= capacity) { capacity *= 2; char **temp = (char **)realloc(*words, capacity * sizeof(char *)); if (temp == NULL) { perror("Failed to reallocate memory for words array"); // 扩容失败,同样要清理已分配的内存 free(wordPtr); // 刚分配的这个单词也要释放 for (int i = 0; i < wordCount; i++) { free((*words)[i]); } free(*words); *words = NULL; return -1; } *words = temp; } // 把当前单词的地址存入数组,单词计数+1 (*words)[wordCount++] = wordPtr; } // 可选:如果最后数组有多余空间,可以缩容节省内存(非必须) if (wordCount < capacity) { char **temp = (char **)realloc(*words, wordCount * sizeof(char *)); if (temp != NULL) { *words = temp; } // 如果缩容失败,不用管,继续用原来的数组就行,不影响功能 } return wordCount; } // 测试用例 int main() { char **words = NULL; int count = getInputWords(&words); if (count == -1) { printf("Memory allocation failed\n"); return 1; } printf("You entered %d words:\n", count); for (int i = 0; i < count; i++) { printf("%s\n", words[i]); free(words[i]); // 释放每个单词的内存 } free(words); // 释放指针数组的内存 return 0; }
关键细节说明:
- 三级指针参数
char ***words:因为我们要在函数内部修改外部的指针数组指针(比如malloc、realloc后更新地址),所以需要传递指针的指针的指针,或者你也可以让函数返回char **,同时用一个指针参数返回单词数量,不过用三级指针的方式更符合你要求的“返回单词数量”的设计。 - 动态扩容的指针数组:一开始分配一个初始容量,当单词数量达到容量时,用
realloc扩容为原来的2倍,这样避免频繁扩容,效率更高。 - 内存泄漏防护:任何一步内存分配失败时,都要把之前已经分配的所有内存(包括每个单词的内存和指针数组的内存)全部释放,然后返回-1,避免内存泄漏。
scanf("%49s", str):限制读取长度为49,避免输入过长导致缓冲区溢出(因为str的大小是50,留一个位置给'\0')。- 最后可选的缩容:如果输入的单词数远小于数组容量,可以用
realloc缩容,节省内存,这一步不是必须的,但属于优化。
使用的时候,记得在主函数里用完单词后,要先逐个free每个单词的内存,再free指针数组的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者waterflower
相关产品推荐
相关产品推荐

