CS50 PSET4恢复:Fread()不填充缓冲区数组

发布于 2025-01-18 19:13:27 字数 2498 浏览 2 评论 0原文

您好,谢谢您的看看。

我正在通过CS50X工作,并且正在努力恢复。目的是打开一个.raw文件,在512个字节块中读取其内容,检查.jpg标头的最初的四个字节,然后将每个JPEG数据写入新文件。

我写了一个代码的主体,文件编译。调试器告诉我,我的缓冲区[512]变量保持空/零。然后,这意味着如果/其他条件和程序退出,则该程序会跳过。

尽管我的逻辑可能会存在缺陷,但我无法进入程序足够远,无法考虑这一点。

发布之前,我查找了问题。一些来源喜欢使用fread(缓冲区,512,1,输入),但是CS50本身使用fread(Buffer,1,512,Input)。另外,在初始化文件名​​时,我已经尝试了char * filename = malloc(8 * sizeof(char)); and char fileName [8];。对于这两行,我都尝试了每种方法,但仍缺少一些东西。

我的代码在下面。预先感谢您的宝贵时间。

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

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    // First check the number of arguments is correct.
    if (argc != 2)
    {
        printf("Correct Usage: ./recover.c [filename]\n");
        return 1;
    }

    // Open the file.
    FILE *inputFile = fopen(argv[1], "r");

    if (inputFile == NULL)
    {
        printf("File not found.\n");
        return 1;
    }

    // Create counter of number of files.
    int counter = 0;
    // Create filename variable
    char *filename = malloc(8 * sizeof(char)); // 7 + 1 for \0
    // Create a 512-size array buffer.
    BYTE buffer[512];
    // Initialise img file for scope access.
    FILE *img = NULL;

    while (fread(buffer, sizeof(BYTE), 512, inputFile))
    {
        // If start of new JPEG:
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            if (counter == 0) // If the FIRST JPEG
            {
                // Make new file:
                sprintf(filename, "%03i.jpg", counter);
                img = fopen(filename, "w");
                fwrite(buffer, sizeof(BYTE), 512, img);
            }
            else // If not the first JPEG
            {
                fclose(img); // Close previous file.
                counter++;
                // Make new file:
                sprintf(filename, "%03i.jpg", counter); // Update filename.
                img = fopen(filename, "w");
                fwrite(buffer, sizeof(BYTE), 512, img);
            }
        }
        else if (counter > 0) // buffer is continuation of previous.
        {
            fwrite(buffer, sizeof(BYTE), 512, img);
        }
        else
        {
            printf("I exited with no images.\n");
            return 2;
        }
    }
    free(filename);
    fclose(img);
    fclose(inputFile);
    return 0;
}

Hello and thank you for taking a look.

I'm working through CS50x and am struggling with Recover. The aim is to open a .raw file, read its contents in 512-byte blocks, check the initial four bytes for .jpg headers, and then write each JPEG data to a new file.

I have a body of code written, and the file compiles. The debugger tells me that my buffer[512] variable remains empty/zeroed. This then means the program skips if/else conditions and the program exits.

While my logic within the While loop may be flawed, I haven't been able to step far enough into the program to consider this.

I looked up my issue before posting. Some sources like to use fread(buffer, 512, 1, input), but CS50 itself uses fread(buffer, 1, 512, input). Also, when initialising the filename, I have tried both char *filename = malloc(8 * sizeof(char)); and char filename[8];. For both lines I have tried each method and am still missing something.

My code is below. Thank you in advance for your time.

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

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    // First check the number of arguments is correct.
    if (argc != 2)
    {
        printf("Correct Usage: ./recover.c [filename]\n");
        return 1;
    }

    // Open the file.
    FILE *inputFile = fopen(argv[1], "r");

    if (inputFile == NULL)
    {
        printf("File not found.\n");
        return 1;
    }

    // Create counter of number of files.
    int counter = 0;
    // Create filename variable
    char *filename = malloc(8 * sizeof(char)); // 7 + 1 for \0
    // Create a 512-size array buffer.
    BYTE buffer[512];
    // Initialise img file for scope access.
    FILE *img = NULL;

    while (fread(buffer, sizeof(BYTE), 512, inputFile))
    {
        // If start of new JPEG:
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            if (counter == 0) // If the FIRST JPEG
            {
                // Make new file:
                sprintf(filename, "%03i.jpg", counter);
                img = fopen(filename, "w");
                fwrite(buffer, sizeof(BYTE), 512, img);
            }
            else // If not the first JPEG
            {
                fclose(img); // Close previous file.
                counter++;
                // Make new file:
                sprintf(filename, "%03i.jpg", counter); // Update filename.
                img = fopen(filename, "w");
                fwrite(buffer, sizeof(BYTE), 512, img);
            }
        }
        else if (counter > 0) // buffer is continuation of previous.
        {
            fwrite(buffer, sizeof(BYTE), 512, img);
        }
        else
        {
            printf("I exited with no images.\n");
            return 2;
        }
    }
    free(filename);
    fclose(img);
    fclose(inputFile);
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

π浅易 2025-01-25 19:13:27

读取原始文件中的第一行后,程序退出(返回)(假设它不是 jpeg 标头,发行版原始文件就是这种情况)。 else if (counter > 0) 计算结果为 false,因此执行 else 分支。

The program exits (returns) after the first line in the raw file is read (assuming it's not a jpeg header, which is the case with the distro raw file). else if (counter > 0) evaluates to false, so the else branch executes.

枕梦 2025-01-25 19:13:27

谢谢大家的回复。现在问题已解决!

@dinocodersaurus(对不起,尚无法投票)提示我意识到我(错误地)以.jpeg标头开始立即(实际上,看起来数据都以隐藏的消息开头) , “惊喜”)。

else条件最初是为了避免错误的情况,但是当然,它已过早地退出时循环。几个循环后正确填充缓冲区。

然后,我遇到了第二个问题(由@some_programmer_dude指出),counter ++;在错误的位置,这意味着在第一个新的JPEG之后,没有其他内容。

我还将考虑您的最佳实践评论。

Thank you everyone for your response. The issue is now fixed!

@DinoCoderSaurus (sorry, can't upvote yet) prompted me to realise that I had assumed (wrongly) that the data in the raw file would immediately begin with a .jpeg header (in fact it looks like the data begins with a hidden message, "surprise").

The Else condition was initially put there to avoid errors but of course it was prematurely exiting the While loop. The buffer was populated correctly after a couple of loops.

I then encountered the second problem (pointed out by @Some_programmer_dude) that counter++; was in the wrong place, which meant after the first new JPEG, no others could be written.

I'll also take your comments about best practice into consideration.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文