C++使用seekg从二进制文件尾向中部反向读取时报错求助
C++ 文件反向读取功能错误分析与修复
核心错误点
- 单位不匹配导致位置判断完全失效
tellg()返回的是字节偏移量,但你计算的posMedian1、posMedian2是元素个数的一半,没有乘以sizeof(int),导致循环边界判断完全错误,很容易触发非法的指针移动操作。另外奇数长度时加2的逻辑没有任何依据,属于逻辑错误。 - 流状态完全未做校验
所有文件打开、指针移动、数据读取操作都没有判断是否成功,一旦出现指针移动到文件头之前、文件打开失败等异常情况,流会进入失效状态,后续所有操作都会报错,这是运行错误的直接原因。 - 循环逻辑嵌套混乱
你把「从尾向中读取」和「从头向中读取」两个独立逻辑写在了嵌套循环里,外层循环第一次执行时就会把两个文件的指针重置到文件头,后续外层循环的边界判断彻底失效,完全不符合需求。 - 短文件处理逻辑错误
两个文件长度不同时的flag标记逻辑完全混乱,无法正确对应两个文件的读取元素,会出现读取脏数据或者越界的问题。
修复思路
- 统一用字节作为位置计算单位,中位数位置计算逻辑修正为:
// 计算int元素的总个数 int elemCount1 = size1 / sizeof(int); int elemCount2 = size2 / sizeof(int); // 中部位置的字节偏移:从头部数第n/2个元素的起始位置 int posMedian1 = (elemCount1 / 2) * sizeof(int); int posMedian2 = (elemCount2 / 2) * sizeof(int);
- 拆分两个独立的处理流程,先完成全部从尾向中读取的逻辑,再处理从头向中读取的逻辑,不要嵌套。
- 每次
seekg、read、open操作后都判断流状态是否正常。 - 反向读取时,读完一个元素后移动指针要判断是否已经越过中位数位置,避免非法偏移。
参考修复代码
void calculatingSum(const char* fname, const char* fname2, const char* fname3) { int size1 = returnSize(fname); int size2 = returnSize(fname2); ifstream fin1, fin2; ofstream fout3(fname3, ios::binary); // 校验输出文件打开状态 if (!fout3.is_open()) { return; } // 统一让fin2对应文件更大的文件 if (size2 < size1) { swap(size1, size2); fin1.open(fname2, ios::binary); fin2.open(fname, ios::binary); } else { fin1.open(fname, ios::binary); fin2.open(fname2, ios::binary); } if (!fin1.is_open() || !fin2.is_open()) { fout3.close(); return; } int elemCount1 = size1 / sizeof(int); int elemCount2 = size2 / sizeof(int); int posMedian1 = (elemCount1 / 2) * sizeof(int); int posMedian2 = (elemCount2 / 2) * sizeof(int); int a, b; // -------------------------- // 第一部分:从尾部向中部读取 // -------------------------- fin1.seekg(-sizeof(int), ios::end); fin2.seekg(-sizeof(int), ios::end); while (fin2.tellg() >= posMedian2 && fin2.good()) { fin2.read((char*)&a, sizeof(int)); // 小文件未到中位数则正常读,超出则补0,可根据需求调整规则 b = 0; if (fin1.tellg() >= posMedian1 && fin1.good()) { fin1.read((char*)&b, sizeof(int)); } int c = a + b; if (c > 0) { fout3.write((char*)&c, sizeof(int)); } // 移动指针到上一个元素,避免越界 if (fin2.tellg() >= 2 * sizeof(int)) { fin2.seekg(-2 * sizeof(int), ios::cur); } else { break; } if (fin1.tellg() >= 2 * sizeof(int)) { fin1.seekg(-2 * sizeof(int), ios::cur); } } // -------------------------- // 第二部分:从头部向中部读取 // -------------------------- fin1.clear(); fin2.clear(); fin1.seekg(0); fin2.seekg(0); while (fin2.tellg() <= posMedian2 && fin2.good()) { fin2.read((char*)&a, sizeof(int)); b = 0; if (fin1.tellg() <= posMedian1 && fin1.good()) { fin1.read((char*)&b, sizeof(int)); } int c = a + b; if (c > 0) { fout3.write((char*)&c, sizeof(int)); } if (fin2.tellg() + sizeof(int) > posMedian2) { break; } } fin1.close(); fin2.close(); fout3.close(); }
内容的提问来源于stack exchange,提问作者Alexandra
相关产品推荐
相关产品推荐

