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

CS50 recover.c运行生成空白JPEG图像,请求技术帮助

问题分析与修复方案

你的代码存在两个关键问题,导致生成的JPEG全为空白:

1. 仅写入了JPEG的首个数据块

JPEG文件由连续的多个512字节块组成,但你的代码仅在检测到JPEG签名时,写入当前块就立刻关闭文件。后续属于该JPEG的块没有被持续写入,最终每个生成的文件只有512字节,无法被图像查看器识别为完整的JPEG文件。

正确逻辑应为:

  • 首次检测到JPEG签名时,打开新文件并写入当前块
  • 后续块(直到下一个JPEG签名出现前)持续写入当前打开的文件
  • 检测到新JPEG签名时,先关闭当前文件,再打开新文件写入

2. 未使用二进制模式操作文件

在Windows系统中,默认的文本模式("r"/"w")会自动处理换行符,破坏JPEG的二进制数据。必须使用二进制模式("rb"/"wb")打开文件,确保数据读写时不被篡改。


修改后的完整代码

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

int main(int argc, char *argv[])
{
    // 检查命令行参数
    if (argc != 2)
    {
        printf("ERROR: Invalid command line argument, enter only 1 file.\n");
        return 1;
    }

    // 以二进制模式打开存储卡文件
    FILE *card = fopen(argv[1], "rb");
    if (card == NULL)
    {
        printf("Error: opening file.\n");
        return 2;
    }

    // 初始化变量
    uint8_t buffer[512];
    int counter = 0;
    FILE *recovered_jpeg = NULL;
    char filename[9];

    // 循环读取存储卡数据
    while (fread(buffer, 1, 512, card) == 512)
    {
        // 检测JPEG签名
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // 若已有打开的JPEG文件,先关闭
            if (recovered_jpeg != NULL)
            {
                fclose(recovered_jpeg);
            }

            // 检查文件数量是否超限
            if (counter > 999)
            {
                printf("Error: file overload.\n");
                return 3;
            }

            // 生成文件名
            sprintf(filename, "%03d.jpeg", counter);
            counter++;

            // 以二进制模式打开新JPEG文件
            recovered_jpeg = fopen(filename, "wb");
            if (recovered_jpeg == NULL)
            {
                printf("Error: opening file.\n");
                return 4;
            }
        }

        // 若当前有打开的JPEG文件,写入当前块
        if (recovered_jpeg != NULL)
        {
            fwrite(buffer, 512, 1, recovered_jpeg);
        }
    }

    // 循环结束后关闭最后一个JPEG文件
    if (recovered_jpeg != NULL)
    {
        fclose(recovered_jpeg);
    }

    fclose(card);
    return 0;
}

修改说明

  • 将fopen模式改为"rb"/"wb",确保二进制数据正确读写
  • 调整写入逻辑:仅在检测到新JPEG时切换文件,后续块持续写入当前文件
  • 循环结束后关闭最后一个JPEG文件,避免资源泄漏
  • 将原有的while(argc !=2)改为if,因为这是一次性参数检查,无需循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:57:30