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; }
核心错误点及修正方案
命令行参数校验错误
作业要求输入、输出两个文件,原代码仅检查argc < 2,会导致argv[2]越界访问。修正为:if (argc != 3) { printf("Usage: reverse input.wav output.wav\n"); return 1; }文件指针位置滥用
- 读取完WAV头后,文件指针已指向音频数据起始位置,原代码却用
fseek重置回文件开头,后续又错误地重新读取bitsPerSample,覆盖了正确的头信息,还导致读取音频数据时从文件开头开始,必然读错数据量。 - 直接删除
fseek和第二次读取bitsPerSample的代码,保留第一次读取的header即可。
- 读取完WAV头后,文件指针已指向音频数据起始位置,原代码却用
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;
- 原代码用
fread参数错误
原代码fread(reversed, sample_size, 2 * num_samples, wav)的元素数量是错误的,应该读取num_frames个每个大小为block_size的采样帧,或者直接读取整个音频字节数:int read_count = fread(frames, block_size, num_frames, wav);采样帧反转逻辑错误
原代码的反转逻辑错误拆分了声道采样点,正确做法是将每个采样帧(含所有声道)作为整体反转: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); }内存分配错误
原代码malloc(num_samples * 2 * sizeof(short))的计算无依据,应根据音频总字节数分配内存:uint8_t *frames = malloc(audio_size);
内容的提问来源于stack exchange,提问作者JamieForster
相关产品推荐
相关产品推荐

