繁体   English   中英

CS50 恢复 - 我如何使用 sprintf? 错误:使用未声明的标识符“文件名”; 您指的是 'rename' 吗?

[英]CS50 Recover - How do I use sprintf? error: use of undeclared identifier 'filename'; did you mean 'rename'?

CS50 是我的第一次编码体验,我无法通过 Recover。 我正在参加在线免费课程,并且我正在自己工作,这些问题集对我来说非常困难。 如果我的代码和问题看起来很新手,我提前道歉。

一些问题:

  1. 我正确使用 sprintf 吗? 我需要用什么代替“文件名”(见错误)
  2. 我是否正确使用了while循环?
  3. 我什至接近正确的解决方案还是应该在这一点上退出编码?
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    // check usage
    if (argc != 2)
    {
        printf("Please enter only 1 argument\n");
        return 1;
    }
    // open file
    FILE *file = fopen(argv[1],"r");
    if (file == NULL)
    {
        printf("Usage: ./recover usage\n");
        return 1;
    }

    int count = 0;
    // Read first 4 bytes
    unsigned char buffer[4];
    while(fread(buffer, 512, 1, file) == 512);
    // check first 4 bytes
    if (buffer[0] == 0xff &&
        buffer[1] == 0xd8 &&
        buffer[2] == 0xff &&
        (buffer[3] & 0xf0) == 0xe0)
        // count this 512B block
        {
            if (count == 0) // if first jpeg
            {
                sprintf(filename, "%03i.jpg", count); // last number is ith filename
                FILE *img = fopen(filename, "w"); // writing to filename
                fwrite(buffer, 512, 1, filename); // write to buffer 512 bytes at a time to filename
            }
            else
            {
                fclose(filename);
                count++; // add to existing count
                sprintf(filename, "%03i.jpg", count); // last number is ith filename
                FILE *img = fopen(filename, "w"); // writing to filename
                fwrite(buffer, 512, 1, filename); // write to buffer 512 bytes at a time to filename
                
            }
        }
        else
        {
            if (count > 1)
            {
                sprintf(filename, "%03i.jpg", count); // last number is ith filename
                FILE *img = fopen(filename, "a"); // writing to filename
                fwrite(buffer, 512, 1, filename); // write to buffer 512 bytes at a time to filename
            }
        }

    fclose(argv[1]);
}

这是我的错误代码: ~/pset4/recover/ $ make recover clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow recover.c -lcrypt -lcs50 -lm -o recover recover.c:33:25:错误:使用未声明的标识符“文件名”; 您指的是 'rename' 吗? sprintf(文件名,“%03i.jpg”,计数); // 最后一个数字是第 i 个文件名 ^~~~~~~~ 重命名

recover.c:57:12:错误:不兼容的指针类型将 'char *' 传递给 'FILE *' 类型的参数(又名 'struct _IO_FILE *')[-Werror,-Wincompatible-pointer-types] fclose(argv[1 ]); ^~~~~~~ /usr/include/stdio.h:199:26: 注意:在此处将参数传递给参数'__stream' extern int fclose (FILE *__stream); ^ 产生 11 个错误。 : 目标“恢复”的配方失败 make: *** [recover] 错误 1

您的代码中存在许多问题。 有些有“简单”的修复,有些我只能做出“智能猜测”。

首先,您正在使用filename变量来写入 output 文件的名称,但永远不要声明; 这是一个简单的修复:声明一个char filename[512]; 变量(或任何大小,代替 512,你觉得是必要的)。

其次, fclose function 将先前打开的FILE* 'handle' 作为其参数; 在您的代码中,这将是file变量(用于输入文件)或img变量(用于输出)。

第三,您的代码对img变量使用了非常“本地”的定义,这些定义不会在不同的if... else块之间共享; 要解决此问题,请在更“外部”的 scope 中声明变量,然后在其他各个地方使用它(无需重新声明)。

其他问题是你的while (fread(buffer, 512, 1, file) == 512); 语句正在读取很多次(可能),但以下代码仅在读取操作失败执行,这几乎肯定不是您需要的; 因此,您应该有一个{... }块将(大部分)以下代码包含在该while循环中。

还有几个地方我认为你应该关闭 output 文件:一旦进入循环,你“重新打开”一个新的 output,然后在整个大循环完成后关闭“悬空”打开文件处理。

我在下面的代码中添加了带有三斜杠 ( /// ) 的注释,以解决这些问题。 请随时要求任何进一步的澄清和/或解释。

int main(int argc, char* argv[])
{
    // check usage
    if (argc != 2) {
        printf("Please enter only 1 argument\n");
        return 1;
    }
    // open file
    FILE* file = fopen(argv[1], "r");
    if (file == NULL) {
        printf("Usage: ./recover usage\n");
        return 1;
    }

    int count = 0;
    /// TEST first 4 bytes
    unsigned char buffer[512]; /// This needs to be 512 bytes - not just the first 4 that you test!!
    char filename[512]; /// Buffer in which to write filename string
    FILE* img = NULL;   /// This variable MUST be in the more outer scope!
    while (fread(buffer, 1, 512, file) == 512) { /// count and size were round the wrong way!
        // check first 4 bytes
        if (buffer[0] == 0xff &&
            buffer[1] == 0xd8 &&
            buffer[2] == 0xff &&
            (buffer[3] & 0xf0) == 0xe0)
            // count this 512B block
        {
            if (count == 0) { // if first jpeg
                sprintf(filename, "%03i.jpg", count); // last number is ith filename
                img = fopen(filename, "w"); /// Don't (re)declare a local "img"
                fwrite(buffer, 1, 512, img); /// Use FILE* handle, not name!
            }
            else {
                fclose(img); /// Use FILE* handle, not name!
                count++; // add to existing count
                sprintf(filename, "%03i.jpg", count); // last number is ith filename
                img = fopen(filename, "w"); /// Don't (re)declare a local "img"
                fwrite(buffer, 1, 512, img); /// Use FILE* handle, not name!
            }
        }
        else {
            if (count > 1) {
                fclose(img); /// I THINK you need to close the old file first!
                sprintf(filename, "%03i.jpg", count); // last number is ith filename
                img = fopen(filename, "a"); // writing to filename
                fwrite(buffer, 1, 512, img); // write to buffer 512 bytes at a time to filename
            }
        }
    }
    fclose(img); /// At SOME point (probably here) you should close the remaining opened output file!

    fclose(file); /// Use FILE* handle, not name!
    return 0;
}

此外,为了彻底,您确实应该检查img - fopen(...)调用的每个结果,如果曾经是NULL ,则添加某种错误处理(正如您在打开输入文件时所做的那样)。

感谢 Adrian Mole 的指点,我完成了如下代码:

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

int main(int argc, char *argv[])
{
    // check usage
    if (argc != 2) 
    {
        printf("Please enter only 1 argument\n");
        return 1;
    }
    // open file
    FILE *file = fopen(argv[1], "r");
    if (file == NULL) 
    {
        printf("Usage: ./recover usage\n");
        return 1;
    }
    int count = 0; // create count integer
    unsigned char buffer[512]; /// This needs to be 512 bytes - not just the first 4 that you test!!
    char filename[512]; // Buffer in which to write filename string
    FILE *img = NULL;   // This variable MUST be in the more outer scope!
    while (fread(buffer, 1, 512, file) == 512) // count and size were round the wrong way!
    { 
        // check first 4 bytes
        if (buffer[0] == 0xff &&
            buffer[1] == 0xd8 &&
            buffer[2] == 0xff &&
            (buffer[3] & 0xf0) == 0xe0)
            // count this 512B block
        {
            if (count == 0) // if first jpeg
            { 
                count++;
                sprintf(filename, "%03i.jpg", count - 1); // last number is ith filename
                img = fopen(filename, "w"); // Don't (re)declare a local "img"
                fwrite(buffer, 1, 512, img); // using img handle
            }
            else 
            {
                fclose(img); /// Use FILE* handle, not name!
                count++; // add to existing count
                sprintf(filename, "%03i.jpg", count - 1); // last number is ith filename
                img = fopen(filename, "w"); // Don't (re)declare a local "img"
                fwrite(buffer, 1, 512, img); // Using img handle
            }
        }
        else 
        {
            if (count > 0) 
            {
                fwrite(buffer, 1, 512, img); // write to buffer 512 bytes at a time to filename
            }
            else
            {
                continue;
            }
        }
    }
    fclose(img); // At SOME point (probably here) you should close the remaining opened output file!

    fclose(file); // Use FILE* handle, not name!
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM