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

在Eclipse Luna中使用链表写入文件时出现垃圾数据问题求助

问题排查与代码修正

嗨,我来帮你梳理下代码里的问题——你的printf输出正常但文件写入垃圾数据,核心是几个逻辑和用法错误,咱们一步步拆解:

1. fwrite 参数完全用错了

你写的这行:

ret= fwrite((struct DETAIL *)&(ptr->next),1,sizeof(struct DETAIL),fp));

首先有个语法错误——多了一个右括号 ),不过你说printf正常,可能是输入时的手误。但最致命的是:
&(ptr->next) 取的是指针变量ptr->next自己的地址,而不是你要写入的结构体的地址。ptr->next本身是一个指向struct DETAIL的指针,你把这个指针的地址传给fwrite,写入的其实是这个指针的内存地址值(也就是stTmp的地址),根本不是结构体里的data和next数据,这肯定是你看到的“垃圾数据”。

2. 所有链表节点都指向同一块内存

你只malloc了一次stTmp,循环里每次只是修改它的data,然后让ptr->next指向它。这意味着你所谓的“10条记录”其实全是同一个结构体实例,最后链表的所有节点都指向同一块内存,就算写入逻辑对了,也只会重复写入同一个内容。

3. 链表初始化逻辑混乱

你一开始malloc了ptr,但这个初始的ptr既没初始化data也没处理next,直接让ptr->next = stTmp,循环里ptr = ptr->next,最后ptr会一直指向stTmp,根本没构建出真正的10个节点的链表。


修正后的代码

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

struct DETAIL { 
    char data[12+1]; 
    struct DETAIL* next; 
}; 

int main() { 
    int ret = 0; 
    FILE *fp = fopen("linked","w+"); 
    if (fp == NULL) { // 务必检查文件是否打开成功
        perror("Failed to open file");
        return 1;
    }

    struct DETAIL *head = NULL; // 链表头节点,用于后续内存释放
    struct DETAIL *current = NULL;
    int i = 0; 

    for(i = 0; i<10; i++) { 
        // 每次循环都为新节点分配内存
        struct DETAIL *stTmp = (struct DETAIL*)malloc(sizeof(struct DETAIL)); 
        if (stTmp == NULL) {
            perror("Failed to allocate memory");
            // 这里可以加入已分配内存的清理逻辑,避免泄漏
            return 1;
        }
        sprintf(stTmp->data,"%012d",i+1); 
        stTmp->next = NULL; // 初始化next指针为NULL,避免野指针

        // 构建链表:第一次循环初始化头节点,后续追加新节点
        if (head == NULL) {
            head = stTmp;
            current = stTmp;
        } else {
            current->next = stTmp;
            current = stTmp;
        }

        // 正确写入结构体数据到文件:直接传结构体指针
        ret = fwrite(stTmp, sizeof(struct DETAIL), 1, fp); 
        if (ret != 1) {
            printf("Write failed for record %d\n", i+1);
        }
        printf("data[%d]:%s\n",i,stTmp->data); 
    } 

    // 释放链表所有节点的内存,避免内存泄漏
    struct DETAIL *tmp = head;
    while (tmp != NULL) {
        struct DETAIL *nextNode = tmp->next;
        free(tmp);
        tmp = nextNode;
    }

    fclose(fp); // 关闭文件,确保数据写入磁盘
    return 0;
}

关键知识点梳理

  • fwrite的正确用法:第一个参数是要写入的数据的起始地址,如果你要写入整个结构体,直接传结构体指针(比如stTmp)即可,而不是指针的地址。另外fwrite的参数顺序是(数据地址, 单个元素大小, 元素个数, 文件指针),我调整成sizeof(struct DETAIL), 1,这样更清晰表示“写入1个大小为结构体的元素”,和你原来的1, sizeof(...)功能一致,但可读性更好。
  • 链表节点的创建:每个节点必须单独分配内存,否则所有节点都会指向同一块内存,修改一个就会影响所有节点,根本存不下10条不同的记录。
  • 资源清理:文件打开后一定要关闭(否则可能导致数据未写入磁盘),malloc的内存一定要free,避免内存泄漏。
  • 错误检查:文件打开、内存分配都要检查返回值,这是C语言编程的良好习惯,能帮你快速定位很多隐藏问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:16:40