Let's start with the printed data that you're seeing. It's image data, meaning that it's the raw data used to define color values. If you print them out, it will look like nothing more than random numbers, so that's why it looks like it does. Kudos for figuring out how to print the data though!
Moving on to the while fread call, it's pretty straightforward when you break it down.
while (fread(&buffer, 512, 1, file) != EOF)
Let's dissect the fread first. The call to fread is going to read the requested amount of data (or less data) from the source file and put that data in the target memory. In this case, the source file is the file pointer
file. The target memory is
buffer. That just leaves the amount of data to be read. The 2nd and 3rd parameters combined determine this.
The 2nd parameter says "You will be reading data chunks that are this big." The third parameter says "Read this many data chunks." So, this call to fread says `read 1 data block of 512 bytes."
Now, remember that I said it will read this much OR LESS? Here's where that comes into play. When the fread call completes, it will return the number of blocks of data that were actually read. In this case, it will return either 1 or 0. If the read is successful, it will return 1. If it doesn't read 1 block of data, say from hitting EOF, it will return 0. But let's look at an example that explains it better.
while (fread(&buffer, 24, 10, file) != EOF)
This would read 24 * 10 = 240 bytes under normally. A fully successfully call would return 10, meaning 10 data blocks (of size 24) were read. Now, say that the file only had 96 bytes left to read. If fread were called at this point, it would read 4 blocks of 24 bytes, so it would return 4, not 10. After this read, the file would be at EOF, so it would return 0 on the next fread call.
That explains the fread call itself. The while loop is simpler. The while statement,
while (fread(&buffer, 512, 1, file) != EOF), will execute the fread and generate a return value. That return value will be compared to EOF.
THat's what happens. Unfortunately, this results in an infinite loop. Think about it. The loop will continue until the return value is equal to the value of EOF. That's the problem. When fread tries to read past the end of file, it returns 0. EOF evaluates as -1. Since 0 will never equal -1, the loop will never terminate!
The correct action is to compare the return value to the expected return value. So, it should have been this:
while (fread(&buffer, 512, 1, file) == 1)
The fread will return 1 until it hits the end of the file, or if something breaks. (One thing that's not covered in the class is that an error flag can also be set. Google the IBM referene page for fread to get more details and then you can google any terms that you don't understand.)
Once the data is in the buffer (it just copied 512 bytes into
buffer), the data can be manipulated as you see fit. In this pset, it's just a matter of checking the values in the first 4 bytes to see if they match the signature and to decide whether to open a new file. Beyond that, all of the data will be written out, using fwrite, at some point and a new block read in, overwriting the existing block. In a more complex program, the data could be modified and the new version written out, or whatever you want to do with it!
One last thing. There's a very common mistake that new programmers make. They will follow the while fread combination statement with a second fread statement. This has the effect of discarding the data from every 2nd read without processing it. They think that the fread inside the while statement only gets a return value to test, without actually executing a read. As you can tell from this discussion, a read is most definitely executed!
So, that's a complete breakdown of the while fread statement. Any questions?
If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)