Problem declaring multidimensional array filled with pre-existing arrays

First, the background on my code. I’m trying to output a set of up to 3 alphanumeric characters converted to morse code. To this end, I have defined each alphanumeric character’s morse code equivalent to an array (e.g “m_A”). During setup, the program will use a number of nested iterative loops to match each character with the morse equivalent and then output the on/off signals to another array that will be progressed through during the main loop.

I suspect this could be done more simply with pointers but I haven’t found a tutorial or reference on them that makes their usage click with me so I’m taking this approach for now.

My immediate problem is that when I attempt to put the individual arrays into a multidimensional array(“morse_char”), I recieve an error saying “array must be initialized with a brace-enclosed initializer”
I’m sure someone else has asked about something similar but I haven’t been able to turn up anything.

I’m sure there are other issues with my code (It’s been a decade since I did much programming, let alone with C/C++) but I’ll tackle those when I get to them.

int m_A[] = {1,3,0,0,0};
int m_B[] = {3,1,1,1,0};
int m_C[] = {3,1,3,1,0};
int m_D[] = {3,1,1,0,0};
int m_E[] = {1,0,0,0,0};
int m_F[] = {1,1,3,1,0};
int m_G[] = {3,3,1,0,0};
int m_H[] = {1,1,1,1,0};
int m_I[] = {1,1,0,0,0};
int m_J[] = {1,3,3,3,0};
int m_K[] = {3,1,3,0,0};
int m_L[] = {1,3,1,1,0};
int m_M[] = {3,3,0,0,0};
int m_N[] = {3,1,0,0,0};
int m_O[] = {3,3,3,0,0};
int m_P[] = {1,3,3,1,0};
int m_Q[] = {3,3,1,3,0};
int m_R[] = {1,3,1,0,0};
int m_S[] = {1,1,1,0,0};
int m_T[] = {3,0,0,0,0};
int m_U[] = {1,1,3,0,0};
int m_V[] = {1,1,1,3,0};
int m_W[] = {1,3,3,0,0};
int m_X[] = {3,1,1,3,0};
int m_Y[] = {3,1,3,3,0};
int m_Z[] = {3,3,1,1,0};

int m_1[] = {1,3,3,3,3};
int m_2[] = {1,1,3,3,3};
int m_3[] = {1,1,1,3,3};
int m_4[] = {1,1,1,1,3};
int m_5[] = {1,1,1,1,1};
int m_6[] = {3,1,1,1,1};
int m_7[] = {3,3,1,1,1};
int m_8[] = {3,3,3,1,1};
int m_9[] = {3,3,3,3,1};
int m_0[] = {3,3,3,3,3};

int morse_char[][5] = {m_A,m_B,m_C,m_D,m_E,m_F,m_G,m_H,m_I,m_J,m_K,m_L,m_M,m_N,m_O,m_P,m_Q,m_R,m_S,m_T,m_U,m_V,m_W,m_X,m_Y,m_Z,m_1,m_2,m_3,m_4,m_5,m_6,m_7,m_8,m_9,m_0};
char text_Uchar[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

int in_Pin = 3;
int out_Pin = 4;
char message[] = "SOS";
int message_size=(sizeof(message))/(sizeof(message[0]));

int flashPattern[62];
int flashCursor=0;
int loopTime;
int reading;
int previous = LOW;
int state = LOW;

unsigned long time = 0;
unsigned long debounce = 200UL;


void buttonCheck() {
  reading = digitalRead(in_Pin);
  if (reading == HIGH && previous == LOW && millis() - time > debounce)
  {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();
  }
  previous=reading;  
}

void prepPattern() {
    for(int i=0;i<message_size;i++){
    for(int j=0;j<36;j++){
      if(message[i] == text_Uchar[j]){
            for(int k=0;k<5;k++){
              for(int m=0;m<morse_char[j][k];m++){
                flashPattern[flashCursor]=1;
                flashCursor++;
              }
                flashPattern[flashCursor]=0;
                flashCursor++;
            }
            for(int n=0;n<3;n++){
              flashPattern[flashCursor]=0;
              flashCursor++;
            }
            break;
      }
    }
  }
  for(int o=flashCursor;o<62;o++){
    flashPattern[o]=0;
  }
}




void setup() {
  prepPattern();

}

void loop() {
  buttonCheck();
  loopTime = ((millis()-time)/175)%62;
  digitalWrite(out_Pin,state*flashPattern[loopTime]);
}

m_A, m_B, …, m_0 are actually pointers. So in the following line of code you are essentially trying to initialize a 2-dimensional int array with a single dimensional list of int pointers.

int morse_char[][5] = {m_A,m_B,m_C,m_D,m_E,m_F,m_G,m_H,m_I,m_J,m_K,m_L,m_M,m_N,m_O,m_P,m_Q,m_R,m_S,m_T,m_U,m_V,m_W,m_X,m_Y,m_Z,m_1,m_2,m_3,m_4,m_5,m_6,m_7,m_8,m_9,m_0};

You could just declare an array of int pointers and adjust your code accordingly:

int* pmorse_char[] = {m_A,m_B,m_C,m_D,m_E,m_F,m_G,m_H,m_I,m_J,m_K,m_L,m_M,m_N,m_O,m_P,m_Q,m_R,m_S,m_T,m_U,m_V,m_W,m_X,m_Y,m_Z,m_1,m_2,m_3,m_4,m_5,m_6,m_7,m_8,m_9,m_0};

Can you elaborate by what you mean when you say m_A...m_0 are actually pointers? I certainly didn't initialize them as such, I initialized them as one dimensional integer arrays.

Hedgesmith:
Can you elaborate by what you mean when you say m_A...m_0 are actually pointers? I certainly didn't initialize them as such, I initialized them as one dimensional integer arrays.

In C/C++ when you declare an array and use the array name it IS a pointer. For example, m_A is a pointer to the array while m_A[0] references the 0th element of the array. Therefore you could reference the 0th element using m_A[0] or *m_A. Similarly, you could reference the second element of the array using m_A[1] or *(m_A+1).

Another more readable alternative to translate your characters to morse would be to use a structure as below:

struct CharToMorse
{
  char text_Uchar;
  int morse_char[5];
};

CharToMorse charToMorse[] = {{"A"}, {1,3,0,0,0}};

Note I didn't completely initialize it but you get the idea.

You’ll quickly see there are many ways to accomplish the same task. Indeed you could dispense with searching for the character and create an index directly to the morse pattern like below:

  if (isdigit(message[i]))
  {
      index = message[i] - '0' + 26;
  }
  else
  {
      index = message[i] - 'A';
  }

ToddL1962:
In C/C++ when you declare an array and use the array name it IS a pointer. For example, m_A is a pointer to the array

This is not true. The array name is not a pointer. It is still an array.

It can implicitly decay to a pointer, though: Array declaration - cppreference.com

If you create a second array of pointers, you get a second level of indirection, and you use significantly more memory than necessary.
I think using a 2D array is the best choice here:

uint8_t morse_char[][5] = {
    {1,3,0,0,0}, // A
    {3,1,1,1,0}, // B
    {3,1,3,1,0}, // C
    {3,1,1,0,0}, // D
    {1,0,0,0,0}, // E
    {1,1,3,1,0}, // F
    {3,3,1,0,0}, // G
    {1,1,1,1,0}, // H
    {1,1,0,0,0}, // I
    {1,3,3,3,0}, // J
    {3,1,3,0,0}, // K
    {1,3,1,1,0}, // L
    {3,3,0,0,0}, // M
    {3,1,0,0,0}, // N
    {3,3,3,0,0}, // O
    {1,3,3,1,0}, // P
    {3,3,1,3,0}, // Q
    {1,3,1,0,0}, // R
    {1,1,1,0,0}, // S
    {3,0,0,0,0}, // T
    {1,1,3,0,0}, // U
    {1,1,1,3,0}, // V
    {1,3,3,0,0}, // W
    {3,1,1,3,0}, // X
    {3,1,3,3,0}, // Y
    {3,3,1,1,0}, // Z
    {1,3,3,3,3}, // 1
    {1,1,3,3,3}, // 2
    {1,1,1,3,3}, // 3
    {1,1,1,1,3}, // 4
    {1,1,1,1,1}, // 5
    {3,1,1,1,1}, // 6
    {3,3,1,1,1}, // 7
    {3,3,3,1,1}, // 8
    {3,3,3,3,1}, // 9
    {3,3,3,3,3}, // 0
};

Pieter

PieterP:
This is not true. The array name is not a pointer. It is still an array.

It can implicitly decay to a pointer, though: Array declaration - cppreference.com

I understand that as I've been doing C/C++ for more than three decades and have advanced degrees in CS; however, it is easier for a newbie to think of it that way especially since it can be used the same way as a pointer syntactically. 99.9% of the time it is irrelevant unless you are using it in the sizeof context where it comes in handy for initializing size constants.

Now we have left the OP thoroughly confused I'm sure...

ToddL1962:
In C/C++ when you declare an array and use the array name it IS a pointer.

AH! Now everything makes sense! Thank you for that crucial detail.

PieterP:
I think using a 2D array is the best choice here:

uint8_t morse_char[][5] = {

{1,3,0,0,0}, // A...

Yes, honestly the main reason I didn't do it that way was because I had originally hoped to use a method similar to how I would use the _G feature of Lua(except C/C++ doesn't have that as a compiled language) and didn't change anything looking for efficiency since it was a first draft.

ToddL1962:
Now we have left the OP thoroughly confused I'm sure...

Not confused at all, and I appreciate being treated with the "lies to children" approach even if Pieter's statement is slightly more accurate.