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.