#c #cs50 #volume #fwrite #fread
Вопрос:
Это код из того, что Брайан объясняет в 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 factorn");
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(amp;buffer, sizeof(int16_t), 1, input))
{
buffer *= factor;
fwrite(amp;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, который является адресом (первого байта) памяти, в которую нужно считывать данные,
размер, который представляет собой размер (в байтах) типа данных для чтения,
nmemb, то есть количество типов, которые нужно прочитать одновременно, и
поток, который является указателем на ФАЙЛ, возвращаемый fopen.
И почему мы используем адрес буфера в fwrite() и fread (), а не для заголовка в fwrite() и fread()? Будет ли значение буфера перезаписываться после каждого цикла?
Комментарии:
1.
sizeof(uint8_t)
равно 1 по определению, иfread(header, HEADER_SIZE, 1, input)
иfread(header, 1, HEADER_SIZE, input)
эквивалентны. но последнее более читабельно, потому что соответствует определениюfread
.2. Вы можете посмотреть на это 2 способами: 1) Прочитать
HEADER_SIZE
количество отдельных байтов или 2) Прочитать один заголовок размераHEADER_SIZE
.3. Вам нужен весь заголовок, и если было прочитано меньше, чем это, это
fread(header, HEADER_SIZE, 1, input)
вернет 0, потомуfread()
что возвращает количество прочитанных элементов . Однако в этомfread(header,sizeof(uint8_t), HEADER_SIZE, input)
случае любое значение, отличное от 0 (частичное считывание), будет считаться равнымtrue
.4. Что ты хочешь почитать? Количество байтов, которое может быть размером заголовка? Или один заголовок (соответствующего размера)? Собираетесь ли вы использовать заголовок по назначению? Или вы собираетесь работать с байтами, не используя информацию о том, что вместе они образуют заголовок?
5. Я хочу прочитать заголовок из входного файла и записать его в выходной файл. Затем считайте буфер из входного файла(который составляет 16 байт) по 16 байт каждый, умножьте его на коэффициент и запишите в выходной файл
Ответ №1:
Это зависит.
Если вы хотите получить один полный заголовок, а затем обработать его как заголовок со значением частей заголовка, вам следует запросить одну копию заголовка, который вы хотите обработать:
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
, то в первом случае будет возвращено 2, а во втором-0. Потому что первый пытается прочитать 44 элемента размера 1, а второй хочет прочитать 1 элемент размера 44.
Комментарии:
1. Для меня это не имеет никакого смысла. Может ли кто-нибудь объяснить простыми словами, что именно происходит с заголовком и буфером при использовании fread() и fwrite()
2. Не могли бы вы указать, какой из вариантов использования является вашим?
3. @WeatherVane Если ОП получил ценную помощь от одного из ваших комментариев, было бы уместно дать вам «принять». Для этого ваш вклад необходим в качестве сообщения с ответом. (Или кто-то, может быть, я, что-то перепутал…?)
4. @Yunnosch ИМО, это началось до того, как мы получили его в свои руки. Энни,
fread(header, 1, 44, input)
иfread(header, 44, 1, input)
оба попытаются прочитать до 44 байт. Если можно прочитать только 2 байта, тоfread
они вернутся2
в первом случае и0
во втором случае. Потому что первый пытается прочитать 44 элемента размера 1, а второй хочет прочитать 1 элемент размера 44.5. Спасибо. Я сделал. @Флюгер