循环遍历数据文件的末尾

Looping through end of data file

我一直在处理哈佛 CS50 的问题集 class,我们的任务是从存储卡中恢复 jpeg。该卡按顺序存储 jpg。在编写我的程序时,我决定使用 while 循环来一直循环直到 EOF,但是使用课程中包含的调试器我发现我的循环永远不会启动。我在下面包含了我的代码,我真的希望有人能帮助我理解我在循环中哪里出错了。

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

int main(int argc, char* argv[])
{
    // Ensure proper Usage
    if (argc != 1)
    {
        printf("This file takes no input commands!\n");
        return 1;
    }

    // open up card data file
    FILE* dataFile = fopen("card.raw", "r");
    if (dataFile == NULL) 
    {
        char* invalidFile = "card.raw";
        printf("Could not open %s.\n", invalidFile);
        return 2;
    }

    // Create variable to keep track of num of output files written
    int numFiles = 0;

    // Create buffer
    int* buffer = (int*)malloc(sizeof(int*) * 512);

    // Create new file conditions
    bool a = buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff;
    bool b = buffer[3] == 0xe0 || buffer[3] == 0xe1|| buffer[3] == 0xe2 || 
             buffer[3] == 0xe3 || buffer[3] == 0xe4 || buffer[3] == 0xe5 || 
             buffer[3] == 0xe6 || buffer[3] == 0xe7 || buffer[3] == 0xe8 || 
             buffer[3] == 0xe9 || buffer[3] == 0xea || buffer[3] == 0xeb || 
             buffer[3] == 0xec || buffer[3] == 0xed || buffer[3] == 0xee || 
             buffer[3] == 0xef;

    // Loop through until all files found         
    while(fread(&buffer, 512, 1, dataFile) == 1)
    {
        if(a && b)
        {
            // Create temporary storage
            char title[999];
            // print new file name
            sprintf(title, "%d.jpg", numFiles);
            // open new file
            FILE* img = fopen(&title[numFiles], "a");
            numFiles = numFiles + 1;
            fwrite(&buffer, sizeof(buffer), 1, img);
            free(buffer);
        }
        else 
        {
            if(numFiles > 0) 
            {

            }
        }
    } 
}

调用 malloc 后,buffer 指向已分配的内存(希望如此;您应该检查 buffer != null),但该内存的内容未定义。尽管如此,你使用它并将它与0xFF进行比较,这是没有意义的。您首先必须从文件中读取数据。

文件通常由字节组成,而不是整数,所以你的缓冲区应该是 unsigned char *.

类型

好吧,你的误解可能不止一种。

首先看一下手册页 of fread:

On success, fread() and fwrite() return the number of items read or written.

因此,如果您请求 512 字节,您应该期望它为 return 512。 如果它 returns 更少,你知道:要么你到达了文件的末尾,要么出了什么问题。

此外,如果您分配:

bool a = something;
bool b = somethingElse;

然后:

while(somethingEntirelyElse) {
    // Never update the value of a or b
    if(a && b) { ... }
    // Neither here ...
}

那么你可以称那张支票多余不是吗?

除非 ab 实际上是 volatile。但是不要去那里!

在您的情况下,ab 的赋值很可能属于 内部 while 循环。

然后你 alloc 你的 buffer 一旦在循环之外,但每次你实际写下来时 free 它。在下一次迭代中,您 得到一个 分段错误

您是否考虑过如果任何图像文件的大小不是 512 字节,并且图像未正确对齐会发生什么情况?

更好的方法是保存一个文件的开头位置,一旦遇到 EOF(你并不是真的要找...),你就会知道文件的确切大小,并且您的缓冲区必须有多大。


总而言之,我同意一些评论者的观点,你真的应该看看一些早期的作业,看看你是否可以从中学到一些东西。


模拟时间:

假设您有一本书,并且您想要复制上面有图像的每一页。 你告诉自己:哦,我只是遵循一个简单的算法,所以我可以考虑其他事情。

您的算法是:

  • 有复印机

  • 有一个笔记本,您可以在笔记本上记下页面是否包含图像。

  • 看看(截至尚未关闭的书),看看是否有图像。 -> 在笔记本上写下结果

  • 只要下一页正好有一个字母就开始翻页。 (不多也不少)-> 大多数情况下你会立即停止

  • 如果笔记本说:有图片,复制此页(注意,笔记本会说你第一次写在上面的内容)

  • 如果你只是复制了一张图片,扔掉你的复印机(不要为下一张图片买一台新的)