CS50问题集4恢复无法恢复图像

时间:2020-06-11 16:37:41

标签: c cs50 recovery

我可以为此提供一些建议,对我来说这在逻辑上是有意义的,但是当我运行check50时,仅恢复了其中一张图像。我已经多次检查了代码,所以我认为它不是语法错误,因此逻辑上一定有错误。任何提示将不胜感激。

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

typedef uint8_t BYTE;

bool is_jpeg_header(BYTE buffer[]);

int main(int argc, char *argv[])
{
    // Check if command line argument is valid
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }
    // Open memory card files
    char* mem_card = argv[1];
    FILE* inptr = fopen(mem_card, "r");
    if (inptr == NULL)
    {
        printf("File not found/n");
        return 1;
    }
    BYTE buffer[512];
    bool found_first_jpeg = false;
    int image_count = 0;
    char filename[8];
    FILE* outptr = NULL;

    while (!feof(inptr) && fread(buffer, sizeof(buffer), 1, inptr) == true)
    {
        // Check if we have found a JPEG
        if (is_jpeg_header(buffer) == true)
        {
            // Check if this is the first JPEG
            if (found_first_jpeg == false)
            {
                found_first_jpeg = true;
                sprintf(filename, "%03i.jpg", image_count);
                outptr = fopen(filename, "w");
                fwrite(buffer, sizeof(buffer), 1, outptr);
                image_count++;
            }
            // If this isn't the first JPEG, close file current JPEG and open new one for new JPEG
            else
            {
                fclose(outptr);
                image_count++;
                sprintf(filename, "%03i.jpg", image_count);
                outptr = fopen(filename, "w");
            }
        }
        // If we haven't found a new JPEG:
        else if (is_jpeg_header(buffer) == false)
        {
            // Continue reading file if we have not found first JPEG
            if (found_first_jpeg == false)
            {
                continue;
            }
            // Continue writing current JPEG into current file
            else
            {
                fwrite(buffer, sizeof(buffer), 1, outptr);
            }
        }
    }
    fclose(inptr);
    fclose(outptr);
    return 0;
}

bool is_jpeg_header(BYTE buffer[])
{
    if (((buffer[0] == 0xff) && (buffer [1] == 0xd8) && (buffer[2] == 0xff) && ((buffer[3] & 0xf0) == 0xe0)))
    {
        return true;
    }
    return false;
}

这是我从check50收到的错误代码

:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:) recovers 000.jpg correctly
:( recovers middle images correctly
    001.jpg not found
:( recovers 049.jpg correctly
    recovered image does not match

2 个答案:

答案 0 :(得分:0)

我看到的一个错误是filename太短:您没有为终止零留任何余地。这是不确定的行为,很可能是您的麻烦根源。

但是,就一个简单的问题而言,整个逻辑非常复杂。这是我的写法。由于您通常不检查错误,因此我以这种方式保留了它-尽管我尚未阅读,但对于该测试任务来说可能还可以。不过,它确实有助于为不同的错误返回不同的错误代码-原来的错字确实有帮助!

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

typedef uint8_t bool;
static const bool true = 1;
static const bool false = 0;

bool is_jpeg_header(const uint8_t buffer[]);

int main(int argc, char *argv[])
{
    // Check if command line argument is valid
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    // Open the memory card image
    char* mem_card = argv[1];
    FILE* infile = fopen(mem_card, "r");
    if (!infile)
    {
        printf("File not found/n");
        return 2;
    }

    uint8_t buffer[512];
    int image_count = 0;
    char filename[9];
    FILE* outfile = NULL;

    while (!feof(infile) && fread(buffer, sizeof(buffer), 1, infile) == 1)
    {
        // Check if we have found a JPEG
        if (is_jpeg_header(buffer))
        {
            // If we're already writing output - close it
            if (outfile)
                fclose(outfile);

            sprintf(filename, "%03i.jpg", image_count);
            outfile = fopen(filename, "w");
            image_count ++;
        }

        // Write the output if we're ready to write
        if (outfile)
            fwrite(buffer, sizeof(buffer), 1, outfile);
    }
    fclose(infile);
    fclose(outfile);
    return 0;
}

bool is_jpeg_header(const uint8_t buffer[])
{
    return
        buffer[0] == 0xff
        && buffer[1] == 0xd8
        && buffer[2] == 0xff
        && (buffer[3] & 0xf0) == 0xe0;
}

答案 1 :(得分:0)

why while(!foef() is always wrong

关于:

printf("File not found/n");

错误消息应该输出到stderr,而不是stdout

当错误指示来自C库函数时,也应该输出到stderr,这是系统认为发生错误的文本原因。功能: perror(“您的错误消息”);

是为此目的而制作的。

关于:

printf("Usage: ./recover image\n"); 

1)这应该是stderr,而不是stdout。 2)不要对可执行文件名称进行硬编码。建议:

fprintf( stderr, "Usage: %s imagefile\n". argv[0] );

关于:

while (!feof(inptr) && fread(buffer, sizeof(buffer), 1, inptr) == true) 

1)truefalsestdbool.h中定义,因此需要包括头文件。

2)fread()返回读取的项目数。 (也是第三个参数,(并记住关于while( !foef() )的先前语句,因此该语句最好写成:

while (  fread(buffer, sizeof(buffer), 1, inptr) == 1) 

捕获EOF和部分读取以及I / O错误。

关于;

outptr = fopen(filename, "w"); 

fopen()的调用成功/失败不受程序控制,因此,请始终检查(!= NULL)返回值以确保操作成功。

关于:

if (is_jpeg_header(buffer) == false)         
{             // Continue reading file if we have not found first JPEG 
    if (found_first_jpeg == false)             
    {                 
        continue;             
    }             // Continue writing current JPEG into current file  

    else 

此代码可以完全删除

启动第二个文件后,发布的代码无法关闭当前输出文件。

发布的代码始终读取sizeof(buffer)个字节(假定没有错误),但不能保证每个图像数据的长度都是sizeof(buffer)的倍数,因此它可能会错过与下一个图像的相遇AND可能导致下一张图片的标题等数据被写入当前输出文件。

请发布功能:

is_jpeg_header(buffer) 

因为不可能纠正上面列出的问题。