You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50 Pset4 Recover作业遇阻:文件指针访问问题求助

JPEG恢复程序的文件指针作用域问题

当前代码

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

typedef uint8_t BYTE;
int const BLOCK_SIZE = 512;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Incorrect usage\n");
        return 1;
    }

    FILE *file = fopen(argv[1], "r");
    if (file == NULL)
    {
        printf("Could not open the file\n");
        return 1;
    }

    BYTE buffer[512];
    int indx = 0;
    int irratation= 0 ;
    char* filename = malloc(10);

    while(fread(buffer, 1, BLOCK_SIZE, file) == BLOCK_SIZE)
    {
        FILE* ptr = NULL;

        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            irratation++;
            if(irratation >= 2)
            {
                indx++;
            }

            if (indx == 0)
            {
                sprintf(filename, "%03i.jpg", indx);
                ptr = fopen(filename, "w");
                fwrite(buffer, 1, BLOCK_SIZE, ptr);
            }
            else
            {
                fclose(ptr);
                sprintf(filename, "%03i.jpg", indx);
                ptr = fopen(filename, "w");
                fwrite(buffer, 1, BLOCK_SIZE, ptr);
            }
        }
        else
        {
            fwrite(buffer, 1, BLOCK_SIZE, ptr);
        }
    }

    return 0;
}

问题描述

我理解该作业的逻辑,并尝试按照walkthrough中的伪代码实现,但目前遇到文件指针作用域问题:当找到新的JPEG文件时,我打开了ptr并写入数据,但找到下一个新文件时无法关闭前一个已打开的文件;同时在未找到新文件的else分支中,无法写入到已打开的文件,因为ptr的作用域仅在if分支内。恳请提供解决建议。


解决建议

  • 调整文件指针作用域:将FILE* ptr = NULL;的声明移到while循环外面,让它的作用域覆盖整个循环过程,这样后续的分支都能访问到同一个指针变量,解决else分支无法写入、新JPEG无法关闭旧文件的问题。
  • 简化计数逻辑:去掉冗余的irratation变量,直接用indx计数。第一次找到JPEG时从0开始,之后每次发现新的JPEG头,先关闭当前打开的文件(如果有的话),再递增indx并打开新文件。
  • 增加空指针检查:在调用fwrite和fclose前,先判断ptr是否不为NULL,避免空指针操作导致程序崩溃。
  • 清理资源:循环结束后要关闭最后一个打开的JPEG文件,还要释放malloc分配的filename内存,避免内存泄漏。

修正后的代码

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

typedef uint8_t BYTE;
int const BLOCK_SIZE = 512;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    FILE *file = fopen(argv[1], "r");
    if (file == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    BYTE buffer[512];
    int indx = 0;
    char* filename = malloc(10);
    FILE* ptr = NULL; // 移到循环外,扩大作用域

    while (fread(buffer, 1, BLOCK_SIZE, file) == BLOCK_SIZE)
    {
        // 检查是否是JPEG起始标志
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // 如果已经打开了一个JPEG文件,先关闭它
            if (ptr != NULL)
            {
                fclose(ptr);
            }

            // 生成新文件名并打开文件
            sprintf(filename, "%03i.jpg", indx);
            ptr = fopen(filename, "w");
            if (ptr == NULL) // 检查文件是否成功打开
            {
                printf("Could not create file.\n");
                fclose(file);
                free(filename);
                return 1;
            }
            fwrite(buffer, 1, BLOCK_SIZE, ptr);
            indx++;
        }
        else
        {
            // 只有当已有打开的JPEG文件时,才写入数据
            if (ptr != NULL)
            {
                fwrite(buffer, 1, BLOCK_SIZE, ptr);
            }
        }
    }

    // 关闭最后一个打开的JPEG文件
    if (ptr != NULL)
    {
        fclose(ptr);
    }

    // 清理资源
    fclose(file);
    free(filename);
    return 0;
}

内容的提问来源于stack exchange,提问作者bopleromn 19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:20:14