header 的 fread() 函数中 pset4 实验室 'volume' 的解决方案视频中可能存在错误

A Possible error in solution video of pset4 lab 'volume' within fread() function of header

这是 Brian 在 cs50 week4 lab4 中解释的代码

// Modifies the volume of an audio file
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// Number of bytes in .wav header
const int HEADER_SIZE = 44;

int main(int argc, char *argv[])
{
    // Check command-line arguments
    if (argc != 4)
    {
        printf("Usage: ./volume input.wav output.wav factor\n");
        return 1;
    }

    // Open files and determine scaling factor
    FILE *input = fopen(argv[1], "r");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

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

    float factor = atof(argv[3]);

    // TODO: Copy header from input file to output file
    uint8_t header[HEADER_SIZE];
    fread(header, HEADER_SIZE, 1,input))
    
    fwrite(header,HEADER_SIZE, 1, output);
    

    // TODO: Read samples from input file and write updated data to output file
    int16_t buffer;
     while(fread(&buffer, sizeof(int16_t), 1, input))
    {
        buffer *= factor;       
        fwrite(&buffer, sizeof(int16_t ), 1 ,output);
    }
    // Close files
    fclose(input);
    fclose(output);
}

我对 fread() 和 fwrite() 的作用感到困惑。 它说:

 while(fread(header, HEADER_SIZE, 1, input))

不应该是:

while(fread(header,sizeof(uint8_t), HEADER_SIZE, input)) 

因为语法是:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

ptr,这是要读取数据的内存地址(第一个字节),

size,即要读取的数据类型的大小(以字节为单位),

nmemb,这是一次读取的那些类型的数量,并且

stream,它是指向 fopen 返回的 FILE 的指针。

为什么我们在 fwrite() 和 fread() 中使用缓冲区的地址而不是 header 在 fwrite() 和 fread() 中?每次循环后buffer的值会被覆盖吗?

视情况而定。

如果你想收到一个完整的header,然后把它作为一个header来处理,具有header各部分的意思,那么你应该索要一份你想要处理的header的副本:

fread(header, HEADER_SIZE, 1, input)

如果你想接收一些字节(恰好是一个头的大小)然后将它们作为单独的字节处理(即忽略它们一起构成一个头的事实),那么你应该要求许多字节:

fread(header,sizeof(uint8_t), HEADER_SIZE, input)

(在获得明确许可的情况下,我添加了 WeatherVance 的贡献。它为我尝试解释语义含义的方法添加了技术后果的详细信息。)

fread(header, 1, 44, input)fread(header, 44, 1, input) 都将尝试读取 最多 44 个字节。
如果只能读取 2 个字节,那么 fread 将 return 在第一种情况下为 2,在第二种情况下为 0。因为第一个试图读取 44 个大小为 1 的项目,而第二个想要读取一个大小为 44 的项目。