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

C语言中逐行读取文件并将每行单词插入二维链表的问题

动态读取文件行并构建二维链表的解决方案

核心思路

通过动态分配内存读取整行内容,再在内存中拆分每行的单词,既保留行边界,又无需提前限制行长度,完美适配未知行/单词数量的场景。

步骤实现

1. 实现动态行读取函数

手动实现一个可自动扩容的行读取函数,替代固定长度的fgets:

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

char* dynamic_getline(FILE* file) {
    size_t buf_size = 128; // 初始缓冲区大小,可按需调整
    char* buf = malloc(buf_size);
    if (!buf) return NULL;

    size_t pos = 0;
    int c;
    // 逐字符读取直到换行或文件结束
    while ((c = fgetc(file)) != EOF && c != '\n') {
        // 缓冲区不足时扩容
        if (pos >= buf_size - 1) {
            buf_size *= 2;
            char* new_buf = realloc(buf, buf_size);
            if (!new_buf) {
                free(buf);
                return NULL;
            }
            buf = new_buf;
        }
        buf[pos++] = c;
    }
    buf[pos] = '\0';

    // 处理EOF且无内容的情况
    if (c == EOF && pos == 0) {
        free(buf);
        return NULL;
    }

    return buf;
}

2. 拆分每行单词并插入链表

拿到动态读取的行字符串后,用strtok拆分单词(或手动遍历拆分),再插入到当前行的链表中:

// 辅助函数:向当前行链表插入单词
void insert_word(struct Node** line_head, const char* word) {
    struct Node* new_node = malloc(sizeof(struct Node));
    if (!new_node) return;
    strncpy(new_node->word, word, sizeof(new_node->word) - 1);
    new_node->word[sizeof(new_node->word) - 1] = '\0'; // 确保字符串终止
    new_node->words = NULL;
    new_node->next = NULL;

    if (*line_head == NULL) {
        *line_head = new_node;
    } else {
        struct Node* temp = *line_head;
        while (temp->words != NULL) {
            temp = temp->words;
        }
        temp->words = new_node;
    }
}

// 主处理逻辑
void parse_file(FILE* file, struct Node** list_head) {
    struct Node* current_line = NULL;
    char* line;
    while ((line = dynamic_getline(file)) != NULL) {
        // 创建新行的头节点
        struct Node* new_line = malloc(sizeof(struct Node));
        if (!new_line) {
            free(line);
            break;
        }
        new_line->words = NULL;
        new_line->next = NULL;

        // 拆分当前行的单词
        char* token = strtok(line, " \t"); // 按空格、制表符拆分,可添加其他分隔符
        while (token != NULL) {
            insert_word(&new_line, token);
            token = strtok(NULL, " \t");
        }

        // 将新行加入二维链表
        if (*list_head == NULL) {
            *list_head = new_line;
        } else {
            struct Node* temp = *list_head;
            while (temp->next != NULL) {
                temp = temp->next;
            }
            temp->next = new_line;
        }

        free(line); // 释放行内存
    }
}

关键说明

  • 放弃fscanf:它会跳过所有空白字符(包括换行),无法区分行边界,不符合按行处理的需求。
  • 替代fgets:固定缓冲区容易导致超长行被截断,手动实现的动态读取可自动扩容,适配任意长度的行。
  • 内存管理:所有动态分配的内存(行缓冲区、链表节点)都要记得在使用完后释放,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:12:48