0

Below are my code for pset4 - Recover, it passed the check50, but I am trying to understand the logic on a particular process of fwrite or file-pointer.

In short, my question is how does line 74 know which file to write on?

My confusion start from the 2nd JPEG file 001.jpg has been created on line 62, from my understanding, the JPEG counter JC should be accumulated to 2 by line line 66 afterwards, and when the 2nd block of data of 001.jpg is copied from card.raw to buffer, since it is not a start for a JPEG, it will jump to the process of line 68, and then the img of line 74 should be getting information from line 40 >> line 39 >> line 36, which is 2...so it should write to a file it haven't created yet 002.jpg...How does it know to write on 001.jpg instead?

Thanks in advance!

as copy and paste doesn't copy line number, so I added a screen-cape here. Screen shot for my code with line number

But here is my code anyway:

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

typedef uint8_t BYTE;

// Number of bytes in buffer
const int BUFFER_SIZE = 512;


int main(int argc, char *argv[])
{
    // TODO:


    // Check command-line arguments
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    // Open memory card
    FILE *raw = fopen(argv[1], "r");
    if (raw == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    // Setup Buffer
    BYTE buffer[BUFFER_SIZE];
    // Setup JPEG counter
    int jc = 0;
    // Setup and open jpg file
    char filename[16];
    sprintf(filename, "%03i.jpg", jc);
    FILE *img = fopen(filename,"w");


    // Repeat until end of card:
        // Read 512 bytes into a buffer
    while (fread(buffer, BUFFER_SIZE, 1, raw))
    {
        // Check the buffer If start of new JPEG
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // If first JPEG
            if (jc == 0)
            {
                // Start writing JPEG file
                fwrite(buffer, BUFFER_SIZE, 1, img);
            }
            else
            {
                // Close the current writing file
                fclose(img);
                // Setup and open new jpg file
                sprintf(filename, "%03i.jpg", jc);
                FILE *img2 = fopen(filename, "w");
                // Write to new jpg file
                fwrite(buffer, BUFFER_SIZE, 1, img2);
            }
            jc++;
        }
        else
        {
            // If already found JPEG
            if ( jc >= 1)
            {
                // Keep writing
                fwrite(buffer, BUFFER_SIZE, 1, img);
            }
        }
    }
    // Close any remaining files
    fclose(raw);
}

1 Answer 1

1

First, when your program reaches line 74, you already have a file open that has it's location stored in a pointer you named img. When your program goes to write to this, it does not try to reopen it or recalculate where that pointer should be going to using the path that you have laid out. Instead, it reads the location that is stored within img even though that might not be the same if the program were to recreate the pointer given the same process as before--it doesn't matter because it already has the location.

Until your program hits a line of code that explicitly tells it img =, it will not change the value that img references. Because of this, you can write this program as I did with only one variable to hold all of the pointers for each new JPG file, changing the variable's contents only when necessary. This means that fwrite will never do any calculations for img and just trusts that it will contain all necessary information to allow the function to work correctly. If fwrite finds the information in img insufficient, then it will throw an error, which will either be caught during compilation or at runtime.

Hopefully this makes sense. If it does, feel free to accept the answer by clicking the check mark. If not, let me know and I can try to help some more.

3
  • Thanks, so both img and img2 are only just pointers, both storing the same location of (or rather pointing to) the file that is currently opening (where the real value is). In this case the value is the file that is currently opening, either opened in line 40 from the very beginning, or when every time a new JPEG file is created in line 64 from 001.jpg onwards. The so call UPDATE of the current opening file I am looking for, has already happened every time a new file is being created in line 64. Am I understanding it correctly? Commented Jan 16, 2021 at 9:28
  • It sounds like you've got it, yes. Your fopen in line 62 stores a new pointer into your img2 variable, which makes your line 64 write to the file at this new location and not the previous. This would be clearer (and still function) if you changed all of your img2 variables to img and didn't redeclare img (so line 62 would be img = fopen(filename, "w")). This would still work, but you would only need to worry about closing one file and not both--especially since it doesn't look like there is any instance of an fclose(img2) to close the file at that pointer. Commented Jan 16, 2021 at 13:34
  • Cool~! Thanks alot! :D Commented Jan 16, 2021 at 14:29

You must log in to answer this question.

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