【问题标题】:CS50 Recover (Pset4)- Images not RecoveredCS50 恢复 (Pset4) - 未恢复的图像
【发布时间】:2020-08-24 13:23:24
【问题描述】:

所以我正在尝试 CS50 Recover 练习(您需要在存储卡中搜索 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);
}

【问题讨论】:

  • 首先,尝试以二元模式打开文件(用于读取和写入):将b 添加到fopen() 的模式字符串中,例如rbwb

标签: c cs50 recover


【解决方案1】:

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

你只做fwrite 如果当前块有标题。否则,您将丢弃数据。

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

如果您遇到了第一个(即任何)标头,您将有一个打开的输出流。因此,在那之后,您必须在 each 循环迭代中执行fwrite


由于您在进入外循环之前将img 设置为NULL,因此无需特殊情况下000.jpg

而且,如果输入文件没有有标题[永远],则最终的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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2020-08-02
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    相关资源
    最近更新 更多