Home > other >  CS50 PSet4: Recover - Conditional Statement Problem
CS50 PSet4: Recover - Conditional Statement Problem

Time:12-30

I have written the code for PSet-4: Recover from CS50 and I have a question regarding the usage of if-else statements in my code inside the while loop. When I run the first code, check50 shows the following errors -

:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:( recovers 000.jpg correctly
    expected exit code 0, not None
:( recovers middle images correctly
    expected exit code 0, not None
:( recovers 049.jpg correctly
    expected exit code 0, not None
:| program is free of memory errors
    can't check until a frown turns upside down

I tried writing this code and it fails.

    char jpeg[8]; //to store each jpeg file
    int i = 0; // to count the number of jpeg files
    BYTE buffer[512]; // store each stream of 512 bytes to read
    FILE *imout; // output file
    bool jpegStart = false; // to check for already opened jpeg file

// read the file 512 bytes at a time until the end
    while (fread(buffer, 1, 512, card) == 512)
    {
        // if buffer detects signature first 4 bytes of JPEG file
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && ((buffer[3] & 0xff) == 0xe0))
        {
            //if already jpeg opened and new detected, close the already opened jpeg
            if (jpegStart)
            {
                fclose(imout);
            }
            //set true when signature detected and write to output file with current index i
            else if (jpegStart == false)
            {
                jpegStart = true;
                sprintf(jpeg, "i.jpg", i);
                imout = fopen(jpeg, "w");
                fwrite(buffer, 1, 512, imout);
                i  ;
            }
         }
     }

Whereas when I run the code without the else if clause, it runs successfully as per the following code:

    char jpeg[8]; //to store each jpeg file
    int i = 0; // to count the number of jpeg files
    BYTE buffer[512]; // store each stream of 512 bytes to read
    FILE *imout; // output file
    bool jpegStart = false; // to check for already opened jpeg file

// read the file 512 bytes at a time until the end
    while (fread(buffer, 1, 512, card) == 512)
    {
        // if buffer detects signature first 4 bytes of JPEG file
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && ((buffer[3] & 0xff) == 0xe0))
        {
            //if already jpeg opened and new detected, close the already opened jpeg
            if (jpegStart)
            {
                fclose(imout);
            }
            //set true when signature detected and write to output file with current index i
 
            jpegStart = true;
            sprintf(jpeg, "i.jpg", i);
            imout = fopen(jpeg, "w");
            fwrite(buffer, 1, 512, imout);
            i  ;
        }
     }

I think it might be a very silly doubt but I would still like to get some clarification on why the first code failed when the else-if conditional statement was included? Thanks.

CodePudding user response:

In the first example, jpegStart is never reset to false. As a consequence, the condition:

if (jpegStart) 

remains true and the else if is discarded.

The first example goes like:

if (jpeg is true) { 
    do this..
} else if (jpeg is false) {
    do this..  /* This line is only executed if jpeg is false */
}

The second example on the other hand translates to:

if (jpeg is true) {
    do this..
}

do this.. /* This line always executes */
}

Do you see the difference?

Here's an example that might help:

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

static void print_greatest(int x, int y) 
{ 
    if (X > y) {
        printf("%d\n", x);
    } 
    printf("%d\n", y);
}

int main(void) 
{
    print_greatest(10, 5);
    return EXIT_SUCCESS;
}

Output:

10
5

y always gets printed. But if we were to add an else, things change:

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

static void print_greatest(int x, int y) 
{ 
    if (x > y) {
        printf("%d", x);
    } else {
        printf("%d", y);
    }
}

int main(void) 
{
    print_greatest(10, 5);
    return EXIT_SUCCESS;
}

Output:

10

y is only printed if it was greater than x.

Side note:

You should always check the return value of fopen to ensure you're not — trying to — reading from or writing to a NULL pointer. Functions like fwrite and fclose should also be checked.

  • Related