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

使用scanf后文本文件中int变量出现垃圾值问题求助

问题分析与修复方案

核心问题根源

  1. id成员未赋值:Record函数完全没有给结构体的id变量赋值,这个int型变量会保留内存中的垃圾值,后续StoreInFile用它计算写入偏移量,直接导致写入位置完全混乱。
  2. 文件操作逻辑错误:
    • 重复打开文件且未关闭第一个指针,造成资源泄漏;
    • "a"追加模式下,所有写操作会自动将指针移到文件末尾,fseek的定位完全无效,再结合未初始化的id计算偏移,会把数据写入到错误位置(比如文件空洞),读取时就会出现垃圾值;
    • 未使用二进制模式写入结构体,文本模式的换行符转换会破坏二进制数据结构。
  3. 输入处理隐患:fgets会读取换行符到字符串中,scanf读取int后残留的换行符会影响后续输入。

修复步骤

1. 修正输入函数,给id赋值并处理输入缓冲区

// 注意:register是C语言关键字,不能用作变量名,改为contact
void Record(SContact *contact)
{
    printf("输入ID: ");
    scanf("%d", &contact->id);
    // 清除scanf后残留的换行符
    getchar();
    
    printf("输入日期: ");
    fgets(contact->date, MAXSTR, stdin);
    // 去掉fgets读取的换行符
    contact->date[strcspn(contact->date, "\n")] = '\0';
    
    printf("输入地点: ");
    fgets(contact->locale, MAXSTR, stdin);
    contact->locale[strcspn(contact->locale, "\n")] = '\0';
    
    printf("输入配送次数: ");
    scanf("%d", &contact->numberOfDeliveries);
    printf("输入体积: ");
    scanf("%d", &contact->volume);
    printf("输入重量: ");
    scanf("%d", &contact->weight);
}

2. 修复文件存储函数

根据需求选择两种模式:

模式一:追加记录到文件末尾
#define FILE_NAME "contacts.dat"

void StoreInFile(SContact *contact)
{
    // 用二进制模式打开,避免文本模式破坏二进制数据
    FILE *f = fopen(FILE_NAME, "ab");
    if(f != NULL)
    {
        fwrite(contact, sizeof(SContact), 1, f);
        fclose(f);
    }
    else
    {
        printf("\n错误:无法打开文件。");
    }
}
模式二:按ID索引固定位置写入

如果需要用ID作为索引,将对应ID的记录写入固定位置:

void StoreInFile(SContact *contact)
{
    FILE *f = fopen(FILE_NAME, "rb+");
    // 如果文件不存在,创建新文件
    if(f == NULL)
    {
        f = fopen(FILE_NAME, "wb+");
    }
    
    if(f != NULL)
    {
        if(contact->id >= 0)
        {
            // 定位到ID对应的结构体位置
            fseek(f, (long)contact->id * sizeof(SContact), SEEK_SET);
            fwrite(contact, sizeof(SContact), 1, f);
        }
        else
        {
            printf("\n错误:ID不能为负数。");
        }
        fclose(f);
    }
    else
    {
        printf("\n错误:无法打开或创建文件。");
    }
}

额外注意事项

  • 读取文件时必须对应使用二进制模式(如rb、rb+),保证结构体数据完整读取;
  • 确保MAXSTR定义的大小足够,避免fgets读取时数组溢出;
  • 永远不要用C语言关键字(如register)作为变量名,会引发编译错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:28:51