【问题标题】:CS50 recover doesn't output any imagesCS50 恢复不输出任何图像
【发布时间】:2020-08-18 12:33:52
【问题描述】:

我正在研究 CS50 课程的恢复计划。以下是说明:

  • 在一个名为 recover.c 的文件中实现您的程序,该文件位于一个名为 recover 的目录中。

  • 您的程序应该只接受一个命令行参数,即要从中恢复 JPEG 的取证图像的名称。

  • 如果你的程序不是只使用一个命令行参数执行的,它应该提醒用户正确使用,而 main 应该 返回 1。

  • 如果取证图像无法打开阅读,你的程序应该通知用户,main应该返回1。

  • 如果您的程序使用 malloc,则不得泄漏任何内存。

我认为我的代码应该可以工作,但事实并非如此。事实上,它根本不输出任何图像!代码如下:

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

int main(int argc, char *argv[])
{
    FILE * pFile = NULL;
    unsigned char *buffer = malloc(512);
    char* filename = NULL;
    int filenumber = 0;

    //If user didn't print 2 items
    if(argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    //Open the file
    pFile = fopen(argv[1], "r");
    if (!pFile)
    {
        fprintf(stderr, "File cannot be opened\n");
        return 2;
    }

    int j=0;
    
    // checking the card by 512b chunks 
    //loop (i=0,  i++);
    while (pFile)
    {
        int i =0;
        i++;

        //k=fread (buffer, 512, i, *file);
        int k = fread(buffer, 512, i, pFile);
        
        // if 512 byte block is jpeg, make new jpeg file
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // if it's not the first file, we should close the last one
            if (filename != NULL)
            {
                fclose(pFile);
            }

            //sprintf
            sprintf(filename, "%03i.jpg", 2);

            //FILE = fopen (W) 
            pFile = fopen(filename, "w");

            // fwrite (buffer, 512, j, *file1)
            fwrite (buffer, 512, j, pFile);

            //j=j+1
            j = j + 1;
        }

        // if k<512 - end of the loop
        if (k < 512)
        {
            return 0;
        }
    }
    free(buffer);
}

我不明白,但我的文件中没有看到新文件或 JPEG 弹出窗口。当我尝试双击名为 card.raw 的文件时,它不允许我打开它。

【问题讨论】:

  • 我重复你上一个问题的评论:正确的缩进很重要。不要让我们难以阅读,更重要的是,为了您自己!
  • 您的代码后半部分根本没有逻辑块的缩进。如果您必须搜索相应的括号,因为它们都在第一列,则不容易阅读。您必须第一眼就看到逻辑块。
  • 如果您的目的是不让人们阅读您的代码,那就是要走的路。
  • //loop (i=0, i++); while (pFile) 注释与下一行的指令无关,而只是下面几行。这比帮助更令人困惑。 pFile 是什么?您的输入文件是否会在运行时更改?
  • 不评论。拒绝应用缩进会分散人们的注意力。尤其是在被告知了几次之后。

标签: c cs50


【解决方案1】:

你有很多问题。在调试器中运行您的代码应该会在一秒钟内显示其中的大部分。

我们来看看:

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

int main(int argc, char *argv[])
{
    FILE * pFile = NULL;
    unsigned char *buffer = malloc(512);
    char* filename = NULL;  <<==== You never allocate any memory for this. Use an array.
    int filenumber = 0;

    //If user didn't print 2 items
    if(argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    //Open the file
    pFile = fopen(argv[1], "r");
    if (!pFile)
    {
        fprintf(stderr, "File cannot be opened\n");
        return 2;
    }

    int j=0;
    
    // checking the card by 512b chunks 
    //loop (i=0,  i++);   <<== No information provided by this comment.
    while (pFile)       <<== pFile is your input file. This should never change. ???
    {
        int i =0;
        i++;

        //k=fread (buffer, 512, i, *file);    <<== Useless comment. Nearly same as code below but causes compiler error
        int k = fread(buffer, 512, i, pFile); <<== i is always 1 and must be 1. Don't use variable.
                                              <<== BTW: You should check k **before** using the buffer.


        // if 512 byte block is jpeg, make new jpeg file
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // if it's not the first file, we should close the last one
            if (filename != NULL)
            {
                fclose(pFile);  <<== Yikes!!! This is your input file.
            }

            //sprintf  <<== Yes, that's obvious. Useless comment.
            sprintf(filename, "%03i.jpg", 2);  <<== Yikes!! You never allocate memory. NULL pointer!!
                                               <<== Why do you always print 2? you have a counter.

            //FILE = fopen (W)  <<== Again no useful information in comment
            pFile = fopen(filename, "w");  <<== Feed NULL into fopen and kill pFile.

            // fwrite (buffer, 512, j, *file1)  <<== you know what I mean...
            fwrite (buffer, 512, j, pFile);  <<== You only have 1 buffer, why write j blocks?

            //j=j+1  <<== obvious
            j = j + 1;
        }

        // if k<512 - end of the loop
        if (k < 512)   <<== fread returns number of elements, i.e. 1, not number of bytes.
        {
            << you return without
               - closing files
               - freeing buffer
            return 0;
        }
   <<== Now you go back to top of the loop and want to read next block from your raw file but pFile was killed in the loop.

    }
    free(buffer);
}

【讨论】:

  • 我不明白这部分:'pFile = fopen(filename, "w"); before using the buffer.'还有这个:'
  • 如果你从头开始读,你会发现你从来没有为filename分配任何内存,当你把它放入fopen时它仍然是NULL
  • 您为什么认为,如果您只有 512 字节的缓冲区,您可以一次写入 512 字节的 j 块?为什么大小应该一直增加(你在每个块之后做j=j+1)?
  • “为文件名分配内存”是什么意思?我应该怎么做?
  • 很抱歉。但是您应该重新开始并查看有关指针的教科书。您必须使用malloc 来获取指针可以指向的一些内存。或者您可以简单地使用数组 char filename[10]; 而不是指针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-02
相关资源
最近更新 更多