【问题标题】:CS50 'Recover' Problem - Incomplete Images - Two Incorrect BytesCS50“恢复”问题 - 不完整的图像 - 两个不正确的字节
【发布时间】:2021-03-14 01:34:22
【问题描述】:

第一次发帖,希望能帮到你!为篇幅道歉 - 只是想彻底。

我正在处理 CS50 问题集 4,我偶然发现了一个我还无法解决的有趣问题。我成功地恢复了 49 张图像,并且大约一半的图像似乎已正确恢复。但是,根据 Windows 资源管理器中的attached image,其余图像在文件末尾具有不同程度的“损坏”数据。

鉴于这发生在文件的中间,并且我似乎正确地找到了每个文件的开头,我相信这发生在我的 while 循环的后半部分 - 即“不是 jpg 标题”。我们被告知 jpg 文件是背靠背存储在原始数据上的,所以我认为我不需要考虑 jpg 文件末尾的任何异常情况。

我已经进行了许多测试以试图解决这个问题,但到目前为止都没有成功:

  1. 通过与 card.raw 比较验证总输出文件大小正确。
  2. 已验证我的 while 循环的后半部分运行图像 001.jpg 的预期次数 - 第一次出现问题。
  3. 在另一个 IDE 上运行
  4. 检查文件大小是否似乎与“损坏”文件有关,因为成功/失败输出没有明显的模式。
  5. 我认为可能是根本原因(缓冲区变量的定义, fread/fwrite 语句模式。)

我最后的调试工作是将我的 001.jpg 版本与一个已完成此问题集的朋友提供的已知正确版本 001.jpg 进行比较。我在十六进制编辑器中比较了这些,发现两个字节(总共 105984)不正确。在 00002400 行和 00012400 行,我在 jpg 文件的十六进制视图中用“d8”代替了“00”。没有其他区别。

我在下面列出了我认为相关的代码区域以及 check50 结果。如果需要,我很乐意提供更多代码。我觉得我目前已经达到了我的理解极限,我不确定如何继续解决这个问题。 谁能给我一些关于这里可能出现的问题的建议?

代码示例:

#include <stdint.h> //required for uint8_t
#include <stdio.h>
#include <stdlib.h>

const int SEG_SIZE = 512;
typedef uint8_t BYTE; //declaring byte to simplify code below

int main(int argc, char *argv[])
{
    //check if single argument has been applied, give usage instructions if not.
        //retracted
    
    //open memory card file
        // retracted code
    
    //error handle
        // retracted code
    
    //define variables
    BYTE buffer[SEG_SIZE]; //char=1 byte. 512 byte buffer for reading file.
    char img_filename[8]; 
    int count = -1; //declaring counter for number of files found. Starting at -1, allowing first found file to be number 0.
    
    //declare jpg file. Declaring in loop produces errors, local variable is 'block scoped'.
    FILE *img = NULL;

    //repeat until end of card
    while (fread(buffer, SEG_SIZE, 1, input)) //read 512 byte samples into buffer until end of file. returns number of items successfully read from file (i.e. 1)
    {
        //if start of new jpg
        if ((buffer[0]==0xff) && (buffer[1]=0xd8) && (buffer[2] == 0xff) && ((buffer[3] & 0xf0) == 0xe0)) // retracted code //checking if first four bytes match the beginning of a new jpg.
        {
            count++;
            if (count == 0) //found first image in raw data.
            {
                //retracted code - creates filename and opens file.
            }
            else
            {
                //closing previous file
                // retracted code
                img = fopen(img_filename, "w"); //opening next image file.
                fwrite(buffer, SEG_SIZE, 1, img);
            }
        }
        else if (count >= 0) //required to prevent running this code before declaring a file.
        {
            fwrite(buffer, SEG_SIZE, 1, img); //continue writing to current file, if present
        }
    }
    // retracted code
}

check50 结果:

Results for cs50/problems/2021/x/recover generated by check50 v3.2.2
:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:) recovers 000.jpg correctly
:( recovers middle images correctly
    recovered image does not match
:) recovers 049.jpg correctly

提前致谢,

安迪。

【问题讨论】:

  • 我认为问题出在“缩回”位上。我从这个程序作为一个 shell 开始,填充了缺失的位,它通过了 check50。
  • @DinoCoderSaurus,我可以向您发送我的代码副本以尝试了解问题所在吗?
  • 当然。创建一个 gist 或 pastebin 并将链接留在评论中,或将完整代码编辑到问题中,我很乐意看看。
  • 嗨@DinoCoderSaurus。我已将完整代码添加到问题中 - 你能看看吗?谢谢。

标签: c cs50


【解决方案1】:

此行中缺少=

if ((buffer[0]==0xff) && (buffer[1]=0xd8) && (buffer[2] == 0xff) && ((buffer[3] & 0xf0) == 0xe0)) //checking if first four bytes match the beginning of a new jpg.

编译器不会给出“表达式不可赋值”错误,因为括号改变了表达式“是”的内容。 buffer[1] = 0xd8(没有括号)会给出错误。除了(buffer[3] &amp; 0xf0),内部括号是无关的。

【讨论】:

  • 谢谢@Dino。我错过了这个,使用 CS50 IDE 上的“make”功能似乎没有出错。这解决了我的问题,谢谢!
  • 措辞相当笨拙,希望现在和后代能够澄清。
【解决方案2】:
FILE *img = NULL;

int counter = 0;
char image[8]; 

BYTE data[BLOCK];
//checking if the end of the card is reached
while (fread(&data, sizeof(BLOCK), 1, card) != 0)
{
    //checking if it's a new jpeg
    if (data[0] == 0xff && data[1] == 0xd8 && data[2] == 0xff && (data[3] & 0xf0)==0xe0)
    {
        //if it's not the first new jpeg, close the previous 
        if (img != NULL)
        {
            fclose(img);
        }

        sprintf(image, "%03i.jpg", counter);
        img = fopen(image, "w");
        if (img == NULL)
        {
            fprintf(stderr, "Couldn't open %s!\n", image);
            fclose(card);
            return 3;
        }
        counter++;

    }
    if (img != NULL)
    {
        fwrite(&data, sizeof(BLOCK), 1, img);
    }
} 

fclose(img);
fclose(card);

return 0;

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多