In western music, the twelve notes used in musical notation are
arranged in the following order:
C/B# C#/Db D D#/Eb E/Fb F/E# F#/Gb G G#/Ab A A#/Bb B/Cb
Note that a slash in the above list indicates alternate notations
for the same note.
Any two notes that are adjacent to each other in the above list
are known as a semitone. Any two notes that have one note
separating them in the list above are known as a tone. A major
scale is made up of 8 notes. It starts on one of the above notes
and moves in the progression tone-tone-semitone-tone-tone-tone-semitone. For example, the major scale starting on Db is made up
of the following notes:
Db Eb F Gb Ab Bb C Db
The following rules also apply to major scales:
- The scale will contain each letter from A to G once and only once, with the exception of the first letter of the scale (which will be repeated as the last note of the scale).
- The scale may not contain a combination of both flat (b)
notes and sharp (#) notes.
For the purposes of this problem, we are only concerned with the
following major scales: C, Db, D, Eb, E, F, Gb, G, Ab, A, Bb, and B.
An interval is a distance between two notes on a scale. It can
be either ascending or descending. The names of the intervals
are derived by the distance between the two notes. Two notes
adjacent to each other in a major scale are known as a major
second. Two notes in a major scale with three notes separating
them are known as a major fifth. An octave is a special interval
which spans from one occurrence of a note to the next occurrence
of it in the major scale.
Your program is to read an input file that contains major scale
intervals to calculate, and is to output the results to an output
file. The data in the input file will consist of pairs of lines.
The first line of each pair will contain the major scale to be
used, and the second line of each pair will contain one or more
intervals to be calculated. Each interval to be calculated will
be separated by a semicolon. The interval to calculate will be
specified with a starting note, a direction (UP or DOWN), and the
interval itself (SECOND, THIRD, FOURTH, FIFTH, SIXTH, SEVENTH, or OCTAVE). When specifying notes, the lowercase letter "b" will be used to represent a flat, and the symbol "#" will be used to
represent a sharp. No spaces will immediately precede or follow
a semicolon, but one space will separate the note from the
direction as well as the direction from the interval.
The output file should be formatted as shown below, with a blank line after every test case. Each pair of lines in
the input file will produce a line stating the key, followed by
the results of the calculated intervals, one interval per line.
If the starting note of the interval is not a part of the major
scale being used, the program should output "invalid note for
this key".
The following example shows more clearly the format of the input
and output files:
C
F UP SECOND;G DOWN THIRD
E
F# DOWN FOURTH;Bb DOWN SEVENTH;B UP OCTAVE
Key of C
F: UP SECOND > G
G: DOWN THIRD > E
Key of E
F#: DOWN FOURTH > C#
Bb: invalid note for this key
B: UP OCTAVE > B
題目有點麻煩,定義一個調中不會同時存在升記號與降記號,並且每個 A-G 只會出現一次。
而定義某某調時,不會有升記號的調。
而詢問在某個調中的七個音中,從某個音往下數或者往上數的音為何。
可能打表比較好一點,再建某個調有哪七個音十分困難!
其餘就一般處理。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <map>
using namespace std;
map<string, int> NOTE;
string nn[12][2] = {
{"C", "B#"}, {"C#", "Db"}, {"D", ""}, {"D#", "Eb"}, {"E", "Fb"},
{"F", "E#"}, {"F#", "Gb"}, {"G", ""}, {"G#", "Ab"}, {"A", ""},
{"A#", "Bb"}, {"B", "Cb"}};
string majorScale[12][2][8];
void build() {
int i, j, k;
int d[] = {2,2,1,2,2,2,1};
for(i = 0; i < 12; i++) {
for(k = 0; k < 2; k++) {
if(nn[i][k] == "" || nn[i][k][1] == '#') continue;
int pos = i;
for(j = 0; j < 7; j++) {
majorScale[i][k][j] = nn[pos][k];
if(j) {
if(majorScale[i][k][j-1][0] == 'G' && nn[pos][k][0] != 'A')
majorScale[i][k][j] = nn[pos][!k];
if(majorScale[i][k][j-1][0] != 'G' && nn[pos][k][0] != majorScale[i][k][j-1][0]+1)
majorScale[i][k][j] = nn[pos][!k];
}
//cout << majorScale[i][k][j] << "-";
pos += d[j];
pos %= 12;
}
//cout << endl;
}
}
}
int trans(string n) {
if(n == "SECOND")
return 2;
if(n == "THIRD")
return 3;
if(n == "FOURTH")
return 4;
if(n == "FIFTH")
return 5;
if(n == "SIXTH")
return 6;
if(n == "SEVENTH")
return 7;
if(n == "OCTAVE")
return 8;
return 0;
}
int main() {
build();
int i, j, k;
char s[10005];
string major;
while(cin >> major) {
while(getchar() != '\n');
gets(s);
int len = strlen(s);
for(i = 0; i < len; i++)
if(s[i] == ';') s[i] = ' ';
stringstream sin(s);
string note, dir, gap;
printf("Key of %s\n", major.c_str());
int mposx, mposy;
for(i = 0; i < 12; i++)
for(j = 0; j < 2; j++)
if(nn[i][j] == major)
mposx = i, mposy = j;
while(sin >> note >> dir >> gap) {
printf("%s: ", note.c_str());
int g = trans(gap)-1, pos = -1;
if(dir == "DOWN") g = -g;
for(i = 0; i < 7; i++) {
if(majorScale[mposx][mposy][i] == note)
pos = i;
}
if(pos == -1) {
puts("invalid note for this key");
continue;
}
printf("%s %s > ", dir.c_str(), gap.c_str());
pos = (pos+g+7)%7;
printf("%s\n", majorScale[mposx][mposy][pos].c_str());
}
puts("");
}
return 0;
}
文章定位: