因此,我正在尝试CS50恢复练习(您需要在存储卡中搜索jpg文件,每当找到一个时,您就打开一个新文件,并将找到的jpg写到新文件中)。 我的代码可以编译,但是当我运行check50命令时,出现以下错误:
:( recovers 000.jpg correctly
recovered image does not match
:( recovers middle images correctly
recovered image does not match
:( recovers 049.jpg correctly
recovered image does not match
有人可以帮我弄清楚我在做什么错吗? 这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
// Checking if the user entered a correct input:
if (argc!=2)
{
printf("You're not using it correctly!\n");
return 1;
}
// Opening the file in argv[1]
FILE *f=fopen(argv[1], "r");
// Validating that there's a file in argv[1]
if(f==NULL)
{
printf("File hasn't found\n");
return 1;
}
unsigned char bytes[512];
int counter=0;
FILE *img= NULL;
while (fread(bytes, 512, 1, f)==1)
{
if (bytes[0]==0xff && bytes[1]==0xd8 && bytes[2]==0xff && (bytes[3]&0xf0)==0xe0)
{
// If it's the first jpg found:
if (counter==0)
{
img=fopen("000.jpg", "w");
}
else
{
fclose(img);
char filename[8];
sprintf(filename,"%03i.jpg", counter);
img= fopen(filename, "w");
if (img==NULL)
{
printf("Couldn't open file\n");
return 1;
}
}
counter++;
fwrite(bytes, 512, 1, img);
}
}
fclose(img);
fclose(f);
}
答案 0 :(得分:0)
您的主要问题是您没有正确处理多块文件。
仅当当前块具有标题时,才执行fwrite
。否则,您将丢弃数据。
这是因为fwrite
位于检测报头的if
块内。
如果,您遇到了第一个(即任意)标题,那么您将获得一个开放的输出流。因此,在那之后,您必须对每个循环 进行fwrite
。
由于在进入外部循环之前已将img
设置为NULL
,所以无需特殊情况000.jpg
并且,如果输入文件中没有[em]标头,则最后一个fclose
会出现段错误,因为img
指针将是NULL
。
我用[修复]注释了这些错误。如果#if 0
阻止了,我已经包装了旧的/新的代码:
#if 0
// old/original code
#else
// new/refactored code
#endif
这是代码:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
// Checking if the user entered a correct input:
if (argc != 2) {
printf("You're not using it correctly!\n");
return 1;
}
// Opening the file in argv[1]
FILE *f = fopen(argv[1], "r");
// Validating that there's a file in argv[1]
if (f == NULL) {
printf("File hasn't found\n");
return 1;
}
unsigned char bytes[512];
int counter = 0;
FILE *img = NULL;
while (fread(bytes, 512, 1, f) == 1) {
if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff &&
(bytes[3] & 0xf0) == 0xe0) {
// NOTE/BUG: no need to special case the first file
#if 0
// If it's the first jpg found:
if (counter == 0) {
img = fopen("000.jpg", "w");
}
else {
fclose(img);
#else
if (img != NULL)
fclose(img);
#endif
char filename[8];
sprintf(filename, "%03i.jpg", counter);
img = fopen(filename, "w");
if (img == NULL) {
printf("Couldn't open file\n");
return 1;
}
#if 0
}
#endif
counter++;
// NOTE/BUG: this is only executed if the current block has a header string
#if 0
fwrite(bytes, 512, 1, img);
#endif
}
// NOTE/FIX: this is the correct placement for the write
#if 1
if (img != NULL)
fwrite(bytes, 512, 1, img);
#endif
}
// NOTE/BUG: if the input file had _no_ header, img will be NULL
#if 0
fclose(img);
#else
if (img != NULL)
fclose(img);
#endif
fclose(f);
}
这是完全清理和重构的代码[ #if 0
]:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
// Checking if the user entered a correct input:
if (argc != 2) {
printf("You're not using it correctly!\n");
return 1;
}
// Opening the file in argv[1]
FILE *f = fopen(argv[1], "r");
// Validating that there's a file in argv[1]
if (f == NULL) {
printf("File hasn't found\n");
return 1;
}
unsigned char bytes[512];
int counter = 0;
FILE *img = NULL;
while (fread(bytes, 512, 1, f) == 1) {
if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff &&
(bytes[3] & 0xf0) == 0xe0) {
if (img != NULL)
fclose(img);
char filename[8];
sprintf(filename, "%03i.jpg", counter);
img = fopen(filename, "w");
if (img == NULL) {
printf("Couldn't open file\n");
return 1;
}
counter++;
}
if (img != NULL)
fwrite(bytes, 512, 1, img);
}
if (img != NULL)
fclose(img);
fclose(f);
}