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

C++使用seekg从二进制文件尾向中部反向读取时报错求助

C++ 文件反向读取功能错误分析与修复

核心错误点

  • 单位不匹配导致位置判断完全失效
    tellg()返回的是字节偏移量,但你计算的posMedian1、posMedian2是元素个数的一半,没有乘以sizeof(int),导致循环边界判断完全错误,很容易触发非法的指针移动操作。另外奇数长度时加2的逻辑没有任何依据,属于逻辑错误。
  • 流状态完全未做校验
    所有文件打开、指针移动、数据读取操作都没有判断是否成功,一旦出现指针移动到文件头之前、文件打开失败等异常情况,流会进入失效状态,后续所有操作都会报错,这是运行错误的直接原因。
  • 循环逻辑嵌套混乱
    你把「从尾向中读取」和「从头向中读取」两个独立逻辑写在了嵌套循环里,外层循环第一次执行时就会把两个文件的指针重置到文件头,后续外层循环的边界判断彻底失效,完全不符合需求。
  • 短文件处理逻辑错误
    两个文件长度不同时的flag标记逻辑完全混乱,无法正确对应两个文件的读取元素,会出现读取脏数据或者越界的问题。

修复思路

  1. 统一用字节作为位置计算单位,中位数位置计算逻辑修正为:
// 计算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);
  1. 拆分两个独立的处理流程,先完成全部从尾向中读取的逻辑,再处理从头向中读取的逻辑,不要嵌套。
  2. 每次seekg、read、open操作后都判断流状态是否正常。
  3. 反向读取时,读完一个元素后移动指针要判断是否已经越过中位数位置,避免非法偏移。

参考修复代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:24:03