CS50恢复(Pset4)-无法恢复图像

时间:2020-08-24 13:23:24

标签: c cs50 recover

因此,我正在尝试CS50恢复练习(您需要在存储卡中搜索jpg文件,每当找到一个时,您就打开一个新文件,并将找到的jpg写到新文件中)。 我的代码可以编译,但是当我运行check50命令时,出现以下错误:

:( 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

有人可以帮我弄清楚我在做什么错吗? 这是我的代码:

#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 个答案:

答案 0 :(得分:0)

您的主要问题是您没有正确处理多块文件。

仅当当前块具有标题时,才执行fwrite 。否则,您将丢弃数据。

这是因为fwrite位于检测报头的if块内。

如果,您遇到了第一个(即任意)标题,那么您将获得一个开放的输出流。因此,在那之后,您必须对每个循环 进行fwrite


由于在进入外部循环之前已将img设置为NULL,所以无需特殊情况000.jpg

并且,如果输入文件中没有[em]标头,则最后一个fclose会出现段错误,因为img指针将是NULL


我用[修复]注释了这些错误。如果#if 0阻止了,我已经包装了旧的/新的代码:

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

这是代码:

#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);
}

这是完全清理和重构的代码[ #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);
}