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

CS50 Pset5 Reverse程序调试:result1返回值异常求助

CS50 Pset5 Reverse 程序错误排查:result1返回值不符合预期

在完成CS50的Pset5 Reverse作业时,程序运行时触发错误提示“RESULT 1 DONT EQUAL 1”,result1的返回值与预期不符。怀疑num_samples计算有误,但调试工具和CS50.ai未能定位问题,代码如下:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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
    if (argc < 2)
    {
        printf("Invalid usage (CLA!)\n");
        return 1;
    }

    // Open input file for reading
    // TODO #2

    // Set second cla to fname
    char *file_name = argv[1];

    // Open fname in read mode and store in wav
    FILE *wav = fopen(file_name, "r");

    // If wav can't be opened
    if (wav == NULL)
    {
        // Error message
        printf("Input is not a WAV file.\n");
        return 1;
    }

    // Read header
    // TODO #3

    WAVHEADER header; // Wav header

    // Read wav into address of header
    int result = fread(&header, sizeof(WAVHEADER), 1, wav);

    if (result != 1)
    {
        return 1;
    }


    // Use check_format to ensure WAV format
    // TODO #4
    check_format(header);

    // Open output file for writing
    // TODO #5

    // Setting filename to argv[2]
    char *outfile_name = argv[2];

    // Opening file in write mode
    FILE *outfile = fopen(outfile_name, "wb");

    // Check if outfile opened correctly
    if (outfile == NULL)
    {
        printf("Error outfile didn't open correctly!!!\n");
        return 1;
    }

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

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

    // Write reversed audio to file
    // TODO #8

    // Size of audio data
    fseek(wav, 0, SEEK_END); // end of file
    int file_size = ftell(wav); // current file position
    fseek(wav, 0, SEEK_SET); // back to begining of file

    // Checking if wav is open
    if (wav == NULL)
    {
        printf("wav is not opened\n");
    }
    
    // Sample size
    int a = fread(&(header.bitsPerSample), sizeof(header.bitsPerSample), 1, wav);
    // Checking if fread had an error
    if (a != 1)
    {
        printf("fread failed to read");
    }


    int sample_size = header.bitsPerSample / 8;

    int size = file_size - sizeof(WAVHEADER); // minus size of header
    int num_samples = size / sample_size;
    short* reversed = malloc(num_samples * 2 * sizeof(short));

    if (reversed == NULL)
    {
        printf("reversed array was equal to null");
        return 1;
    }

    if (num_samples / 2 != 0)
    {
         num_samples = num_samples - 1;
    }


        int result1 = fread(reversed, sample_size, 2 * num_samples, wav);

        if (result1 != 2 * num_samples)
        {
            printf("RESULT 1 DONT EQUAL 1\n");
            return 1;
        }

    for (int i = 0; i < num_samples / 2; i++)
    {
         // Store the pair of samples at index i
        short temp = reversed[2 * i];
        short temp1 = reversed[2 * i + 1];

        // Swap the pair of samples at index i with the pair at index num_samples / 2 - 1 - i
        reversed[2 * i] = reversed[2 * (num_samples / 2 - 1 - i)];
        reversed[2 * i + 1] = reversed[2 * (num_samples / 2 - 1 - i) + 1];

        // Put the stored samples at index num_samples / 2 - 1 - i
        reversed[2 * (num_samples / 2 - 1 - i)] = temp;
        reversed[2 * (num_samples / 2 - 1 - i) + 1] = temp1;

    }
    int result2 = fwrite(reversed, sample_size, num_samples, outfile);

    // Check if all audio was reversed
    if (result2 < num_samples)
    {
        printf("some audio not reversed");
    }

    // Close files
    fclose(outfile);
    fclose(wav);
    free(reversed);
    }


int check_format(WAVHEADER header)
{
    // TODO #4
    if (strncmp((char *) header.format, "WAVE", 4) == 0)
    {
        return 0;
    }
    else
    {
        printf("NOT A WAV FILE !\n");
        return 1;
    }
}

int get_block_size(WAVHEADER header)
{
    // TODO #7
    long total_channels = header.numChannels;
    long bits_per_sample = header.bitsPerSample;
    long block_size = total_channels * (bits_per_sample / 8);

    return (int) block_size;
}

核心错误点及修正方案

  1. 命令行参数校验错误
    作业要求输入、输出两个文件,原代码仅检查argc < 2,会导致argv[2]越界访问。修正为:

    if (argc != 3)
    {
        printf("Usage: reverse input.wav output.wav\n");
        return 1;
    }
    
  2. 文件指针位置滥用

    • 读取完WAV头后,文件指针已指向音频数据起始位置,原代码却用fseek重置回文件开头,后续又错误地重新读取bitsPerSample,覆盖了正确的头信息,还导致读取音频数据时从文件开头开始,必然读错数据量。
    • 直接删除fseek和第二次读取bitsPerSample的代码,保留第一次读取的header即可。
  3. num_samples计算逻辑完全错误

    • 原代码用file_size - sizeof(WAVHEADER)得到音频字节数,再除以单样本字节数,得到的是所有声道的总采样点数,但后续处理逻辑混淆了采样帧(含所有声道)和单声道采样点的概念。
    • 正确计算方式:用header.subchunk2Size(音频数据总字节数)除以block_size(每个采样帧的字节数,由get_block_size返回),得到采样帧数量:
      int audio_size = header.subchunk2Size;
      int num_frames = audio_size / block_size;
      
  4. fread参数错误
    原代码fread(reversed, sample_size, 2 * num_samples, wav)的元素数量是错误的,应该读取num_frames个每个大小为block_size的采样帧,或者直接读取整个音频字节数:

    int read_count = fread(frames, block_size, num_frames, wav);
    
  5. 采样帧反转逻辑错误
    原代码的反转逻辑错误拆分了声道采样点,正确做法是将每个采样帧(含所有声道)作为整体反转:

    for (int i = 0; i < num_frames / 2; i++)
    {
        uint8_t temp[block_size];
        memcpy(temp, &frames[i * block_size], block_size);
        memcpy(&frames[i * block_size], &frames[(num_frames - 1 - i) * block_size], block_size);
        memcpy(&frames[(num_frames - 1 - i) * block_size], temp, block_size);
    }
    
  6. 内存分配错误
    原代码malloc(num_samples * 2 * sizeof(short))的计算无依据,应根据音频总字节数分配内存:

    uint8_t *frames = malloc(audio_size);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:54:54