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 的项目。
这是 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 的项目。