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

CS50 Week4 Recover作业:000.jpg加载异常排查求助

CS50 Recover作业:000.jpg加载异常的问题修复

你的000.jpg加载异常的核心原因是在找到第一个JPEG文件的起始标记前,就已经向000.jpg写入了内存卡开头的非JPEG数据。

问题代码的核心逻辑缺陷

  • 进入循环前,你直接创建并打开了000.jpg文件
  • 第一次读取内存卡数据后,若不是JPEG起始块,会执行else分支的fwrite,把这段无效数据写入000.jpg
  • 直到找到第一个合法JPEG标记时,000.jpg的头部已经混入了垃圾数据,导致图片无法正常解析

此外还有两个次要问题:

  • if (argv[1] == NULL)的检查无意义:当argc==2时,argv[1]必然指向传入的参数,不会为NULL
  • 未处理内存卡文件打开失败的情况:若fopen返回NULL,后续代码会直接崩溃

修复后的代码

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

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    // 检查命令行参数数量
    if (argc != 2) {
        fprintf(stderr, "Usage: ./recover IMAGE\n");
        return 1;
    }

    // 打开内存卡文件并检查是否成功
    FILE *card = fopen(argv[1], "r");
    if (card == NULL) {
        fprintf(stderr, "Could not open %s.\n", argv[1]);
        return 1;
    }

    BYTE buffer[512];
    int count = 0;
    FILE *outfile = NULL;
    char *filename = malloc(8); // 足够存储"000.jpg" + 字符串终止符

    while (fread(buffer, sizeof(BYTE), 512, card) == 512) {
        // 检查JPEG起始标记
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) {
            // 如果已有打开的JPEG文件,先关闭
            if (outfile != NULL) {
                fclose(outfile);
            }

            // 生成新的JPEG文件名并打开
            sprintf(filename, "%03i.jpg", count);
            outfile = fopen(filename, "w");
            if (outfile == NULL) {
                fprintf(stderr, "Could not create %s.\n", filename);
                free(filename);
                fclose(card);
                return 1;
            }

            // 写入当前块
            fwrite(buffer, sizeof(BYTE), 512, outfile);
            count++;
        } else if (outfile != NULL) {
            // 仅当正在写入某个JPEG文件时,才继续写入当前块
            fwrite(buffer, sizeof(BYTE), 512, outfile);
        }
    }

    // 清理资源
    if (outfile != NULL) {
        fclose(outfile);
    }
    fclose(card);
    free(filename);

    return 0;
}

关键修正说明

  1. 延迟创建输出文件:初始时outfile设为NULL,直到找到第一个合法JPEG标记才创建000.jpg,避免写入无效头部数据
  2. 严格控制写入逻辑:仅当outfile不为NULL(即正在写入有效JPEG文件)时,才写入非起始块的数据
  3. 完善错误处理:添加了内存卡文件打开失败的判断,以及输出文件创建失败的回滚逻辑
  4. 移除无效代码:删除了无意义的argv[1] == NULL检查

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:33:06