Execute contents of variable

Hey guys

I'm doing my first Arduino project and not exactly what you would call proficient in programming, although Google has made me come a long way. However, this problem I have not been able to find a solution to, mostly because I'm not really sure what to search for.

I'm making a menu on a 1602 LCD display, and use an array to hold all the settings for the menu.

Here's a single line of my array:

char* Menu[][6] = {
  {"Reset configuration", "", "SubMenu", "", "", "ResetConfiguration()"}
};

The idea is, that if the menu item is of the type SubMenu, I want to execute a function, which I have also defined in the array ("ResetConfiguration()" in this case).

Is it somehow possible for me to execute the contents of that specific variable directly? It's a void function, and I don't need to pass any variables into it.

I'm trying to make it kinda modular, so that if I at some point add another menu item of the type SubMenu, I can just add a new function, instead of rummaging around in the existing code.

Hope this makes sense. If not, I apologize. I've been working on this for a whole day and I'm reaching a state of semi-madness. :stuck_out_tongue:

I want to execute a function, which I have also defined in the array ("ResetConfiguration()" in this case).

When the compiler gets done, there are no function names any more. So, you won't be able to "call a function" using only its name.

You could google function pointers, and store the address of the function, instead of its name. Of course, you won't be able to store it in a character array.

Hey Paul,

thanks a lot for your prompt answer! :slight_smile:

PaulS:
When the compiler gets done, there are no function names any more. So, you won't be able to "call a function" using only its name.

I wasn't aware of that, but it makes perfect sense, now that I think about it.

PaulS:
You could google function pointers, and store the address of the function, instead of its name. Of course, you won't be able to store it in a character array.

Thanks, I'll take a closer look at that later. Initially, it does seem to complicate things more than necessary for me, but I might be wrong.

I just had a friend suggest to me, that I should just make one function and have it accept my SubMenu function as a parameter, and keep all the code in there. I guess that's a way to go, but if any of you have any better ideas, I'm very interested in hearing them.

It's not difficult: here's some working example code I just churned out

struct Menu {
    const char* description;
    const char* name;
    void (* function)(void);
};

void ResetConfiguration() {
    Serial.println("Reset Configuration is being called!");
}
void secondFunc() {
    Serial.println("Second func");
}
void thirdFunc() {
    Serial.println("Third func");
}

const size_t numMenu = 3;
Menu mymenu[] = {
    {"Reset configuration","SubMenu",ResetConfiguration},
    {"Item two", "2", secondFunc},
    {"Item three", "3", thirdFunc},
};

void parseMenu() {
    // Must give a number 0 to numMenu
    unsigned char c = Serial.read();
    c -= '0'; // Make c 0 to numMenu
    if(c < 0 || c >= numMenu) return;
    mymenu[c].function();
}

void setup() {
    Serial.begin(115200);
}

void loop() {
    if (Serial.available()) {
        parseMenu();
    }
}

EDIT: To run it, upload and then type 0, 1, or 2 into the serial monitor

Oh rats! WizenedEE did an example while I was doing one. And his is a bit more comprehensive. Oh well, for the record:

File: tmenu.h

typedef struct 
  {
  const char * description;
  void (* submenu) ();
  }  tMenu;  // menu type

Main sketch:

#include "tmenu.h"

void resetConfiguration ()
  {
  Serial.println ("Inside resetConfiguration.");  
  }  // end of resetConfiguration
  
tMenu menus [] = 
  {
  
  { "Foo", NULL },
  { "Reset configuration", resetConfiguration },
  { "Bar", NULL },

  { NULL, NULL}  // end of table 
  };  // end of menus
  
void showMenu (tMenu which [])
  {
  for (byte i = 0; which [i].description != NULL; i++)
    {
    Serial.print (i + 1);
    Serial.print (". ");
    Serial.println (which [i].description); 
    }  // end of for loop
  }  // end of showMenu
  
void setup ()
  {
  Serial.begin (115200);  
  
  showMenu (menus);  // show a menu
  
  // get a response, let's assume they picked 1. (second item)
  
  int response = 1;
  
  // if menu has submenu, call the function
  if (menus [response].submenu)
    menus [response].submenu ();
  
  }  // end of setup
  
void loop () {}

My example allows for no function (not sure if that is useful). Probably if everything is a function that is easier, and one of the things the function can do is display another menu.