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

C语言WAV文件反转代码排查:CS50检测报错问题

CS50 WAV文件反转程序问题排查

我正在完成CS50课程中的WAV文件反转程序,程序看似运行正常,但CS50的检测工具发现了错误,我找不到问题所在。我尝试修改for循环中的迭代器i,当设置为infile_size - block_size时,文件无法完成转换/反转。以下是我的代码:

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

#include "wav.h"

int check_format(WAVHEADER header);
int get_block_size(WAVHEADER header);

int main(int argc, char *argv[])
{
    // Ensure proper usage
    // TODO #1
    // check if command-line arguments = argv[0], argv[1], argv[2] = 3 in sum
    if (argc != 3)
    {
        if (argc < 3)
        {
            printf("not enough command-line args\n");
        }
        else
        {
            printf("too much command-line args\n");
        }
        return 1;
    }

    // remember filenames
    char *infile = argv[1];
    char *outfile = argv[2];

    // open input file for reading
    FILE *inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        printf("could not open the infile\n");
        return 1;
    }

    // read header into an array
    WAVHEADER header;
    fread(&header, sizeof(header), 1, inptr);

    // use check_format to ensure WAV format
    check_format(header);

    // open output file for writing
    FILE *outptr = fopen(outfile, "w");
    if (outptr == NULL)
    {
        printf("couldn't open the outfile\n");
        fclose(inptr);
        return 1;
    }

    // write header to file
    fwrite(&header, sizeof(header), 1, outptr);

    // use get_block_size to calculate size of block
    int block_size = get_block_size(header);
    printf("block_size: %i\n", block_size);
    if (block_size < 0)
    {
        printf("block_size with no size\n");
        return 1;
    }

    // write reversed audio to file
    // 1. declare an array to store each block of audio
    char *buffer = malloc(block_size * sizeof(char));
    if (buffer == NULL)
    {
        printf("no memory location");
        return 1;
    }

    // get the size of the input file
    fseek(inptr, 0, SEEK_END);
    long int infile_size = ftell(inptr);
    printf("file_size: %li\n", infile_size);

    // iterate through the input file audio data
    for (long int i = infile_size; i >= 0; i -= block_size)
    {
        // move the file indicator to the start
        fseek(inptr, i, SEEK_SET);

        // read from inptr each size
        fread(buffer, sizeof(char), block_size, inptr);

        // write in outfile
        fwrite(buffer, sizeof(char), block_size, outptr);
    }

    // free
    free(buffer);

    // close files:
    fclose(inptr);
    fclose(outptr);
}

int check_format(WAVHEADER header)
{
    // TODO #4
    if (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E')
    {
        printf("This is the type .wav\n");
        return 0;
    }
    else
    {
        printf("File is not the type .wav\n");
        return 1;
    }
}

int get_block_size(WAVHEADER header)
{
    // TODO #7
    // check if channels are mono or audio
    if (header.numChannels == 1 || header.numChannels == 2)
    {
        int block_size;
        block_size = header.numChannels * (header.bitsPerSample / 8);
        return block_size;
    }
    else
    {
        printf("Not supported\n");
        return 1;
    }

}

问题分析与修正方案

1. 错误的文件范围处理

你当前用整个文件大小来反转,会把WAV文件头也当成音频数据处理,直接导致输出文件损坏。WAV的音频数据从文件头之后开始,正确的音频数据起始位置是sizeof(WAVHEADER),总长度是header.subchunk2Size。

2. 循环逻辑错误

  • 起始位置应该是最后一个音频块的起始地址:sizeof(WAVHEADER) + header.subchunk2Size - block_size
  • 循环终止条件应该是i >= sizeof(WAVHEADER),确保只处理音频数据部分
  • 原循环从文件末尾开始,第一次fseek到infile_size时已经没有数据可读,完全无效

3. 其他潜在问题

  • 文件打开模式:处理二进制文件必须用rb(读)和wb(写),否则Windows系统会自动转换换行符,破坏文件结构
  • check_format返回值未校验:如果输入不是WAV文件,程序应该直接退出,而不是继续执行后续操作
  • get_block_size错误返回值:通道数不支持时返回1,但主函数只判断block_size <0,会漏掉错误,应该返回-1表示异常

修正后的核心代码片段

// 修正:二进制模式打开文件
FILE *inptr = fopen(infile, "rb");
// ...
FILE *outptr = fopen(outfile, "wb");

// 修正:校验check_format的返回值
if (check_format(header) != 0)
{
    fclose(inptr);
    return 1;
}

// 修正:计算音频数据的有效范围
long int audio_start = sizeof(WAVHEADER);
long int audio_end = audio_start + header.subchunk2Size;

// 修正:循环逻辑
for (long int i = audio_end - block_size; i >= audio_start; i -= block_size)
{
    fseek(inptr, i, SEEK_SET);
    fread(buffer, block_size, 1, inptr);
    fwrite(buffer, block_size, 1, outptr);
}

// 修正get_block_size的错误返回值
int get_block_size(WAVHEADER header)
{
    if (header.numChannels == 1 || header.numChannels == 2)
    {
        return header.numChannels * (header.bitsPerSample / 8);
    }
    else
    {
        printf("Not supported\n");
        return -1; // 返回-1表示错误
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:56:10