Search code examples
arrayscarduinoarduino-esp32

Pass multidimensional Array as parameter to function


I am writing a basic menu system for a TTGO-T to be able to select between different functions, I am trying to pass a multidimensional(2D) array of strings to a function(drawMenu & updateMenu). Ex: drawMenu(TFT_GREEN, 4, options);

The array is defined at compile time. It works if I specify which array inside the function
Example:

void drawMenu(uint16_t color, int stringArrLength)
{
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(color, TFT_BLACK);
  tft.drawCentreString("TTGO - T",69,0,4);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  for(int i=0;i<stringArrLength;i++)
  {
    if(count == i)
    {
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.drawString("> ", 0, (20 + (20 * i)), 2);
      tft.setTextColor(TFT_WHITE, color);
      tft.drawString(options[i], 10, (20 + (20 * i)), 2);
    }
    else
    {
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.drawString(options[i], 5, (20 + (20 * i)), 2);
    }
  }
}

...But I would like to be able to have sub-menus, and not have to write new functions for each sub-menu. When I compile I get this error

cannot convert 'char (*)[25]' to 'char**' for argument '3' to 'void drawMenu(uint16_t, int, char**)'

I thought as long as you defined that it was a multi-dimensional array in the parameters the dimensions didn't matter, I may just be stupid though.

Code:
#include <TFT_eSPI.h> 
#include <SPI.h>
#include <Wire.h>

TFT_eSPI tft = TFT_eSPI();

int leftButton = 0;
int rightButton = 35;
int count = 0;

/**
 * NOTE: If adding more options dont forget the change the parameters for
 * drawMenu();
 * &
 * updateMenu();
 */
char options[4][25] = {
  "Triangle",
  "TicTacToe",
  "Option 3",
  "Change Color"
};

char colors[6][25] = {
  "Red",
  "Orange",
  "Yellow",
  "Green",
  "Blue",
  "Purple"
};


void setup(void) 
{
  pinMode(leftButton,INPUT_PULLUP);
  pinMode(rightButton,INPUT_PULLUP);
  tft.init();
  tft.fillScreen(TFT_BLACK);
  drawMenu(TFT_GREEN, 4, options);
}

void loop() 
{
    updateMenu(4, options);
}

void drawMenu(uint16_t color, int stringArrLength, char **Arr)
{
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(color, TFT_BLACK);
  tft.drawCentreString("TTGO - T",69,0,4);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  for(int i=0;i<stringArrLength;i++)
  {
    if(count == i)
    {
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.drawString("> ", 0, (20 + (20 * i)), 2);
      tft.setTextColor(TFT_WHITE, color);
      tft.drawString(Arr[i], 10, (20 + (20 * i)), 2);
    }
    else
    {
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.drawString(Arr[i], 5, (20 + (20 * i)), 2);
    }
  }
}

void updateMenu(int stringArrLength, char **Arr)
{
  /**
   * Dont need to mess with anything here
   */
  if(digitalRead(leftButton) == 0 &&  count <= stringArrLength)
  {
    if(count == (stringArrLength - 1))
    {
      count = 0;
    }
    else
    {
      count++;
    }
    drawMenu(TFT_GREEN, 4, Arr);
    delay(500);
  }
/**
 * If right button pressed call function that matches current index(count)
 * 
 * NOTE: first "option" in options Array is at index 0; or Count = 0,
 * the last option is at (array length - 1); b/c of string ending null char (\0).
 */
  else if(digitalRead(rightButton) == 0)
  {
    if(count == 0)// 1st option...
    {
        triangles();
        delay(5000);
    }
    else if(count == 1)// 2nd option...
    {

    }
    else if(count == 2)
    {

    }
    drawMenu(TFT_GREEN, 4, Arr);// return back to menu after call
  }
}

Solution

  • The array-to-pointer conversion that occurs when an array is passed to a function only applies to the outermost array dimension. In your case, this means that a char [4][25] decays into a char (*)[25], not a char **, so the parameter types are not compatible.

    Change the declaration of the function parameter(s) from char **Arr to char Arr[][25].