Simplify which array and variables to use in a function ?

I am working on a small project that has multiple String arrays and variables for each of the arrays.

I want to pass the arrays to a function but can not see how to tell the function which Array and variables to use in the function without hard coding the options in the function.

How can I simplify this code without having to change the Array - so only by making changes in the call to the displayList function, or in the displayList function itself ?

int ListIsActive = 1;

String ListItems1[] = {"x", "ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"};
int ListTop1 = 1;

String ListItems2[] = {"x", "sub item 1", "sub item 2", "sub item 3", "sub item 4", "sub item 5", "sub item 6", "sub item 7"};
int ListTop2 = 1;


// code in the main loop will change ListIsActive to 1, 2, 3, etc ( depending on other conditions ) and then call displayList()

void displayList() {

	if(ListIsActive == 1){
		lcd.print(ListItems1[ListTop1]);
	}
	if(ListIsActive == 2){
		lcd.print(ListItems2[ListTop2]);
	}
	if(ListIsActive == 3){
		lcd.print(ListItems3[ListTop3]);
	}
	if(ListIsActive == 4){
		lcd.print(ListItems4[ListTop4]);
	}
	if(ListIsActive == 5){
		lcd.print(ListItems5[ListTop5]);
	}
	if(ListIsActive == 6){
		lcd.print(ListItems6[ListTop6]);
	}

} // end of : void displayList

Q1 : Why are you using Strings in the first place ?

DaveO:
How can I simplify this code without having to change the Array - so only by making changes in the call to the displayList function, or in the displayList function itself ?

Without changing data structure there's little you can do... maybe using a switch case in your displayList() procedure to make code a little bit easy to read. If you're willing to do a minimal change in your data structure, you could use a bidimensional array (an array of your ListItemsn arrays), and your ListIsActive var could just be the index of the array you want to work on in your new displayList(int activeList, int topElement) procedure.

And if you're wondering why you should switch from String to char arrays, this is a good lecture : )

Goet:
you could use a bidimensional array

Thanks Goet.

So your suggestion is to convert the code to use a multi-dimensional array of type char to store the values.

Would this be the right path :

int ListIsActive = 0;

char ListItemsArray[2][8];
ListItemsArray[0][] = {"x", "ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"};
ListItemsArray[1][] = {"x", "sub item 1", "sub item 2", "sub item 3", "sub item 4", "sub item 5", "sub item 6", "sub item 7"};



// code in the main loop will change ListIsActive to either 1 or 2 ( depending on other conditions ) and then call displayList()

// in the main loop call :
displayList(ListIsActive);



void displayList(int WhichRow) {

		lcd.print(ListItemsArray[WhichRow,0]);  // to print the first element in the array ListItemsArray[0][]
		lcd.print(ListItemsArray[WhichRow,1]);  // to print the second element in the array ListItemsArray[0][]

} // end of : void displayList

DaveO:
Would this be the right path :

you may wish to look into PROGMEM to store constant string literals

DaveO:
Thanks Goet.

So your suggestion is to convert the code to use a multi-dimensional array of type char to store the values.

Would this be the right path :

Welcome : )
We're close. Conceptually we're there.
Here's a little overview about what a char array is, and how to handle multidimensional char arrays:

int activeList = 0;

// this is a char array:
//         index:   01234567 <-- it has 8 characters, so it's size is 9 (8 plus null terminating character typical of char array)
char charArray[] = "hi dave!";

// so this is an array of char arrays:
//                                   012345 <-- longest element has 6 characters, so it's a char array of 7 elements
char arrayOfCharArrays[][7] = {"x", "ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"};

// and so this is an array of arrays of char arrays:
// 8 cause it's the max number of elements we have in our arrays, 11 cause it's the longest char array we have in there
char arrayOfArraysOfCharArrays[][8][11] = {
  {"x", "ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"},
  {"x", "sub item 1", "sub item 2", "sub item 3", "sub item 4", "sub item 5", "sub item 6", "sub item 7"}
};

void setup() {
// your stuff
}

void loop() {
// your stuff
  displayList(activeList);
  delay(3000);
  activeList++;          // do something with activeList
  if (activeList > 1) { // checking it to avoid reading
    activeList = 0;    // stuff outside our structure (we have only 2 elements in our structure: 0 and 1)
  }
}

void displayList(int row) {

  lcd.print(arrayOfArraysOfCharArrays[row][0]); // prints the first element of the *array of char arrays* with index 'row' in our arrayOfArraysOfCharArrays structure
  lcd.print(arrayOfArraysOfCharArrays[row][1]); // prints the second element of the *array of char arrays* with index 'row' in our arrayOfArraysOfCharArrays structure

}

As already mentioned, using char type instead of String objects is good for our memory : )
And, as BulldogLowell suggested, we can even save ram space using PROGMEM modifier. Another good lecture about it (lot of examples) here.
There are a lot of ways to adapt the code for program memory usage. The one I suggest in your case could be something like this:

int activeList = 0;

const char arrayOfArraysOfCharArrays[][8][11] PROGMEM = {
  {"x", "ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"},
  {"x", "sub item 1", "sub item 2", "sub item 3", "sub item 4", "sub item 5", "sub item 6", "sub item 7"}
};

void setup() {
// your stuff
}

void loop() {
  displayList(activeList);
  delay(3000);
  activeList++;          // do something with activeList
  if (activeList > 1) { // checking it to avoid reading
    activeList = 0;    // stuff outside our structure (only 2 elements: 0 and 1)
  }
}

void displayList(int row) {
  lcdPrintFromPRGMEM(row, 0);
  lcdPrintFromPRGMEM(row, 1);
  // etc. Use a for if you have to print all elements
}

// this does the real printing job
void lcdPrintFromPRGMEM(int row, int col) {
  const char * ptr = arrayOfArraysOfCharArrays[row][col];
  char c;
  while (c = pgm_read_byte(ptr++)) {
    lcd.print(c);
  }
}

Thank You to all for the guidance and advice. Much appreciated.

Using your guidance, I managed to hack together some code found on google that looks like it works and is running as required on my Mega2560

Basic code is :

const int NumberOfMenus = 3;

char* ListItemsArray[NumberOfMenus][10] = {
{"x", "ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"},
{"x", "sub item 1", "sub item 2", "sub item 3", "sub item 4", "sub item 5", "sub item 6", "sub item 7"},
{"x", "sub2 item 1", "sub2 item 2", "sub2 item 3"}
}; 

int MenuCount[NumberOfMenus] = {6, 7, 3};  // the number of menu items in each of the above rows
int MenuTop[NumberOfMenus] = {1, 1, 1};    // default top item to display is the top of the list
int MenuPos[NumberOfMenus] = {1, 1, 1};    // active / last selected position where the cursor appears for each of the above menus

MenuIsActive = 1;  // tells the functions which of the rows to use from the array

and then in the function that uses the code :

lcd.print(ListItemsArray[MenuIsActive][MenuTop[MenuIsActive]]);

Well, if it's working... good!
Just few notes about your code (but I guess you already figured them out by yourself):

if you use a pointer to a bidimensional char array

char* ListItemsArray[NumberOfMenus][10]

then the content of the second couple of square brackets (10) indicates the number of elements you have in your longest menu. In your example, it's the second array with 8 elements. So could be covenient define that size as well, like this:

#define NumberOfMenu 3
#define MaxMenuLength 8
char * ListItemsArray[NumberOfMenu][MaxMenuLength] = {
{"x", "ITEM 1", "ITEM 2", "ITEM 3", "ITEM 4", "ITEM 5", "ITEM 6"},
{"x", "sub item 1", "sub item 2", "sub item 3", "sub item 4", "sub item 5", "sub item 6", "sub item 7"},
{"x", "sub2 item 1", "sub2 item 2", "sub2 item 3"}
};

Of course we have to pay attention to the fact that, for istance, ListItemsArray[0][7] or ListItemsArray[2][4] are pointing to a not meaningful memory areas relatively to our ListItemsArray structure, so you have to be sure that your menu handling logic

int MenuCount[NumberOfMenus] = {6, 7, 3};  // the number of menu items in each of the above rows
int MenuTop[NumberOfMenus] = {1, 1, 1};    // default top item to display is the top of the list
int MenuPos[NumberOfMenus] = {1, 1, 1};    // active / last selected position where the cursor appears for each of the above menus

will always identify meaningful memory areas when you call

lcd.print(ListItemsArray[MenuIsActive][MenuTop[MenuIsActive]]);

Goet:
Of course we have to pay attention to the fact that, for istance, ListItemsArray[0][7] or ListItemsArray[2][4] are pointing to a not meaningful memory areas relatively to our ListItemsArray structure, so you have to be sure that your menu handling logic

Thanks Goet

Yes, I have code in place to ensure that I don't go past the relative MenuCount value for the currently active row in the ListItemsArray array.

The code is linked to the rotary encoder input that is on the LCD board - I am using a reprap discount smart controller LCD board connected to a Ramps shield.

Thank You again for all your guidance - I doubt I would have found this solution without being steered in the right direction.

Regards