CS50问题集4恢复不出图像。

问题描述 投票:0回答:1

我可以做一些建议,对我来说,这在逻辑上是合理的,但是当我运行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
c cs50 recovery
1个回答
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;
}

0
投票

为什么while(!foef()总是错的?

关于。

printf("File not found/n");

错误信息应输出到 stderr,不 stdout.

当错误指示来自于C库函数时,也应该输出到 stderr,系统认为发生错误的文本原因。函数:perror( "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) truefalse 定义在 stdbool.h 所以需要包含该头文件。

2) fread() 返回读取的项目数。(这也是第三个参数,(还记得之前说的关于 while( !foef() ) 所以该语句最好写成:

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

捕捉EFO和部分读取以及IO错误。

关于。

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) 的长度,所以它可能会错过与下一个图像的相遇,并可能导致下一个图像的部分标题等数据被写入当前输出文件。

请把这个函数贴出来。

is_jpeg_header(buffer) 

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

© www.soinside.com 2019 - 2024. All rights reserved.