文件整数元素循环移位函数多次迭代异常排查与修复咨询
问题分析与修复方案
我要实现文件中整数元素的循环移位(效果等同于数组循环移位),单次迭代运行正常,但多次迭代后出现文件写入错误。要求偏移次数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; // }
关键修复说明
- 切换二进制模式:打开文件时使用
"wb+"(读写二进制模式),用fread/fwrite直接操作二进制数据,保证每个整数占用固定的sizeof(int)字节,fseek偏移计算完全准确。 - 修正移位逻辑:
shiftElements改为单次实现右移一位,由外层的executionForSecondBlock控制移位次数,避免重复操作。 - 清理冗余代码:移除未使用的
lastElementPosition参数,删除shiftElements内部的无效循环。 - 统一读写格式:二进制读写无需处理空格分隔,彻底解决整数解析混乱问题。
内容的提问来源于stack exchange,提问作者apromise
相关产品推荐
相关产品推荐

