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

C语言中如何正确将文本文件逐行存储到动态数组?

C语言读取变长行到动态数组的问题解决

你的代码运行后重复打印最后一行,核心原因和你猜测的完全一致:所有数组元素都指向同一个buffer的内存地址,每次fgets只是覆盖了buffer内的内容,并没有为每行文本分配独立的存储空间。

解决方案

需要为每行文本分配独立内存并复制内容,而不是直接传入buffer的指针。以下是修改后的完整代码:

优化后的动态数组实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct array {
    char **elements;
    long size;
    long capacity;
};

void array_init(struct array *array, long capacity)
{
    array->size = 0; // 必须初始化size为0,原代码遗漏了这一步
    array->capacity = capacity;
    array->elements = malloc(capacity * sizeof(char*));
    if (!array->elements) {
        perror("malloc failed for array elements");
    }
}

void array_push_back(struct array *array, char *element)
{
    if (!array || !element) return;

    if (array->size == array->capacity) {
        long new_capacity = array->capacity * 2;
        // 先分配新内存,再替换原指针,避免分配失败时丢失原数据
        char **new_elements = realloc(array->elements, new_capacity * sizeof(char*));
        if (!new_elements) {
            perror("realloc failed for array expansion");
            return;
        }
        array->elements = new_elements;
        array->capacity = new_capacity;
    }
    array->elements[array->size++] = element;
}

修改后的文件读取代码

int main(int argc, char *argv[])
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return 1;
    }
    const char *filename = argv[1];

    struct array array;
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror("failed to open file");
        return 1;
    }

    const unsigned MAX_LENGTH = 256;
    char buffer[MAX_LENGTH];
    array_init(&array, 1000);

    while (fgets(buffer, MAX_LENGTH, file))
    {
        // 复制当前行到新分配的内存,strdup自动处理内存分配和字符串复制
        char *line = strdup(buffer);
        if (!line) {
            perror("strdup failed for line");
            // 清理已分配的内存
            for (long i = 0; i < array.size; i++) {
                free(array.elements[i]);
            }
            free(array.elements);
            fclose(file);
            return 1;
        }
        array_push_back(&array, line);
    }

    // 打印所有行
    for (long i = 0; i < array.size; i++)
    {
        printf("%s", array.elements[i]); // 使用格式化字符串更安全
    }

    // 释放所有内存
    for (long i = 0; i < array.size; i++) {
        free(array.elements[i]);
    }
    free(array.elements);
    fclose(file);

    return 0;
}

关键修改说明

  • 初始化size成员:原动态数组代码未初始化size,会导致array_push_back中的判断逻辑出现未定义行为,必须显式设为0。
  • 为每行分配独立内存:用strdup复制buffer内容,生成新的字符串指针,确保数组中每个元素指向独立的内存块,不会被后续fgets覆盖。
  • 错误检查:增加了文件打开、内存分配的错误处理,避免程序崩溃或内存泄漏。
  • 安全的内存扩容:扩容时先通过realloc获取新内存,再替换原指针,防止分配失败时丢失已存储的数据。
  • 内存释放:程序结束前释放所有分配的内存,避免内存泄漏。

如果你的环境不支持strdup,可以手动实现一个替代函数:

char* my_strdup(const char* s) {
    if (!s) return NULL;
    size_t len = strlen(s) + 1;
    char* dup = malloc(len);
    if (dup) {
        strcpy(dup, s);
    }
    return dup;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:25:40