【问题标题】:2d array in Arduino with different row sizeArduino中具有不同行大小的二维数组
【发布时间】:2017-07-01 01:30:38
【问题描述】:

我打算用一个 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'声明为多维数组必须有边界 除第一个维度外的所有维度

那么如果我想保持数组中的内容不变该怎么办呢?

【问题讨论】:

  • 数组的每一行的大小必须相同。您可以通过将所有小数组括在大括号中来声明整个数组,即String notes[][] = { {..}, {..}, {..} }
  • @Grifplex 不,必须指定最后一个维度
  • @M.M 那么如果我将最后一个维度的大小定义为,例如10,如果一行只有5个项目,那么该行中剩余槽的值是多少?跨度>
  • @AgnesLeung 它们将包含空字符。我建议进行设计更改:使用enum 代替字符串,使数组成为包含枚举值的 1 字节元素的数组,然后当您想要获取字符串时,有一个查找表,其中枚举值转换到一个字符串
  • 这是一种对微控制器编程的糟糕风格,如果您知道矩阵的元素,最好创建一个静态和常量元素数组。

标签: c++ arrays arduino arduino-ide


【解决方案1】:

“啦啦啦”对我来说听起来像是 40(四十!)年前在学校学到的东西。我问了谷歌,找到了Solmization

因此,我的第一个结论是:我们在学校学到的一切都会有回报的一天(迟早)。

当我读到一些关于(浪费的)存储(字里行间)的担忧时,我想到了如何让它更紧凑一些。 (使用一些巧妙的压缩技术会变得更加紧凑,但这超出了我想在这里展示的范围。)

由于一组有限的音节没有太多不同的值,我打算将它们存储为字节。由于字节可以表示为字符,因此字节序列可以简单地定义为常量 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

$ 

注意事项:

  1. 我拒绝了对有声输出的第一个愿望,而是进行了打印输出。

  2. 在转换原始数据时,我在字符串中发现了一些 ,`。我不认为他们保持示例代码简短。它们可能有我不知道的含义。我想,按照我的示例的想法,应该可以适当地扩展定义。

  3. 我不喜欢音节宏的双重定义(对于字符常量和字符串常量),但我没有更好的主意。虽然,我真的不记得存在类似 stringize for character constants 的东西,我在 Google 上搜索并在 The C Preprocessor – 3.4 Stringizing(GNU gcc 在线文档的一部分)中找到了。

无法将宏参数转换为字符常量。

【讨论】:

    猜你喜欢
    • 2018-07-12
    • 2021-11-17
    • 2012-07-17
    • 2021-06-06
    • 2014-09-19
    • 2020-07-10
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多