1

thanks in advance for your patience.

While working on the recover portion of pset4, I'm running into a problem. My code below compiles, but when I run it with card.raw as its input, I only get 26 JPEGs as output (they are all different sizes), and none of them is a visible picture: instead they are blocky, weird colors. I'm really not sure what I did wrong here, any help would be much appreciated :)

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

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    if (argc != 2) // ensure proper usage
    {
        fprintf(stderr, "Usage: ./recover name\n");
        return 1;
    }
    char *infile = argv[1]; // store user input (file name)

    // open the card
    FILE *input = fopen(infile, "r");
    if (input == NULL)
    {
        fprintf(stderr, "Could not open file\n");
        return 2;
    }
    bool first = true;
    BYTE block[512];
    int number = 0;

    FILE *image = NULL; // declare ouput file "image"
    char filename[8]; // declare string "filename"

    // repeat until end of card
    do
    {
        fread(block, 512, 1, input);    //*****************
        if (block[0] == 0xff &&         //*****************
            block[1] == 0xd8 &&         // if start of JPEG
            block[2] == 0xff &&         //*****************
            (block[3] & 0xf0) == 0xe0)  //*****************
        {
            if (first == true) // if this is the start of the first JPEG
            {
                // write JPEG to new file
                sprintf(filename, "%03i.jpg", number); // generate file name
                image = fopen(filename, "w"); // open file to write to
                fwrite(block, sizeof(block), 1, image); // write from buffer 
to image file
                number++; // track # of JPEGs
                first = false;

            }
            else // if this is not the first JPEG (but is start of new)
            {
                fclose(image); // close previous file
                sprintf(filename, "%03i.jpg", number); // generate file name
                image = fopen(filename, "w"); // open file to write to
                fwrite(block, sizeof(block), 1, image); // write to image
                number++; // track # of JPEGs
            }
        }
        else // not the start of a new JPEG
        {
            if (first == true) // have any JPEGs been found?
            {
                // not part of a pointer, discard
            }
            else
            {
                fwrite(block, sizeof(block), 1, image); // continue writing
            }
        }
    }
    while ((fread(block, 512, 1, input)) != 0);
    fclose(input); // close the card file
    fclose(image); // close the final JPEG file
}

EDIT: 23 JPEGs (000 through 022) are output, not 26

2

Usually when the program returns 1/2 as many images as expected, it indicates a "double fread", which is indeed true here. Program reads a block first thing in the do loop, and again when the while executes. That will give you 1/2 the images, with 1/2 the bytes!

2
  • This worked :) I changed my do-while loop to a while loop while (fread(block, 512, 1, input) != 0) and removed the superfluous fread and it outputs the correct number of photos. Thanks for the help Jul 24 '17 at 17:39
  • Wow, this simple trick saved the day! However, being a totally newbie in C, I was following the CS50 walkthrough recommendations strictly... I think I got the double fread rom there.
    – B Furtado
    Aug 5 '17 at 20:03
-1

block is just an address, so sizeof(block) != 512 as you assume. sizeof() returns number of bites that is allocated for this variable type.

2
  • block is not a pointer, it is is a 512 BYTE array so sizeof(block) returns 512. Jul 24 '17 at 11:28
  • I don't think that's the problem because if I replace sizeof(block) with 512 I get the same results. Jul 24 '17 at 17:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .