Block I/O浮点数读取异常:库存统计程序二进制文件读写不一致
解决二进制文件读取单价乱码的问题
兄弟,我之前也踩过一模一样的坑!你说写入时单价显示正常,读取就变成无意义乱码,基本跑不出下面这几个常见原因,咱们一个个来捋:
1. 读写两端的结构体定义不一致(头号嫌疑人!)
这是最容易犯的错误——你在写入程序里定义的零件结构体,和读取程序里的结构体必须完全一致,包括每个字段的类型、顺序,甚至内存对齐规则都得一模一样。
举个典型反例:
- 写入程序里单价用的是
float:
typedef struct { int part_id; int quantity; float unit_price; // 这里是4字节的float } InventoryItem;
- 读取程序里却错写成了
double:
typedef struct { int part_id; int quantity; double unit_price; // 这里是8字节的double } InventoryItem;
两种类型的字节数不一样,读取时会把后面的内存数据当成double的一部分,自然就是乱码。
解决办法:把结构体定义写成单独的头文件(比如inventory.h),让读写程序都包含这个头文件,彻底避免手动写错。
2. 文件打开模式错误
二进制文件读写必须用对应的模式:
- 写入时要开
wb(write+binary)模式,不能用普通的w(文本模式) - 读取时要开
rb(read+binary)模式,不能用普通的r(文本模式)
如果用文本模式操作二进制数据,系统会自动转换换行符(比如Windows下把\n转成\r\n),直接破坏二进制数据的字节结构,导致读取时数据错位。
正确的打开方式:
// 写入程序 FILE *fp = fopen("inventory.bin", "wb"); // 读取程序 FILE *fp = fopen("inventory.bin", "rb");
3. 数据读写方式不匹配
你说用scanf写入二进制文件——应该是先用scanf读取用户输入到结构体变量,再用fwrite把整个结构体写入文件吧?千万别搞混:不能用fprintf往二进制文件里写文本格式的数据,再用fread读二进制,这完全是两种存储格式,肯定乱码。
正确的写入流程:
InventoryItem item; // 注意格式串要匹配用户输入的逗号分隔格式 scanf("%d, %d, %f", &item.part_id, &item.quantity, &item.unit_price); // 写入二进制文件 fwrite(&item, sizeof(InventoryItem), 1, fp);
正确的读取流程:
InventoryItem item; // 从二进制文件读取整块数据 fread(&item, sizeof(InventoryItem), 1, fp); // 打印时用对应格式符:float用%f,double用%lf printf("零件编号:%d,数量:%d,单价:%.2f\n", item.part_id, item.quantity, item.unit_price);
4. 内存对齐的隐藏坑(少见但可能)
有些编译器会自动给结构体做内存对齐,比如如果编译器的对齐选项不同(比如GCC的-fpack-struct),或者结构体字段顺序调整,会导致结构体的总大小不一样,读取时直接错位。
解决办法:
- 读写程序用同一个编译器编译,或者手动指定结构体的对齐方式:
#pragma pack(push, 1) // 强制按1字节对齐 typedef struct { int part_id; int quantity; float unit_price; } InventoryItem; #pragma pack(pop) // 恢复默认对齐规则
快速排查小技巧
你可以在写入程序里打印结构体的内存大小:
printf("结构体大小:%zu\n", sizeof(InventoryItem));
然后在读取程序里也打印同样的数值,如果两个数值不一样,那肯定是结构体定义或对齐的问题,直接从这里入手就行!
内容的提问来源于stack exchange,提问作者Tcranmer
相关产品推荐
相关产品推荐

