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

文件整数元素循环移位函数多次迭代异常排查与修复咨询

问题分析与修复方案

我要实现文件中整数元素的循环移位(效果等同于数组循环移位),单次迭代运行正常,但多次迭代后出现文件写入错误。要求偏移次数n不超过文件元素数量,元素数量无限制,不能使用额外文件和数组,必须通过fseek()直接访问文件元素。以下是我的代码:

void shiftElements(FILE* file, int numsCount, int lastElementPosition, int n) {
    int temp;
    int buffer;

    for (int i = 0; i <= n; i++) {
        fseek(file, (numsCount-i-1) * sizeof(int), 0);
        fscanf_s(file, "%d", &temp);
        printf("\n%d\n", temp);

        for (int j = numsCount - 1; j > 0; j--) {
            fseek(file, (j - 1) * sizeof(int), 0);
            fscanf_s(file, "%d", &buffer);
            printf("\n----%d\n", buffer);

            if (buffer < 10) {
                fseek(file, j * sizeof(int), 0);
                fprintf(file, "%d ", buffer);
            }
            else {
                fseek(file, j * sizeof(int), 0);
                fprintf(file, "%d", buffer);
            }
        }

        fseek(file, 0, 0);
        fprintf(file, "%d ", temp);
    }
}
    

void executionForSecondBlock(FILE* file_block_2, int numsCount, int n) {
    int lastElementPosition;
    int c;

    for (int i = 0; i < numsCount; i++) {
        c = rand() % 100;
        fseek(file_block_2, i * sizeof(int), 0);
        fprintf(file_block_2, "%d", c);
        if (i == numsCount - 2) {
            lastElementPosition = ftell(file_block_2);
        }
    }

    int pointerPosition = ftell(file_block_2);
    printf("\tЗапис закiнчився на %d позицiї покажчика\n", pointerPosition);

    printf("\n\tВиведення з файлу пiсля запису: \n");
    fseek(file_block_2, 0, 0);

    for (int i = 0; i < numsCount; i++) {
        fseek(file_block_2, i * sizeof(int), 0);
        fscanf_s(file_block_2, "%d", &c);
        printf("\t%d", c);
    }

    fseek(file_block_2, 0, 0);

    for (int i = 0; i < n; i++) {
        shiftElements(file_block_2, numsCount, n);
    }

    printf("\n\n\tВиведення з файлу пiсля змiщення: \n");
    fseek(file_block_2, 0, 0);

    for (int i = 0; i < numsCount; i++) {
        fseek(file_block_2, i * sizeof(int), 0);
        fscanf_s(file_block_2, "%d", &c);
        printf("\t%d", c);
    }
}

核心问题分析

  • 文本模式与固定字节偏移不匹配:用fprintf/fscanf_s以文本模式读写整数时,整数的字节长度是可变的(比如5占1字节,100占3字节),但代码中用(j-1)*sizeof(int)按二进制固定字节数计算偏移,完全不符合文本模式的实际字节位置,多次迭代后读写位置彻底混乱。
  • 移位逻辑重复冗余:shiftElements内部的外层循环for (int i = 0; i <= n; i++)完全多余,因为executionForSecondBlock已经循环调用了n次shiftElements,相当于执行了n*(n+1)次移位,逻辑错误。
  • 无效参数与格式不一致:lastElementPosition参数未被使用;写入时有的整数加空格、有的不加,导致文件中整数分隔混乱,后续读取无法正确解析。
  • 读写切换未同步状态:文本模式下读写操作切换时,未调用fflush或fseek同步文件缓存,加剧数据混乱。

修复方案

必须切换为二进制模式操作(保证每个整数字节长度固定),同时修正逻辑错误:

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>

// 单次循环右移一位(如需左移可调整逻辑)
void shiftElements(FILE* file, int numsCount) {
    int temp;
    int buffer;

    // 读取最后一个元素
    fseek(file, (numsCount - 1) * sizeof(int), SEEK_SET);
    fread(&temp, sizeof(int), 1, file);

    // 从后往前,将前一个元素移动到后一个位置
    for (int j = numsCount - 1; j > 0; j--) {
        fseek(file, (j - 1) * sizeof(int), SEEK_SET);
        fread(&buffer, sizeof(int), 1, file);
        
        fseek(file, j * sizeof(int), SEEK_SET);
        fwrite(&buffer, sizeof(int), 1, file);
    }

    // 将最后一个元素放到第一个位置
    fseek(file, 0, SEEK_SET);
    fwrite(&temp, sizeof(int), 1, file);
}

void executionForSecondBlock(FILE* file_block_2, int numsCount, int n) {
    int c;

    // 二进制模式写入随机整数
    for (int i = 0; i < numsCount; i++) {
        c = rand() % 100;
        fseek(file_block_2, i * sizeof(int), SEEK_SET);
        fwrite(&c, sizeof(int), 1, file_block_2);
    }

    long pointerPosition = ftell(file_block_2);
    printf("\t写入结束于指针位置 %ld\n", pointerPosition);

    printf("\n\t写入后的文件内容: \n");
    fseek(file_block_2, 0, SEEK_SET);
    for (int i = 0; i < numsCount; i++) {
        fseek(file_block_2, i * sizeof(int), SEEK_SET);
        fread(&c, sizeof(int), 1, file_block_2);
        printf("\t%d", c);
    }
    printf("\n");

    // 执行n次循环移位
    for (int i = 0; i < n; i++) {
        shiftElements(file_block_2, numsCount);
    }

    printf("\n\t移位后的文件内容: \n");
    fseek(file_block_2, 0, SEEK_SET);
    for (int i = 0; i < numsCount; i++) {
        fseek(file_block_2, i * sizeof(int), SEEK_SET);
        fread(&c, sizeof(int), 1, file_block_2);
        printf("\t%d", c);
    }
    printf("\n");
}

// 调用示例(需以二进制模式打开文件)
// int main() {
//     FILE* fp = fopen("test.bin", "wb+");
//     if (fp == NULL) {
//         perror("打开文件失败");
//         return 1;
//     }
//     executionForSecondBlock(fp, 5, 2); // 5个元素,右移2次
//     fclose(fp);
//     return 0;
// }

关键修复说明

  1. 切换二进制模式:打开文件时使用"wb+"(读写二进制模式),用fread/fwrite直接操作二进制数据,保证每个整数占用固定的sizeof(int)字节,fseek偏移计算完全准确。
  2. 修正移位逻辑:shiftElements改为单次实现右移一位,由外层的executionForSecondBlock控制移位次数,避免重复操作。
  3. 清理冗余代码:移除未使用的lastElementPosition参数,删除shiftElements内部的无效循环。
  4. 统一读写格式:二进制读写无需处理空格分隔,彻底解决整数解析混乱问题。

内容的提问来源于stack exchange,提问作者apromise

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:05:54