Возможная ошибка в видео решения pset4 lab «объем» в функции fread() заголовка

#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. Спасибо. Я сделал. @Флюгер