Музыка CS50 Pset3 - что делает sizeof (string)? - PullRequest
0 голосов
/ 20 ноября 2018

В pset3 CS50 мы должны иметь смысл файла notes.c:

// Печатает частоты и выводит WAV-файл со всеми нотами в октаве

#include <cs50.h>
#include <stdio.h>
#include <string.h>

#include "helpers.h"
#include "wav.h"

// Notes in an octave      
const string NOTES[] = {"C", "C#", "D", "D#", "E", "F",
                    "F#", "G", "G#", "A", "A#", "B"
                   };

// Default octave 
#define OCTAVE 4

int main(int argc, string argv[])
{
// Override default octave if specified at command line
int octave = OCTAVE;  
if (argc == 2)
{
    octave = atoi(argv[1]); 
    if (octave < 0 || octave > 8)
    {
        fprintf(stderr, "Invalid octave\n");
        return 1;
    }
}
else if (argc > 2)
{
    fprintf(stderr, "Usage: notes [OCTAVE]\n");
    return 1;
}

// Open file for writing
song s = song_open("notes.wav");

// Add each semitone
for (int i = 0, n = sizeof(NOTES) / sizeof(string); i < n; i++)
{
    // Append octave to note
    char note[4];
    sprintf(note, "%s%i", NOTES[i], octave);

    // Calculate frequency of note
    int f = frequency(note);

    // Print note to screen
    printf("%3s: %i\n", note, f);

    // Write (eighth) note to file
    note_write(s, f, 1);
}

// Close file
song_close(s);
}

Часть, которую я не могу понять: for (int i = 0, n = sizeof (NOTES) / sizeof (string); i

Для работы sizeof(string), не должно ли быть где-то в коде переменная с именем string?например, строка, которая на самом деле называется string?

Не совсем уверен, о чем идет речь.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

sizeof может использоваться как для переменных / выражений, так и для типов.Здесь string является типом, а NOTES является экземпляром переменной (массива).

Корень проблемы вызван CS-50 typedef char* string;.В целом, код является прекрасным примером запутывания.Сокрытие указателей за typedefs широко признано ужасной практикой.

Что код на самом деле говорит так:

const char* NOTES[] = { ...
...
sizeof(NOTES) / sizeof(NOTES[0])

Если бы он был написан как выше, не было бы сомнений в том, что этоделает: делит размер массива на размер каждого отдельного члена, чтобы получить количество элементов в массиве.

Я бы посоветовал прекратить использование учебника CS-50.

0 голосов
/ 20 ноября 2018

Чтобы sizeof(string) работал, не нужно ли где-нибудь в коде иметь переменную с именем string?

Нет, * 1009Оператор * может использоваться для операнда типа, например sizeof(int).Цитируя спецификацию ( выделение шахты )

Оператор sizeof возвращает размер (в байтах) своего операнда, который может быть выражением или именем в скобкахтипа .[....]

Вы можете увидеть использование типа string в своем коде:

const string NOTES[] = {"C", "C#", "D", "D#", "E", "F",
                    "F#", "G", "G#", "A", "A#", "B"
                   };

Итак, NOTES - это массив type string, string - здесь имя типа.

Выражение

 for (int i = 0, n = sizeof(NOTES) / sizeof(string); i < n; i++)

- очень плохая попытка сосчитать членов вмассив, он мог бы быть переписан как

 for (int i = 0, n = sizeof(NOTES) / sizeof(NOTES[0]); i < n; i++)

, который в основном делит размер всего массива на размер одного элемента, производя количество членов для удобства чтения.

Чтобы добавить точный источник, Проверьте заголовочный файл <cs50.h>, string определен как тип там.

Точное определение:

 /**
 * Our own data type for string variables.
 */
typedef char *string;
...