0

I'm going to use an Arduino to play a melody, the melody is split into 11 parts which stored in an array called notes

Here's the code:

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"};

When I tried to compile it, it returns an error message saying that

declaration of 'notes' as multidimensional array must have bounds for all dimensions except the first

so what should I do if I want to keep the contents in the array unchanged?

6
  • Each row of an array must be the same size. You may declare the entire array by surrounding all of your small arrays in braces, i.e. String notes[][] = { {..}, {..}, {..} }.
    – Grifplex
    Commented Jul 1, 2017 at 1:45
  • @Grifplex no, the last dimension must be specified
    – M.M
    Commented Jul 1, 2017 at 2:00
  • @M.M so what if I define the size of the last dimension as, for example, 10, if one row has only 5 items, what is the value of the remaining slots in the row?
    – hrmck
    Commented Jul 1, 2017 at 2:09
  • @AgnesLeung they'll contain null characters. I would recommend a design change: instead of strings use an enum, make the arrays be arrays of 1-byte elements containing the enum values, and then when you want to get a string, have a lookup table where the enum value translates to a string
    – M.M
    Commented Jul 1, 2017 at 2:19
  • This is a bad style to program microcontrollers, if you know the elements of your matrix it is better to create an array of static and constant elements.
    – eyllanesc
    Commented Jul 1, 2017 at 2:28

1 Answer 1

0

"La la la" sounds for me like something I learnt 40 (fourty!) years ago in the school. I asked google and found Solmization.

Thus, my first conclusion: Everything, we learnt in school will pay off one day (sooner or later).

As I read some concerns about (wasted) storage (between the lines), I thought about how to make it a little bit more compact. (It would become even more compact using some clever compression techniques but this is beyond what I want to present here.)

As there is a limited set of syllables with not too many distinct values, I intended to store them as bytes. As bytes can be represented as characters, sequences of bytes can simply be defined as constant C strings. Constant C strings provide an end-marker (0 terminator) for free. It's possible to declare/initialize arrays of constant C strings even if they have differing lengths (as the array stores actually only the pointers to the strings). Last but not least, I exploited the fact that multiple double-quoted sequences are concatenated as one string constant (if separated by whitespace only).

Furthermore, I did some "macro-magic" to simplify the code writing. This is not very elegant but quite convenient in "daily usage". (The "design goal" was to make the source code robust against typos in the definition of notes as well as to keep it "readable".)

My sample 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;
}

Test and output:

$ 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

$ 

Notes:

  1. I resisted the first desire for audible output and made print output instead.

  2. While I was transforming the original data I realized some , and ` in the strings. I didn't consider them to keep the sample code short. They've probably a meaning which I don't know. I guess, following the idea of my sample it should be possible to extend the definitions appropriately.

  3. I don't like the double definition of syllable macros (for character constants as well as string constants) but I didn't get a better idea. Although, I really couldn't remember that something like stringize for character constants exists I googled and found in The C Preprocessor – 3.4 Stringizing (part of the GNU gcc online docs.):

There is no way to convert a macro argument into a character constant.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.