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

CS50课程WAV音频反转代码无法通过check50检测求助

CS50 WAV反转过滤器check50不通过问题排查

我是编程新手,正在为CS50课程编写WAV音频反转过滤器代码。代码完成后,测试输入文件时主观听感是反转的,但check50功能提示文件未被正确反转。我反复检查代码未发现问题,且将输出文件再次反转后与原文件完全一致。附上代码如下:

#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 command-line arguments
    if (argc != 3)
    {
        printf("Usage: ./reverse input.wav output.wav\n");
        return 1;
    }

    // Open input file for reading
    // TODO #2
    // “read-only” mode
    FILE *input = fopen(argv[1], "r");
    if (input == NULL)
    {
        printf("Could not open %s.\n", argv[1]);
        return 1;
    }
    // Read header
    // TODO #3
    WAVHEADER header;
    fread(&header, sizeof(WAVHEADER), 1, input);

    // Use check_format to ensure WAV format
    // TODO #4
    if (!check_format(header))
    {
        printf("Not a WAV file.\n");
        return 1;
    }

    // Open output file for writing
    // TODO #5
    // write mode
    FILE *output = fopen(argv[2], "w");
    if (output == NULL)
    {
        printf("Could not open %s.\n", argv[2]);
        return 1;
    }

    // Write header to file
    // TODO #6
    fwrite(&header, sizeof(WAVHEADER), 1, output);

    // Use get_block_size to calculate size of block
    // TODO #7
    int size = get_block_size(header);

    // Write reversed audio to file
    // TODO #8
    BYTE buffer[size];
    if (fseek(input, size, SEEK_END))
    {
        return 1;
    }

    while (ftell(input) - size > sizeof(header))
    {
        if (fseek(input, - 2 * size, SEEK_CUR))
        {
            return 1;
        }
        fread(buffer, size, 1, input);
        fwrite(buffer, size, 1, output);
    }

    fclose(output);
    fclose(input);

}

int check_format(WAVHEADER header)
{
    // TODO #4
    if (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E')
    {
        return 1;
    }
    return 0;
}

int get_block_size(WAVHEADER header)
{
    // TODO #7
    int size = header.numChannels * header.bitsPerSample/8;
    return size;
}

问题排查与修复

  1. 文件打开模式错误
    WAV是二进制文件,你用了文本模式的"r"和"w"打开文件,在Windows系统下,文本模式会自动转换换行符(将\n转为\r\n),这会破坏WAV文件的二进制数据结构,导致check50检测到文件不一致。需要改为二进制模式:
FILE *input = fopen(argv[1], "rb");
FILE *output = fopen(argv[2], "wb");
  1. 循环条件遗漏最后一个音频块
    当前循环条件ftell(input) - size > sizeof(header)会导致当文件指针刚好在sizeof(header) + size位置时,最后一个块不会被处理。应该调整循环条件,确保所有音频块都被读取:
// 初始定位到文件末尾,然后回退一个块大小
if (fseek(input, -size, SEEK_END))
{
    return 1;
}

// 只要当前位置大于等于header的大小,就继续读取
while (ftell(input) >= sizeof(header))
{
    fread(buffer, size, 1, input);
    fwrite(buffer, size, 1, output);
    // 回退两个块大小:因为读完一个块后指针已经前进了size,所以需要回退2*size到上一个块的起始位置
    if (fseek(input, -2 * size, SEEK_CUR))
    {
        return 1;
    }
}
  1. 块大小计算的优先级问题
    虽然当前计算结果正确,但header.numChannels * header.bitsPerSample/8的运算优先级可能会让人误解,建议加上括号明确顺序:
int size = (header.numChannels * header.bitsPerSample) / 8;

修复以上问题后,check50应该就能正确通过检测了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:35:05