CS50 问题集 4 Recover 不恢复图像

CS50 Problem set 4 Recover not recovering images

我可以为此提出一些建议,对我来说这在逻辑上是有道理的,但是当我 运行 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

我看到的一个错误是 filename 太短:您没有为终止零留出任何空间。这是未定义的行为,可能是您的麻烦来源。

但是对于一个简单的问题来说,整体逻辑非常复杂。我是这样写的。由于您一般不会检查错误,所以我就这样离开了 - 尽管我还没有阅读它,但对于这个测试作业来说可能没问题。不过,它确实有助于 return 不同错误的不同错误代码 - 它确实有助于解决原始错字!

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

why while(!foef() is always wrong

关于:

printf("File not found/n");

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

当错误指示来自C库函数时,也应该输出到stderr,系统认为发生错误的文本原因。功能: 错误("your error msg");

专为此而生。

关于:

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 中定义,因此需要包含 header 文件。

2) fread() returns 阅读的项目数。 (这也是第三个参数,(并记住之前关于 while( !foef() ) 的陈述,所以该陈述会更好地写成:

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

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

关于;

outptr = fopen(filename, "w"); 

调用 fopen() 的 success/failure 不受程序控制,因此,请始终检查 (!=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 

这段代码可以完全删除

posted 代码无法在第二个文件启动后关闭当前输出文件。

posted 代码总是读取 sizeof(buffer) 字节(假设没有错误)但是不能保证每个图像数据的长度恰好是 sizeof(buffer) 的倍数,因此它可以错过与下一张图像的相遇并且可能导致下一张图像的部分 header 等数据被写入当前输出文件。

请post函数:

is_jpeg_header(buffer) 

因为它不太可能解决上面列出的问题。