这是代码。我是C语言的初学者,所以任何缩短我的代码的建议都将非常感激。我检查了所有50个图像,它们看起来很完美,但代码没有通过cs50检查。
int main(void)
{
FILE* source = fopen("card.raw", "r");
uint8_t jpg[512];
int direct = 0;
int jpgcounter = 0;
uint8_t checkjpg[4];
FILE* outputfile ;
char filename[7] ;
while(feof(source) == 0)
{
fread(jpg,512,1,source);
for (int i = 0 ; i < 4 ; i++)
{
checkjpg[i] = jpg[i];
}
if( checkjpg[0] == 0xff && checkjpg[1] == 0xd8 && checkjpg[2] == 0xff && checkjpg[3] >= 0xe0 && checkjpg[3] <= 0xef )
{
if ( direct == 0 )
{
sprintf( filename, "%03d.jpg" , jpgcounter);
outputfile = fopen(filename, "w");
fwrite(jpg,512,1,outputfile);
direct = 1;
}
else
{
fclose(outputfile);
jpgcounter++;
sprintf( filename, "%03d.jpg" , jpgcounter);
outputfile = fopen(filename, "w");
fwrite(jpg,512,1,outputfile);
}
}
else
{
fwrite(jpg,512,1,outputfile) ;
}
}
fclose(outputfile);
fclose(source);
return 0;
}
现在主要的问题是它没有通过cs50检查所以必须有一些我在card.raw或其他东西上遗漏的数据,人眼无法检测图像中的这些错误,但计算机可以。
答案 0 :(得分:1)
我想我知道问题所在。您永远不会初始化outputfile
。作为初学者,您应该在声明变量时始终初始化变量。永远不要写
int i;
写
int i = ...;
并给它一个初始值(0
,-1
,INT_MAX
,无论你喜欢什么)。这对于指针非常重要。如果你写
FILE * outputfile;
指针指向哪里?嗯,它是随机的。它可能指向任何地方或任何地方。这是&#34;无效&#34;指针,在任何情况下都不能使用outputfile
,因为任何使用的结果都是未定义的。但是你怎么知道它被初始化了?好吧,你不能!您无法为其分配任何可以检查的值。
更好的代码将是
FILE * outputfile = NULL;
因为现在outputfile
有一个定义的值,它是NULL
,这意味着您可以测试它是否已初始化
if (outputfile == NULL) {
// Not initialized
} else {
// Initialized
}
查看您的代码并考虑以下事项:
如果您的循环第一次运行并且第一个512字节块与0xffd8ff..
的if-test不匹配会发生什么?然后你以else-case结束,这个案例做了以下
fwrite(jpg,512,1,outputfile) ;
但这里有什么价值outputfile
?没有价值,它完全没有定义。您可以在任何地址访问内存,这很可能会使您的应用程序崩溃,这正是您遇到的情况。如果您已将outputfile
初始化为NULL
,那么正确的代码就是:
} else if (outputfile != NULL) {
fwrite(jpg,512,1,outputfile);
}
这里有一个超级美化,清理过的代码版本。代码未经测试,我只知道它编译。我知道它也变得更大,但请考虑还有大量的评论,代码是检查和处理所有预期的错误,甚至打印到STDERR
出了什么问题。如果我想要,我可以轻松压缩down to 58 lines,这比问题中的代码多7行,但是您的代码没有捕获或打印所有这些错误:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
int main ( void ) {
FILE * inputFile = fopen("card.raw", "r");
if (!inputFile) { // Same as "if (inputFile == NULL)"
fprintf(stderr, "Cannot open input file!\n");
// Don't close it, it didn't open!
return 1;
}
// Always declare variables in the smallest possible scope!
// Don't declare anything here you only need in the loop and
// whose value doesn't need to survive a loop iteration.
int fileCounter = 0;
FILE * outputFile = NULL;
bool writeError = false;
for (;;) { // Endless loop, will never terminate on its own
uint8_t cluster[512];
// It will read one cluster or nothing at all.
if (fread(cluster, sizeof(cluster), 1, inputFile) != 1) {
// If we have an open output file, close it.
if (outputFile) {
fclose(outputFile);
outputFile = NULL; // Not required but good style.
}
break; // Terminates the loop!
// Not reached, code flow continues after the loop.
}
// Check if start of new _or first_ JPG file.
if (cluster[0] == 0xFF && cluster[1] == 0xd8
&& cluster[2] == 0xFF && cluster[3] >= 0xE0 && cluster[3] <= 0xEF
) {
char filename[8];
snprintf(filename, sizeof(filename), "%03d.jpg", fileCounter++);
// Start nof an new JPG file.
// If we have an "old" one, time to close it
if (outputFile) {
fclose(outputFile);
}
// Open new file
outputFile = fopen(filename, "w");
if (!outputFile) {
// Cannot create output file.
writeError = true;
break; // Terminates the loop!
// Not reached, code flow continues after the loop.
}
}
// If we have an output file, write the cluster to it.
if (outputFile) {
if (fwrite(cluster, sizeof(cluster), 1, outputFile) != 1) {
// Write error.
writeError = true;
// Close the file.
fclose(outputFile);
break; // Terminates the loop!
// Not reached, code flow continues after the loop.
}
}
}
// If we end up here, we ran into one of the "breaks"
// and now need to find out which one.
bool exitWithError = false;
if (writeError) {
exitWithError = true;
fprintf(stderr, "Counldn't create/write to output file!\n");
} else if (ferror(inputFile) != 0) {
exitWithError = true;
fprintf(stderr, "Counldn't read from input file file!\n");
}
// Otherwise input file was just at the end.
// Final clanup:
fclose(inputFile);
return (exitWithError ? 1 : 0);
}
我与您分享此代码,因为只需了解其他人如何编写代码,学习某些编码概念可能最简单。