使用scanf后文本文件中int变量出现垃圾值问题求助
问题分析与修复方案
核心问题根源
id成员未赋值:Record函数完全没有给结构体的id变量赋值,这个int型变量会保留内存中的垃圾值,后续StoreInFile用它计算写入偏移量,直接导致写入位置完全混乱。- 文件操作逻辑错误:
- 重复打开文件且未关闭第一个指针,造成资源泄漏;
- "a"追加模式下,所有写操作会自动将指针移到文件末尾,
fseek的定位完全无效,再结合未初始化的id计算偏移,会把数据写入到错误位置(比如文件空洞),读取时就会出现垃圾值; - 未使用二进制模式写入结构体,文本模式的换行符转换会破坏二进制数据结构。
- 输入处理隐患:
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
相关产品推荐
相关产品推荐

