C语言二进制模式打开两文件逐行比对数据更新账户余额方法
问题根因
你遇到的二进制模式读取失败、比对异常是3个核心问题导致的:
- 文件格式和读取方式不匹配:你给出的测试样例是人类可读的文本格式存储(每行是空格分隔的账号、姓名、余额/交易信息),但你直接使用
fread按结构体固定大小读取二进制字节流,相当于把文本字符的ASCII码直接映射到int、float类型的内存空间,读出来的字段值完全是乱码,自然无法做账号比对。这种读取方式仅适用于文件本身是通过fwrite把结构体内存原样写入生成的纯二进制.dat文件。 - 文件指针未重置:内层交易文件的读取循环在处理第一个客户时就会把文件指针读到文件末尾,后续处理其他客户时,
fread直接返回EOF,根本读不到任何交易记录。 - 交易处理逻辑错误:你的代码匹配到第一笔对应账号的交易就直接break跳出循环,同一个客户的多笔交易只会处理第一笔;且非当前账号的交易没有做跳过逻辑,会无意义遍历同时错误触发break。
修复方案
根据你实际使用的文件格式选择对应实现:
场景1:使用文本格式存储文件(即你当前测试用的txt样例)
这种场景不建议直接用块读取逻辑,要么用文本模式("r"/"w")打开逐行解析字段,要么用二进制模式打开后自行处理换行符(Windows下二进制模式不会自动把\r\n转换为\n)、逐行拆分内容、把字符串转成对应数值类型赋值给结构体字段,解析逻辑和文本模式完全一致。
场景2:使用二进制格式存储文件(即直接存结构体内存的.dat文件)
这种场景可以直接用fread/fwrite做块读写,修复逻辑错误后的可运行代码如下:
#include<stdio.h> #include<stdlib.h> // 跨编译器读写二进制文件时建议开启1字节对齐,避免结构体填充字节导致字段错位 // #pragma pack(1) struct customer { int accno ; char name[30] ; float balance ; }; struct trans { int accnum ; char trans_type ; float amount ; } ; int main() { FILE *fs, *ft, *f1; struct customer c; struct trans tr; fs = fopen("CUSTOMER.DAT","rb"); if (fs == NULL) { printf("Can't open customer file."); exit(1); } f1 = fopen("TRANSACTIONS.DAT","rb"); if (f1 == NULL) { printf("Can't open transactions file."); fclose(fs); exit(2); } ft = fopen("temp.dat","wb"); if (ft == NULL) { printf("Can't open temp file."); fclose(fs); fclose(f1); exit(3); } // 逐一遍历所有客户记录 while(fread(&c, sizeof(struct customer), 1, fs) == 1) { // 处理当前客户前,重置交易文件指针到文件开头 rewind(f1); // 遍历全部交易,处理当前客户名下所有交易 while(fread(&tr, sizeof(struct trans), 1, f1) == 1) { if (tr.accnum != c.accno) { continue; // 非当前客户交易直接跳过 } if (tr.trans_type == 'D') { c.balance += tr.amount; } else if (tr.trans_type == 'W') { // 扣减后余额不低于100才执行扣款,否则跳过该笔失败交易 if (c.balance - tr.amount >= 100) { c.balance -= tr.amount; } } } // 所有交易处理完成后,将更新后的客户信息写入临时文件 fwrite(&c, sizeof(struct customer), 1, ft); } fclose(fs); fclose(f1); fclose(ft); remove("CUSTOMER.DAT"); rename("temp.dat", "CUSTOMER.DAT"); return 0; }
二进制文件读写注意事项
- 读写两端的结构体定义必须完全一致:字段顺序、字段类型、字段长度、字节对齐规则必须完全相同,否则会出现字段错位、数值异常。
- 二进制文件不具备跨平台可读性:不同操作系统、不同编译器下的基础类型长度、字节序可能存在差异,直接拷贝二进制文件到其他环境读取可能出现异常。
- 交易遍历必须覆盖全量记录:不要匹配到第一笔交易就终止循环,避免漏处理同一客户的多笔交易。
内容的提问来源于stack exchange,提问作者Nitin Bhartiya
相关产品推荐
相关产品推荐

