自定义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
相关产品推荐
相关产品推荐

