CS50 Pset4 Recover作业遇阻:文件指针访问问题求助
JPEG恢复程序的文件指针作用域问题
当前代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> typedef uint8_t BYTE; int const BLOCK_SIZE = 512; int main(int argc, char *argv[]) { if (argc != 2) { printf("Incorrect usage\n"); return 1; } FILE *file = fopen(argv[1], "r"); if (file == NULL) { printf("Could not open the file\n"); return 1; } BYTE buffer[512]; int indx = 0; int irratation= 0 ; char* filename = malloc(10); while(fread(buffer, 1, BLOCK_SIZE, file) == BLOCK_SIZE) { FILE* ptr = NULL; if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { irratation++; if(irratation >= 2) { indx++; } if (indx == 0) { sprintf(filename, "%03i.jpg", indx); ptr = fopen(filename, "w"); fwrite(buffer, 1, BLOCK_SIZE, ptr); } else { fclose(ptr); sprintf(filename, "%03i.jpg", indx); ptr = fopen(filename, "w"); fwrite(buffer, 1, BLOCK_SIZE, ptr); } } else { fwrite(buffer, 1, BLOCK_SIZE, ptr); } } return 0; }
问题描述
我理解该作业的逻辑,并尝试按照walkthrough中的伪代码实现,但目前遇到文件指针作用域问题:当找到新的JPEG文件时,我打开了ptr并写入数据,但找到下一个新文件时无法关闭前一个已打开的文件;同时在未找到新文件的else分支中,无法写入到已打开的文件,因为ptr的作用域仅在if分支内。恳请提供解决建议。
解决建议
- 调整文件指针作用域:将
FILE* ptr = NULL;的声明移到while循环外面,让它的作用域覆盖整个循环过程,这样后续的分支都能访问到同一个指针变量,解决else分支无法写入、新JPEG无法关闭旧文件的问题。 - 简化计数逻辑:去掉冗余的
irratation变量,直接用indx计数。第一次找到JPEG时从0开始,之后每次发现新的JPEG头,先关闭当前打开的文件(如果有的话),再递增indx并打开新文件。 - 增加空指针检查:在调用
fwrite和fclose前,先判断ptr是否不为NULL,避免空指针操作导致程序崩溃。 - 清理资源:循环结束后要关闭最后一个打开的JPEG文件,还要释放
malloc分配的filename内存,避免内存泄漏。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> typedef uint8_t BYTE; int const BLOCK_SIZE = 512; int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: ./recover image\n"); return 1; } FILE *file = fopen(argv[1], "r"); if (file == NULL) { printf("Could not open file.\n"); return 1; } BYTE buffer[512]; int indx = 0; char* filename = malloc(10); FILE* ptr = NULL; // 移到循环外,扩大作用域 while (fread(buffer, 1, BLOCK_SIZE, file) == BLOCK_SIZE) { // 检查是否是JPEG起始标志 if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) { // 如果已经打开了一个JPEG文件,先关闭它 if (ptr != NULL) { fclose(ptr); } // 生成新文件名并打开文件 sprintf(filename, "%03i.jpg", indx); ptr = fopen(filename, "w"); if (ptr == NULL) // 检查文件是否成功打开 { printf("Could not create file.\n"); fclose(file); free(filename); return 1; } fwrite(buffer, 1, BLOCK_SIZE, ptr); indx++; } else { // 只有当已有打开的JPEG文件时,才写入数据 if (ptr != NULL) { fwrite(buffer, 1, BLOCK_SIZE, ptr); } } } // 关闭最后一个打开的JPEG文件 if (ptr != NULL) { fclose(ptr); } // 清理资源 fclose(file); free(filename); return 0; }
内容的提问来源于stack exchange,提问作者bopleromn 19
相关产品推荐
相关产品推荐

