I have had to look at this for a moment to get my head to understand the logic. You have written your
feof condition in a way that should work, but it would be much easier to follow if written
feof(in) as both of these clearly evaluate to true; you currently have written a statement that reads "not false" which is just awkward to read, especially when trying to find out why something isn't working.
The problem that I see is that there is no return statement for the
code methods, only for the
if statements that check for the EOF. The other statements need a return statement after they call the
code method so that they can return (or "walk" back up the recursion) to the original call and then the original method that called the
code method. This means that the whole
code method also needs a return statements. Right now, it looks as though this will hang, or sit forever, as the program will run out of things to execute without reaching the end of the program.
It's possible there might be something else, but everything else looks like reasonable logic to me and I don't see anything else that would cause you to say that "using EOF doesn't seem to work."
Edit: Ok, seeing that you are getting an check error of all routes call itself, I will go back to my original thought regarding your recursive function--it's base case is not properly defined. Upon rereading your code a few times, it seemed like maybe its structure wasn't the issue and you were saying it was just never finding the end of the file. But, now that we know that this isn't the case, let's look at how to declare the cases of the recursive function a little clearer for both the human reader and the computer.
What I see in your
code method, currently, is a lot of linear logic, where the code is meant to run through nested if-else statements, narrowing down the possible cases until it finds a correct one. Your recursive function is almost identical to how this would be done without recursion. So, with restructuring your code to look for cases first, and not running into nested statements to find them, your
code method should look something like this:
void code(FILE* in, FILE* out)
fread(buffer, 1, 512, in);
//base case; eof reached
else if(buffer == 0xff && buffer == 0xd8 && buffer == oxff && (buffer & 0xf0) == 0xe0)
if(count > 0) //new JPEG header found
//code to close old file and open a new one
//code to write the buffer to the file and increment counter
//this can stay out of the if because it always applies
//buffer contains contents of a JPEG
else if (counter > 1)
//code to write buffer to file
//close the out file as the writing is done and exit the method
Now, I'll admit that this code is written off the top of my head and I haven't had the time to test it, but you should see how it's structure is different from what you have written. Personally, I would not do this problem recursively (you can almost copy-paste your recursive method into your main function, with few modifications and removing the recursive calls, and it would work), but this will hopefully help you get closer to finding a recursive solution to this. Obviously, there are many ways to write recursive methods (and all methods), but, in my experience, recursive methods are usually written with a structure that is different from non-recursive methods. I will admit, though, that the projects I work on do not often lend themselves to recursive logic (they are event-based), and so I haven't dealt with this much outside of coursework.
Hopefully this helps and let me know in the comments if you still have questions about this.
Edit 2: Let me try to explain how
(buffer & 0xf0) == 0xe0) works.
First, the last zero that was originally in that code snippet (you asked about
(buffer & 0xf0) == 0xe00) should have been a closing parenthesis. The correct code snippet, as I have listed at the start of this edit and corrected in my code example, is
(buffer & 0xf0) ==0xe0).
Now, we can discuss how the code works. This code is, or at least was, provided in the video that is in the problem set--I recommend watching them, even if you already have a working solution, as they introduce you to cool concepts like these that might be helpful sometime. The
& operator in C is a bitwise operator, meaning that it operates on the provided values at their binary level, not their human-legible one. Specifically, this one compares the binary values of each bit, similar to how a Boolean operator would compare two values.
Then, instead of returning a simple
false if the whole value provided is equal, it provides a value back whose binary is equal to which bits where present in both values. Remember that a bit of
0 is empty/off and a bit of
1 is filled/on. This can get a bit confusing to try and read (it is working at the computer's level of understand after all), so let's work through two examples:
bool true = (0xef & 0xf0) == 0xe0;
bool false = (0xff & 0xf0) == 0xe0;
Ultimately, we are using this bitwise operator to perform a boolean comparison, so I have set the examples to fill to boolean variables (as they will get resolved down into a regular true/false quantity in order to fulfill the if statement's condition requirements). These examples as written don't really help with anything, right? I mean, they are still in a human-legible format. So, let's translate the parts being compared into binary:
bool true = (11101111 & 11110000) == 11100000;
bool false = (11111111 & 11110000) == 11100000;
Ok, now we are closer to what the computer will be reading and can really dissect this. The
& operator will return a
1 where both values have a
1 and a
0 otherwise. So, if you go bit-by-bit through the first example, the expression in the parentheses becomes
(11100000). This is equal to
0xe0), so the whole expression is true. For the second one, though, the expression in the parentheses becomes
(11110000). Because this is not equal to
11100000, the whole expression evaluates to false.
In the problem set, we are told that
0xef all have
1110 as their first four bytes. So, when plugged into the expression
(buffer & 0xf0) == 0xe0, they will all evaluate to true just as
0xef did above. For me, this seemed like the cleanest and most succinct way to deal with the great variety that the fourth byte of the header could have.
Let me know if any of that doesn't make sense.