我将使用Arduino播放旋律,旋律被分成11个部分,存储在一个名为notes的数组中
以下是代码:
String notes[0][]={"do", "re", "mi", "fa"};
String notes[1][]={"so", "rest", "mi", "do", "rest", "so", "rest", "fa", "re", "rest",
"fa", "rest", "re", "ti", "rest", "fa", "rest", "mi", "do", "rest"};
String notes[2][]={"rest", "si,", "do", "fa", "mi", "so", "do", "rest", "mi"
"fa", "mi", "fa", "mi", "fa", "mi", "do", "re"};
String notes[3][]={"la,", "la", "so", "fa", "mi", "fa", "so", "do", "do",
"rest", "mi", "fa", "mi", "do", "fa", "mi", "do", "la", "so", "rest"};
String notes[4][]={"rest", "so,", "so,", "fa", "mi", "re", "mi", "do"};
String notes[5][]={"la", "ti", "so", "fa", "so", "fa",
"fa", "mi", "re", "mi", "re", "do", "ti,", "do", "ti,", "la,", "so,"};
String notes[6][]={"rest", "do", "ti,", "do", "so,", "rest"};
String notes[7][]={"do", "ti,", "do", "mi", "rest"};
String notes[8][]={"fa", "mi", "re", "do", "fa", "mi", "re", "do", "do", "re", "re", "do`", "re`"};
String notes[9][]={"rest", "do", "ti,", "do", "so", "fa", "fa", "fa", "fa", "fa", "mi", "re", "mi",
"rest", "re", "mi", "fa", "mi", "mi", "mi", "re", "do", "mi", "rest"};
String notes[10][]={"la,", "ti,", "do", "re", "la,", "la,", "ti,", "do", "re", "do", "so"};
当我尝试编译它时,它会返回一条错误消息,说明
声明'notes'作为多维数组必须具有边界 除第一个
之外的所有维度
那么如果我想保持数组中的内容不变,该怎么办?
答案 0 :(得分:0)
因此,我的第一个结论是:我们在学校学到的一切都会在一天之前得到回报(迟早)。
当我读到关于(浪费)存储(在线之间)的一些担忧时,我想到了如何使它更紧凑一点。 (使用一些聪明的压缩技术会变得更加紧凑,但这超出了我想要呈现的范围。)
由于存在一组有限的音节且没有太多不同的值,我打算将它们存储为字节。由于字节可以表示为字符,因此字节序列可以简单地定义为常量C字符串。常量C字符串免费提供结束标记(0终止符)。即使它们具有不同的长度,也可以声明/初始化常量C字符串的数组(因为数组实际上只存储指向字符串的指针)。最后但并非最不重要的是,我利用了多个双引号序列作为一个字符串常量连接的事实(如果仅用空格分隔)。
此外,我做了一些“宏观魔术”来简化代码编写。这不是很优雅,但在“日常使用”中非常方便。 (“设计目标”是使源代码在notes
的定义中对拼写错误具有鲁棒性,并使其“可读”。)
我的样本solmization.cc
:
#include <cassert>
#include <cstring>
#include <iostream>
#define C_REST '0'
#define C_DO '1'
#define C_RE '2'
#define C_MI '3'
#define C_FA '4'
#define C_SOL '5'
#define C_LA '6'
#define C_TI '7'
#define C_DI 'a'
#define C_RI 'b'
#define C_FI 'c'
#define C_SI 'd'
#define C_LI 'e'
#define REST "0"
#define DO "1"
#define RE "2"
#define MI "3"
#define FA "4"
#define SOL "5"
#define LA "6"
#define TI "7"
#define DI "a"
#define RI "b"
#define FI "c"
#define SI "d"
#define LI "e"
const char *notes[] = {
DO RE MI FA,
SOL REST MI DO REST SOL REST FA RE REST FA REST RE TI REST FA REST MI DO REST,
REST SI DO FA MI SOL DO REST MI FA MI FA MI FA MI DO RE,
LA LA SOL FA MI FA SOL DO DO REST MI FA MI DO FA MI DO LA SOL REST,
REST SOL SOL FA MI RE MI DO,
LA TI SOL FA SOL FA FA MI RE MI RE DO TI DO TI LA SOL,
REST DO TI DO SOL REST,
DO TI DO MI REST,
FA MI RE DO FA MI RE DO DO RE RE DO RE,
REST DO TI DO SOL FA FA FA FA FA MI RE MI REST RE MI FA MI MI MI RE DO MI REST,
LA TI DO RE LA LA TI DO RE DO SOL
};
using namespace std;
int main()
{
enum { n = sizeof notes / sizeof *notes };
for (size_t i = 0; i < n; ++i) {
cout << "Line " << (i + 1) << ":" << endl;
const char *line = notes[i];
for (size_t j = 0, m = strlen(line); j < m; ++j) {
switch (line[j]) {
#define CASE(SYL) case C_##SYL: cout << ' ' << #SYL; break
CASE(REST);
CASE(DO);
CASE(RE);
CASE(MI);
CASE(FA);
CASE(SOL);
CASE(LA);
CASE(TI);
CASE(DI);
CASE(RI);
CASE(FI);
CASE(SI);
CASE(LI);
#undef CASE
default: assert(false); // should be unreachable
}
}
cout << endl;
}
return 0;
}
测试和输出:
$ g++ -std=c++11 -o solmization solmization.cc
$ ./solmization
Line 1:
DO RE MI FA
Line 2:
SOL REST MI DO REST SOL REST FA RE REST FA REST RE TI REST FA REST MI DO REST
Line 3:
REST SI DO FA MI SOL DO REST MI FA MI FA MI FA MI DO RE
Line 4:
LA LA SOL FA MI FA SOL DO DO REST MI FA MI DO FA MI DO LA SOL REST
Line 5:
REST SOL SOL FA MI RE MI DO
Line 6:
LA TI SOL FA SOL FA FA MI RE MI RE DO TI DO TI LA SOL
Line 7:
REST DO TI DO SOL REST
Line 8:
DO TI DO MI REST
Line 9:
FA MI RE DO FA MI RE DO DO RE RE DO RE
Line 10:
REST DO TI DO SOL FA FA FA FA FA MI RE MI REST RE MI FA MI MI MI RE DO MI REST
Line 11:
LA TI DO RE LA LA TI DO RE DO SOL
$
注意:
我拒绝了对声音输出的第一个愿望,而是改为打印输出。
在我转换原始数据时,我在字符串中意识到了一些,
和`
。我没有考虑他们保持示例代码简短。它们可能是我不知道的意思。我想,按照我的样本的想法,应该可以适当地扩展定义。
我不喜欢音节宏的双重定义(对于字符常量以及字符串常量),但我没有更好的主意。虽然,我真的不记得像字符常量字符串的东西存在,我用谷歌搜索并找到The C Preprocessor – 3.4 Stringizing(GNU gcc在线文档的一部分。):
无法将宏参数转换为字符常量。