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

自定义C语言链表存储TXT行:循环内外printf打印异常问题

问题分析与解决方案

核心问题1:未复制字符串,链表元素共享同一块内存

你当前的链表只是存储了getline返回的line指针,而非字符串的副本。而getline的特性是会复用同一个内存缓冲区(当现有缓冲区足够容纳新行时),这意味着:

  • 循环中每次append的content都指向同一个内存地址
  • 循环内打印时,line刚被赋值为当前行内容,所以显示正常
  • 循环结束后,所有链表元素的content实际都指向最后一次getline写入的内容(如果文件有多行,前面的元素内容也会被覆盖成最后一行)

之前用char*字面量测试正常,是因为字面量存储在只读数据段,不会被修改。

核心问题2:stdout行缓冲导致输出不显示

循环内的printf带有\n换行符,会触发stdout的行缓冲刷新,所以能立即看到输出;而循环外的printf没有换行符,stdout的内容会暂存缓冲区中,若程序直接退出,可能无法及时显示。


修复方案

1. 修改链表代码,存储字符串副本

需要在创建元素时复制传入的字符串,而不是直接存储指针。可以修改initElement函数:

#include <string.h> // 引入strlen、memcpy

// 如果是标准C环境,需要自己实现strdup(POSIX环境可直接用)
char* strdup(const char* s) {
    size_t len = strlen(s) + 1;
    char* dup = malloc(len);
    if (dup != NULL) {
        memcpy(dup, s, len);
    }
    return dup;
}

TElement* initElement(const void* content){
    TElement* element = (TElement*)malloc(sizeof(TElement));
    if (!element) return NULL;
    
    // 复制字符串内容,而非存储原指针
    element->content = strdup((const char*)content);
    if (!element->content) {
        free(element);
        return NULL;
    }
    
    element->prev = NULL;
    element->next = NULL;
    return element;
}

2. 修复输出缓冲问题

在循环外的printf后添加换行符,或者手动刷新缓冲区:

// 方案1:添加换行
printf("%s\n", (const char*)names->last->content);

// 方案2:手动刷新
printf("%s", (const char*)names->last->content);
fflush(stdout);

3. 补充内存释放逻辑(避免泄漏)

添加链表销毁函数,释放每个元素的字符串和链表本身:

void destroyList(TList* list) {
    if (!list) return;
    
    TElement* current = list->first;
    while (current) {
        TElement* next = current->next;
        free((void*)current->content); // 释放复制的字符串
        free(current);
        current = next;
    }
    free(list);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:34:55