1

My program does return all 50 jpegs, check50 says that the last file is not recovered correctly. Unfortunately, I have no idea of why - I check for the end of the file before reading new data into the file. Can anyone help?

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

int main(void)
{
    //open memory card
    FILE* inptr = fopen("card.raw", "r");
    if (inptr == NULL)
    {
        printf("Could not open file.");
        return 1;
    }

    //establishing a counter for jpegs recovered
    int jpeg_count = 0;
    //establishes temporary storage
    uint8_t buffer[512];

    //create temporary file for output
    FILE* outfile = NULL;

    //array for changing file names
    char name[4];

    while (1)
    {
        //close files and end program if end of file is reached
        if (feof(inptr))
        {
            fclose(inptr);
            if (outfile != NULL)
            {
                fclose(outfile);
            }
            return 0;
        }

        //read a block of info into temporary storage
        fread(&buffer, 512, 1, inptr);

        //read three bytes; compare to 0xff 0xd8 0xff
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] == 0xe0 || buffer[3] == 0xe1 || buffer[3] == 0xe2 || buffer[3] == 0xe3 || buffer[3] == 0xe4 || buffer[3] == 0xe5 || buffer[3] == 0xe6 || buffer[3] == 0xe7 || buffer[3] == 0xe8 || buffer[3] == 0xe9 || buffer[3] == 0xea || buffer[3] == 0xeb || buffer[3] == 0xec || buffer[3] == 0xed || buffer[3] == 0xee || buffer[3] == 0xef))
        {
            //if matches, save 512 bytes as a jpeg and increase counter
            if (outfile != NULL)
            {
                fclose(outfile);
            }
            sprintf(name, "%03d.jpg", jpeg_count);
            outfile = fopen(name, "w");

            fwrite(&buffer, 512, 1, outfile);
            jpeg_count++;
        }
        else if (outfile != NULL)
        {
            fwrite(&buffer, 512, 1, outfile);
        }
    }

    fclose(inptr);

    return 0;
}
2

The problem is that you check for EOF before reading new data. You need to do the read and then check for EOF. Remember, after the last word is read, the file pointer is positioned to detect the EOF on the next read, but isn't there yet. Until the next actual read is executed, the EOF condition hasn't been detected.

The effect is that the code is executing one read past the last word and processing the result of that read. Because it hit the EOF, it didn't change the buffer, so the previous contents of the buffer get processed again. THEN, the EOF is detected on the next pass through the loop.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

| improve this answer | |
0

The fread() will stop reading when it encounters EOF. And fread() will return the number of elements it read, it will be an integer number. In your program, "fread(&buffer, 512, 1, inptr)" means that fread() will read one element of size 512 Bytes. So while processing the last iteration fread() will encounter the EOF before reading a single element of 512 Bytes, as a result the fread() will fails and return 0. The data now in the buffer will be corrupted or it will be the previously stored data, and that data is used by fwrite() to write the last part of your last .jpg file. That's why you got the error.

My suggestion is modify your fread() and fwrite() to

int no_read = fread(&buffer, 1, 512, inptr);
fwrite(&buffer, 1, no_read, outfile);

So in the last iteration fread() will read until it encounters EOF. And fread() returns the number of elements it read. That number is stored in no_read. And fwrite() writes only no_read Bytes to the file.

Please try this.

Thank you :)

| improve this answer | |

You must log in to answer this question.

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