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

CS50x Pset4 recover程序仅恢复图片部分内容的问题求助

CS50x Pset4 Recover 代码修复指南

你的代码只能恢复图片的部分内容,核心问题出在几个关键细节上,下面逐个拆解并给出修复方案:

核心错误点

  • 文件头检测逻辑错误:你写的buffer[0] = 255是赋值操作,不是比较!这会把buffer的第一个字节强行改成255,不仅导致后续的JPG头检测失效,还会破坏要写入的原始数据。正确写法是buffer[0] == 255。
  • 文件名缺少终止符:img_recovered是长度为8的char数组,但你只赋值了前7个字符(0-6位),没有加字符串终止符'\0'。fopen读取文件名时会越界读取内存垃圾数据,导致文件名错误,无法正确写入文件。
  • 频繁开关文件:每读一个512字节块就打开、写入、关闭文件,不仅效率极低,还可能因为文件系统缓存问题导致数据丢失。正确做法是保持当前文件打开,直到遇到新的JPG头再关闭。
  • 文件打开模式错误:处理二进制文件必须用二进制模式打开,即读用"rb",写用"wb",追加用"ab"。虽然CS50的Linux环境下文本模式和二进制模式差异不大,但跨平台会出问题,且符合规范。
  • 冗余变量设计:用j来判断是否开始写入图片不够直观,直接用一个FILE*指针跟踪当前打开的文件更清晰。

修复后的代码

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

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./recover forensic_image_file\n");
        return 1;
    }
    // 二进制模式打开取证图片
    FILE *for_image = fopen(argv[1], "rb");
    if (for_image == NULL)
    {
        printf("Could not open %s.\n", argv[1]);
        return 1;
    }

    char img_recovered[8];
    int img_count = -1;
    BYTE buffer[512];
    // 跟踪当前打开的图片文件
    FILE *current_img = NULL;

    while (fread(buffer, 1, 512, for_image) == 512)
    {
        // 正确检测JPG文件头:0xff 0xd8 0xff 0xe0-0xef
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // 如果已有打开的文件,先关闭
            if (current_img != NULL)
            {
                fclose(current_img);
            }
            img_count++;
            // 生成标准格式的文件名
            sprintf(img_recovered, "%03d.jpg", img_count);
            // 二进制模式创建新文件
            current_img = fopen(img_recovered, "wb");
            if (current_img == NULL)
            {
                printf("Could not create %s.\n", img_recovered);
                fclose(for_image);
                return 1;
            }
            // 写入当前块
            fwrite(buffer, 1, 512, current_img);
        }
        else if (current_img != NULL)
        {
            // 如果当前有打开的文件,继续写入
            fwrite(buffer, 1, 512, current_img);
        }
    }

    // 循环结束后关闭最后一个打开的文件
    if (current_img != NULL)
    {
        fclose(current_img);
    }
    fclose(for_image);
    return 0;
}

关键修改说明

  1. 把文件头检测的赋值=改成比较==,并调整第四个字节的检测为位运算(buffer[3] & 0xf0) == 0xe0,更准确匹配JPG的起始标记范围。
  2. 用sprintf生成三位数字的文件名,既简洁又避免手动赋值时的终止符遗漏问题。
  3. 使用current_img指针跟踪当前打开的文件,避免频繁开关,直到遇到新JPG头才关闭旧文件。
  4. 所有文件操作都用二进制模式(rb/wb),保证二进制数据不被篡改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:43:14