如何实现cs50的pset3频率并理解notes.c

时间:2018-06-03 16:38:33

标签: c cs50

关于cs50的音乐我几乎没有问题。

1)for (int i = 0, n = sizeof(NOTES) / sizeof(string); i < n; i++)中有一行notes.c。什么意思是sizeof(字符串)?我可以理解sizeof(NOTES),这里的NOTES是一个字符串数组。但是sezeof( string )中的字符串是什么意思?我无法得到它。

2)这是我对“频率”的实现:

int frequency(string note)
{
    char N[2];
    int octave;
       //parsing the string into a note...
    strncpy(N, note, (strlen(note) - 1));
    //...and its octave
    octave = note[strlen(note) - 1] - '0';
    //add semitones
    int semitone;
    if (strcmp(N, "C") == 0)
        semitone = 1;
    if (strcmp(N, "C#") == 0 || strcmp(N, "Db") == 0)
        semitone = 2;
    if (strcmp(N, "D") == 0)
        semitone = 3;
    if (strcmp(N, "D#") == 0 || strcmp(N, "Eb") == 0)
        semitone = 4;
    if (strcmp(N, "E") == 0)
        semitone = 5;
    if (strcmp(N, "F") == 0)
        semitone = 6;
    if (strcmp(N, "F#") == 0 || strcmp(N, "Gb") == 0)
        semitone = 7;
    if (strcmp(N, "G") == 0)
        semitone = 8;
    if (strcmp(N, "G#") == 0 || strcmp(N, "Ab") == 0)
        semitone = 9;
    if (strcmp(N, "A") == 0)
        semitone = 10;
    if (strcmp(N, "A#") == 0 || strcmp(N, "Bb") == 0)
        semitone = 11;
    if (strcmp(N, "B") == 0)
        semitone = 12;
    //calculate freq: semitones
    float freq = 440 * (powf(2, (semitone -10) / (float)12));
    //calculate freq: multiply by num of octaves
    return round(freq * (powf(2, octave - 4)));
}

在./notes之后的输出是:

 C4: 262
C#4: 922746880
 D4: 294
helpers.c:55:12: runtime error: value 5.85908e+09 is outside the range of representable values of type 'int'
D#4: -2147483648
 E4: 330
 F4: 349
F#4: -2147483648
 G4: 392
G#4: -2147483648
 A4: 440
A#4: -2147483648
 B4: 494

代码本身有效,但它在notes.c中不起作用。

请帮助我理解什么是错的。

3 个答案:

答案 0 :(得分:1)

感谢。现在看起来效果更好。

//parsing the string into a note...
    char N = note[0];
    //...and its octave
    int octave = note[strlen(note) - 1] - '0';
    //add semitones
    int semitone;
    if (N == 'C')
        semitone = 1;
    if (N == 'D')
        semitone = 3;
    if (N == 'E')
        semitone = 5;
    if (N == 'F')
        semitone = 6;
    if (N == 'G')
        semitone = 8;
    if (N == 'A')
        semitone = 10;
    if (N == 'B')
        semitone = 12;
    //add accidentals
    if (note[1] == '#')
        semitone ++;
    if (note[1] == 'b')
        semitone --;
    //calculate freq: semitones
    float freq = 440 * (powf(2, (semitone - 10) / (float)12));
    //calculate freq: multiply by num of octaves
    return round(freq * (powf(2, octave - 4)));

我会详细了解sizeof。

答案 1 :(得分:1)

string 错误 1 类型char *的别名(指向char的指针)。 C没有实际的“字符串”数据类型;字符串表示为字符值序列,后跟0值终止符。例如,字符串"hello"由序列{'h', 'e', 'l', 'l', 'o', 0}表示。终止0很重要 - 没有它,strcpystrlen以及printf等各种库例程都不会将序列识别为字符串。

字符串存储在char的数组中。在大多数情况下,类型为“char数组”的表达式将被转换(“衰减”)为“指向char”的类型的表达式({{1 }})。所以,在大多数情况下,当我们处理字符串时,我们正在处理char *表达式。

但这并不意味着char * 是一个字符串。 char *可以指向字符串的开头(即,以零结尾的字符值序列),或者它可以指向不是的字符值序列的开头em>一个字符串,或者它可能指向一个不属于较大序列的单个字符。

随着那种咆哮......

char *string == char *,这是sizeof (string) == sizeof (char *)中字节数 2 char *显然是NOTES的数组,因此char *sizeof(NOTES)数组中的字节数。将NOTES除以sizeof(NOTES)可以得出sizeof(string)数组中的元素数量。

<小时/>

  1. NOTES头文件创建cs50.h typedef,我想抽象出C,呃,唯一字符串和数组语义。不幸的是,这导致了CS50学生之间的混淆。我个人认为,创建CS50课程的人们认为这是一个大错。
  2. 从技术上讲,“存储单元”,但存储单元实际上是一个字节。

答案 2 :(得分:0)

您可能需要对此进行细分。

您从数组中获得了

   int octave = note[strlen(note) - 1];

您将获得最后一个字符串的ASCII值(整数)。要将其转换为正确的数字,您需要“移动” ASCII表。

   octave -= 48; // Adjust ASCII to int value

因为char 0 = ASCII 48,所以可以一步完成。

   int octave = note[strlen(note) - 1] - '0';

请注意,当您要获取数组中以alpha表示的整数时,此方法有效。 如果要从数组中获取字符串(又名char *),则需要做一些不同的操作。关键是,即使是单个字符长字符串也应以\ 0结尾。

所以,现在您要获得提示音:

    char N[2];
    N[0] = note[0];
    N[1] = '\0';

请注意以上内容与本项之间的区别:

    char N = note[0];