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

CS50 Recover作业问题:首个JPEG无效,无法通过check50

Fixing the Corrupted First JPEG in CS50's Recover Assignment

Hey, let's break down why your first JPEG isn't valid while the rest work—your code's logic for handling the first JPEG header is causing it to get cut off prematurely.

The Core Issue in Your Code

When your code detects the first JPEG header, it runs two separate if blocks back-to-back:

  1. The first if (!jpgAlreadyNew) block creates 000.jpg, writes the 512-byte buffer, sets jpgAlreadyNew to true, and increments filenumber to 1.
  2. Immediately after, the second if (jpgAlreadyNew) block triggers (since you just set the flag to true), closes 000.jpg right away, creates 001.jpg, writes the same buffer again, and increments filenumber to 2.

This leaves 000.jpg with only 512 bytes of data—way too short to be a valid JPEG—while the actual first image's data gets dumped into 001.jpg instead. That's why check50 fails on the first file.

Corrected Full Code

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

int main(int argc, char *argv[]) {
    // Ensure proper usage
    if (argc != 2) {
        fprintf(stderr, "Usage: ./recover image\n");
        return 1;
    }

    // Open memory card file
    FILE *card_ptr = fopen(argv[1], "r");
    if (card_ptr == NULL) {
        fprintf(stderr, "Could not open %s.\n", argv[1]);
        return 2;
    }

    // Allocate 512-byte buffer (check for allocation success)
    unsigned char *buffer = malloc(512);
    if (buffer == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        fclose(card_ptr);
        return 3;
    }

    bool jpg_found = false;
    int file_count = 0;
    FILE *outfile = NULL;
    char filename[8];

    // Read 512-byte blocks until end of file
    while (fread(buffer, 1, 512, card_ptr) == 512) {
        // Check for JPEG header signature
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) {
            // If we already have an open JPEG, close it first
            if (jpg_found) {
                fclose(outfile);
            } else {
                // Mark that we've found our first JPEG
                jpg_found = true;
            }

            // Create new output file
            sprintf(filename, "%03i.jpg", file_count);
            outfile = fopen(filename, "w");
            if (outfile == NULL) {
                fprintf(stderr, "Could not create %s.\n", filename);
                free(buffer);
                fclose(card_ptr);
                return 4;
            }

            // Write the current block and increment file counter
            fwrite(buffer, 1, 512, outfile);
            file_count++;
        } else if (jpg_found) {
            // If we're in the middle of writing a JPEG, keep writing blocks
            fwrite(buffer, 1, 512, outfile);
        }
        // If no JPEG found yet, just skip the block
    }

    // Handle any remaining bytes at the end of the card (if we were writing a JPEG)
    if (jpg_found) {
        size_t remaining_bytes = fread(buffer, 1, 512, card_ptr);
        if (remaining_bytes > 0) {
            fwrite(buffer, 1, remaining_bytes, outfile);
        }
        fclose(outfile);
    }

    // Clean up resources
    free(buffer);
    fclose(card_ptr);
    return 0;
}

Key Fixes & Improvements

  • Mutually Exclusive Logic: Replaced the two separate if blocks with a single conditional flow—when a JPEG header is found, we either close an existing file (if we've already started writing) or mark that we've found the first JPEG, then create the new file. No more accidental double-processing of the first header.
  • Memory Allocation Check: Added a check to make sure malloc didn't fail, which prevents crashes from a null buffer.
  • End-of-File Handling: Added code to write any leftover bytes (less than 512) at the end of the memory card, ensuring the last JPEG is complete.
  • Clearer Variable Names: Renamed jpgAlreadyNew to jpg_found and filenumber to file_count for better readability.
  • Robust Loop Condition: Changed the loop to check if we read exactly 512 bytes, which is more precise than checking for non-zero (since the last read might return fewer bytes).

How to Verify

Run the corrected code, then check the first JPEG—you should be able to open it normally. When you run check50 cs50/problems/2024/x/recover, all test cases should pass.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:14:35