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

C语言链表存储文件单词时遍历打印仅重复最后单词问题

问题根因

你误以为问题出在链表打印环节,实际上打印逻辑本身没有错误,核心问题是所有链表节点的data指针都指向了同一个栈上的buffer数组,你根本没有为每个读取到的单词单独分配存储内存。
你在add函数中写的new_node->data = data;仅仅是把传入的buffer首地址存到了节点里,所有节点的data都指向同一块内存地址。读取文件时你不断往buffer里写入新单词覆盖旧内容,调用add时打印正常是因为当下buffer里刚好存的是刚读到的单词,等全部文件读取完成后,buffer里留存的只有最后一个单词work?,此时遍历链表访问所有节点的data指针,指向的都是这块存了最后一个单词的内存,自然会重复输出最后一个词,附带异常符号是因为部分场景下字符串没有正确补\0结束符。

修复方案

按以下顺序修改代码即可解决问题:

    1. 修改add函数逻辑,为每个单词单独分配堆内存,拷贝字符串内容,不要直接存储buffer的地址
      将add函数中new_node->data = data;替换为如下代码:
    new_node->data = malloc(strlen(data) + 1); // 多分配1字节存字符串结束符\0
    strcpy(new_node->data, data);
    
    1. 修改free_list函数,释放节点时先释放节点内存储单词的内存,避免内存泄漏
      原逻辑只释放了节点结构体本身的内存,没有释放存字符串的堆内存,修改后代码:
    void free_list(ptr *hnode)
    {
        ptr p;
        while(*hnode){
            p = *hnode;
            *hnode = (*hnode)->next;
            free(p->data);
            free(p);
        }
    }
    
    1. 修复读取逻辑的隐藏bug
    • fgetc返回值是int类型,把原来的char ch;改成int ch;,否则在char为无符号类型的平台上EOF判断会失效
    • 去掉while(!feof(file))的判断写法,feof只有在读取操作已经越过文件末尾后才会返回真,会导致多读取异常字符,直接用fgetc的返回值判断EOF即可
    • 增加连续分隔符判断,避免连续空格、空行生成内容为空的无效节点
    • 循环结束后补充处理文件末尾的最后一个单词——如果文件最后一个单词后没有空格/换行,原逻辑会漏掉这个单词

修复后的文件读取核心代码参考:

int ch;
int i = 0;
while( (ch = fgetc(file)) != EOF && i < MAX-1 )
{
    if(ch == ' '|| ch == '\n' || ch == '\t')
    {
        if(i > 0) {
            buffer[i] = '\0';
            add(buffer);
            i = 0;
        }
    }
    else{
        buffer[i++] = ch;
    }
}
// 处理文件末尾最后一个未被分隔符截断的单词
if(i > 0) {
    buffer[i] = '\0';
    add(buffer);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 09:39:24