CS50 Recover (Pset4)- Images not Recovered

|▌冷眼眸甩不掉的悲伤 提交于 2021-02-05 08:12:48

问题


So I'm trying CS50 Recover exercise (where you need to search for jpg files in a memory card and whenever you find one- you open a new file and write the jpg found to the new file). My code compiles but when I'm running the check50 command I'm receiving the following errors:

:( recovers 000.jpg correctly
    recovered image does not match
:( recovers middle images correctly
    recovered image does not match
:( recovers 049.jpg correctly
    recovered image does not match

Can somebody help me figure out what am I doing wrong? This is my code:

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

int main(int argc, char *argv[])
{
// Checking if the user entered a correct input:
    if (argc!=2)
    {
        printf("You're not using it correctly!\n");
        return 1;
    }
    
// Opening the file in argv[1]
    FILE *f=fopen(argv[1], "r");

// Validating that there's a file in argv[1]
    if(f==NULL)
    {
        printf("File hasn't found\n");
        return 1;
    }
    
    unsigned char bytes[512];
    int counter=0;
    FILE *img= NULL;
    
    while (fread(bytes, 512, 1, f)==1)
    {   
        if (bytes[0]==0xff && bytes[1]==0xd8 && bytes[2]==0xff && (bytes[3]&0xf0)==0xe0)
        {
            // If it's the first jpg found:
            if (counter==0)
            {
                img=fopen("000.jpg", "w");
            }
            else
            {
                fclose(img);
                char filename[8];
                sprintf(filename,"%03i.jpg", counter);
                img= fopen(filename, "w");
                if (img==NULL)
                {
                    printf("Couldn't open file\n");
                    return 1;
                }
            }
            counter++;
            fwrite(bytes, 512, 1, img);
        }   
    }
    fclose(img);
    fclose(f);
}

回答1:


Your primary problem is that you are not handling multiblock files correctly.

You only do the fwrite if the current block has the header. Otherwise, you are throwing away the data.

That's because the fwrite is inside the if block that detects the header.

If you have encountered the first (i.e. any) header, you will have an open output stream. Therefore, after that, you have to do the fwrite on each loop iteration.


Since you set img to NULL before entering the outer loop, there is no need to special case the 000.jpg

And, if the input file did not have a header [ever], the final fclose would segfault because the img pointer would be NULL.


I've annotated the bugs [with fixes]. I've wrapped the old/new code if #if 0 blocks:

#if 0
// old/original code
#else
// new/refactored code
#endif

Here's the code:

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

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

    // Checking if the user entered a correct input:
    if (argc != 2) {
        printf("You're not using it correctly!\n");
        return 1;
    }

    // Opening the file in argv[1]
    FILE *f = fopen(argv[1], "r");

    // Validating that there's a file in argv[1]
    if (f == NULL) {
        printf("File hasn't found\n");
        return 1;
    }

    unsigned char bytes[512];
    int counter = 0;
    FILE *img = NULL;

    while (fread(bytes, 512, 1, f) == 1) {
        if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff &&
            (bytes[3] & 0xf0) == 0xe0) {
// NOTE/BUG: no need to special case the first file
#if 0
            // If it's the first jpg found:
            if (counter == 0) {
                img = fopen("000.jpg", "w");
            }
            else {
                fclose(img);
#else
            if (img != NULL)
                fclose(img);
#endif
                char filename[8];

                sprintf(filename, "%03i.jpg", counter);
                img = fopen(filename, "w");
                if (img == NULL) {
                    printf("Couldn't open file\n");
                    return 1;
                }
#if 0
            }
#endif
            counter++;

// NOTE/BUG: this is only executed if the current block has a header string
#if 0
            fwrite(bytes, 512, 1, img);
#endif
        }

// NOTE/FIX: this is the correct placement for the write
#if 1
        if (img != NULL)
            fwrite(bytes, 512, 1, img);
#endif
    }

// NOTE/BUG: if the input file had _no_ header, img will be NULL
#if 0
    fclose(img);
#else
    if (img != NULL)
        fclose(img);
#endif
    fclose(f);
}

Here's the fully cleaned up and refactored code [without the #if 0]:

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

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

    // Checking if the user entered a correct input:
    if (argc != 2) {
        printf("You're not using it correctly!\n");
        return 1;
    }

    // Opening the file in argv[1]
    FILE *f = fopen(argv[1], "r");

    // Validating that there's a file in argv[1]
    if (f == NULL) {
        printf("File hasn't found\n");
        return 1;
    }

    unsigned char bytes[512];
    int counter = 0;
    FILE *img = NULL;

    while (fread(bytes, 512, 1, f) == 1) {
        if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff &&
            (bytes[3] & 0xf0) == 0xe0) {
            if (img != NULL)
                fclose(img);
            char filename[8];

            sprintf(filename, "%03i.jpg", counter);
            img = fopen(filename, "w");
            if (img == NULL) {
                printf("Couldn't open file\n");
                return 1;
            }
            counter++;
        }

        if (img != NULL)
            fwrite(bytes, 512, 1, img);
    }

    if (img != NULL)
        fclose(img);
    fclose(f);
}


来源:https://stackoverflow.com/questions/63561945/cs50-recover-pset4-images-not-recovered

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!