循环遍历数据文件的末尾
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 ...
}
那么你可以称那张支票多余不是吗?
除非 a
和 b
实际上是 volatile。但是不要去那里!
在您的情况下,a
和 b
的赋值很可能属于 内部 while
循环。
然后你 alloc 你的 buffer
一旦在循环之外,但每次你实际写下来时 free 它。在下一次迭代中,您 将 得到一个 分段错误 。
您是否考虑过如果任何图像文件的大小不是 512 字节,并且图像未正确对齐会发生什么情况?
更好的方法是保存一个文件的开头位置,一旦遇到 EOF(你并不是真的要找...),你就会知道文件的确切大小,并且您的缓冲区必须有多大。
总而言之,我同意一些评论者的观点,你真的应该看看一些早期的作业,看看你是否可以从中学到一些东西。
模拟时间:
假设您有一本书,并且您想要复制上面有图像的每一页。
你告诉自己:哦,我只是遵循一个简单的算法,所以我可以考虑其他事情。
您的算法是:
有复印机
有一个笔记本,您可以在笔记本上记下页面是否包含图像。
看看(截至尚未关闭的书),看看是否有图像。 -> 在笔记本上写下结果
只要下一页正好有一个字母就开始翻页。 (不多也不少)-> 大多数情况下你会立即停止
如果笔记本说:有图片,复制此页(注意,笔记本会说你第一次写在上面的内容)
如果你只是复制了一张图片,扔掉你的复印机(不要为下一张图片买一台新的)
我一直在处理哈佛 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 ...
}
那么你可以称那张支票多余不是吗?
除非 a
和 b
实际上是 volatile。但是不要去那里!
在您的情况下,a
和 b
的赋值很可能属于 内部 while
循环。
然后你 alloc 你的 buffer
一旦在循环之外,但每次你实际写下来时 free 它。在下一次迭代中,您 将 得到一个 分段错误 。
您是否考虑过如果任何图像文件的大小不是 512 字节,并且图像未正确对齐会发生什么情况?
更好的方法是保存一个文件的开头位置,一旦遇到 EOF(你并不是真的要找...),你就会知道文件的确切大小,并且您的缓冲区必须有多大。
总而言之,我同意一些评论者的观点,你真的应该看看一些早期的作业,看看你是否可以从中学到一些东西。
模拟时间:
假设您有一本书,并且您想要复制上面有图像的每一页。 你告诉自己:哦,我只是遵循一个简单的算法,所以我可以考虑其他事情。
您的算法是:
有复印机
有一个笔记本,您可以在笔记本上记下页面是否包含图像。
看看(截至尚未关闭的书),看看是否有图像。 -> 在笔记本上写下结果
只要下一页正好有一个字母就开始翻页。 (不多也不少)-> 大多数情况下你会立即停止
如果笔记本说:有图片,复制此页(注意,笔记本会说你第一次写在上面的内容)
如果你只是复制了一张图片,扔掉你的复印机(不要为下一张图片买一台新的)