You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

关键细节说明:

  1. 三级指针参数char ***words:因为我们要在函数内部修改外部的指针数组指针(比如malloc、realloc后更新地址),所以需要传递指针的指针的指针,或者你也可以让函数返回char **,同时用一个指针参数返回单词数量,不过用三级指针的方式更符合你要求的“返回单词数量”的设计。
  2. 动态扩容的指针数组:一开始分配一个初始容量,当单词数量达到容量时,用realloc扩容为原来的2倍,这样避免频繁扩容,效率更高。
  3. 内存泄漏防护:任何一步内存分配失败时,都要把之前已经分配的所有内存(包括每个单词的内存和指针数组的内存)全部释放,然后返回-1,避免内存泄漏。
  4. scanf("%49s", str):限制读取长度为49,避免输入过长导致缓冲区溢出(因为str的大小是50,留一个位置给'\0')。
  5. 最后可选的缩容:如果输入的单词数远小于数组容量,可以用realloc缩容,节省内存,这一步不是必须的,但属于优化。

使用的时候,记得在主函数里用完单词后,要先逐个free每个单词的内存,再free指针数组的内存,避免内存泄漏。

内容的提问来源于stack exchange,提问作者waterflower

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:07:43