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

如何将文件文本读取到结构体中的动态数组

问题分析与修正代码

原代码的核心错误

  • 内存分配逻辑错误:char **line是指向指针数组的指针,你需要先分配存储每行指针的数组空间(每个元素是char*类型),再为每个指针单独分配单行的字符内存。原代码直接分配了连续的字符内存,却当作指针数组访问,导致指针地址无效,引发未定义行为。
  • 循环条件错误:while(!feof(inputPtr))的判断时机不对,feof仅在读取操作失败后才会置位,直接用它做循环条件会导致多执行一次无效读取。
  • 索引处理错误:lineIndex是传值调用,函数内的修改无法同步到外部;且初始索引自增后直接访问line[lineIndex],会跳过索引0,还可能导致越界。

修正后的代码

首先建议给结构体增加行数字段,方便后续管理:

typedef struct Text{
    char **line;
    size_t line_count; // 存储总行数
} Text;

然后是修正后的readFile函数:

#define LINE_LENGTH 255

void readFile(FILE *inputPtr, Text *textInFile) {
    // 初始化结构体字段
    textInFile->line = NULL;
    textInFile->line_count = 0;

    char buffer[LINE_LENGTH];
    // 先读取一行到缓冲区,判断是否成功
    while (fgets(buffer, LINE_LENGTH, inputPtr) != NULL) {
        // 重新分配指针数组的空间:新增一个char*的位置
        char **temp_lines = realloc(textInFile->line, (textInFile->line_count + 1) * sizeof(char*));
        if (temp_lines == NULL) {
            // 内存分配失败,释放已分配的内存避免泄漏
            for (size_t i = 0; i < textInFile->line_count; i++) {
                free(textInFile->line[i]);
            }
            free(textInFile->line);
            textInFile->line = NULL;
            textInFile->line_count = 0;
            return;
        }
        textInFile->line = temp_lines;

        // 为当前行分配内存,需要包含字符串结束符
        textInFile->line[textInFile->line_count] = malloc(strlen(buffer) + 1);
        if (textInFile->line[textInFile->line_count] == NULL) {
            // 分配失败,清理已分配资源
            for (size_t i = 0; i < textInFile->line_count; i++) {
                free(textInFile->line[i]);
            }
            free(textInFile->line);
            textInFile->line = NULL;
            textInFile->line_count = 0;
            return;
        }

        // 复制缓冲区内容到分配的内存
        strcpy(textInFile->line[textInFile->line_count], buffer);
        // 测试打印
        printf("%s", textInFile->line[textInFile->line_count]);
        // 更新行数
        textInFile->line_count++;
    }
}

代码说明

  1. 内存分配逻辑修正:先分配存储指针的数组(sizeof(char*)),再为每行单独分配字符内存,确保line的每个元素都是有效的字符串指针。
  2. 循环条件修正:用fgets的返回值判断是否读取成功,避免feof的陷阱。
  3. 错误处理:检查realloc和malloc的返回值,分配失败时清理已分配的内存,防止内存泄漏。
  4. 行数管理:通过结构体的line_count字段记录总行数,方便后续对文本的操作。
  5. 缓冲区使用:先用栈上的缓冲区读取内容,再分配内存复制,避免直接用fgets写入未初始化的堆内存。

使用注意

调用该函数后,不再使用文本内容时,需要手动释放内存:

void freeText(Text *text) {
    for (size_t i = 0; i < text->line_count; i++) {
        free(text->line[i]);
    }
    free(text->line);
    text->line = NULL;
    text->line_count = 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:50:46