Function Argument: Array of Strings (RobotC)

For my LCD system, I’m making a function


lcd_menu()

, which takes an array of strings (and the size of the menu, cause C has taught me well ;)), and prints a menu, yadda yadda yadda

So far, my code is like so:


int lcd_menu(char ** options, int menuSize) {
    int choice = 0;

    while(nLCDButtons != 0x010) {
        if (nLCDButtons == 0x100 && choice > 0) choice--;
        if (nLCDButtons == 0x001 && choice < menuSize) choice++;

        string buffer = "";
        stringFromChars(buffer, options[choice]);

        displayLCDCenteredString(1, buffer);
    }
    return choice;

}

When I googled this problem, I was led to a post on the FTC Forums that suggested a pointer of a pointer to a char (since, of course, in C style languages, arrays really are just pointers)

However, this leads to a compilation error, printed below:

What am I doing wrong here? Thanks!

(I’m coming from a PROS C++ environment, where I would usually just use an array of


std::string

, or something similar)

So I spent some time digging into this problem:

In general, RobotC does not play nicely with pointers. Any assumptions that RobotC should behave just like C will leave you frustrated - that’s what happened to me.

How I was able to solve your problem:
-Use an array of strings instead of a 2D char array. Under the hood, they are the same thing, but this way plays nicer with RobotC.
-Use the enums of the LCD buttons (kButtonLeft, kButtonRight, kButtonCenter) or change your button ids to 0x02, 0x04, and 0x01. Your assumptions for the button mask is the correct line of thinking but an incorrect implementation: using 0x as a formatter means your numbers are in hexadecimal - so your masks are 16, 256, and 1. Your masks are correct in binary but not hexadecimal.

  • Once your array is an array of strings, you can just set the buffer equal to the array[index]. You’ll need to cast your array[index] to string.
    -Watch out for “off by one” errors! If I call lcd_menu with 3 items, your choice++ decision allows me to go beyond the bounds of the array, arrays are 0 based so an array of three items long will have a max index of 2 - [0][1][2].

Here is how I rewrote your function:


oid lcd_menu(string* options, int size) {
	int choice = 0;

	int prev_choice = choice;
	while(1) {
		if (nLCDButtons == kButtonLeft && choice > 0) 
		{
			choice--;
		}
		if (nLCDButtons == kButtonRight && choice < size-1) 
		{
			choice++;
		}
		if (nLCDButtons == kButtonCenter))
		{
			break;
		}
		string buffer = (string) options[choice];

		if(prev_choice != choice)
		{
			displayLCDCenteredString(1, buffer);
		}

		prev_choice = choice;
	}
}

I used prev_choice logic so that I’m not writing to LCD every iteration through the loop. I also had the center button trigger a break instead of using it in the while condition for clarity. That is probably not necessary.

Also, here is my main, so you can see how I set up and called it:


task main()
{
	string list[3] = {"Where am I?", "What am I?", "I am a robot"};
	lcd_menu(list, 3);
}	

The only reason I included this was to demonstrate how I created and initialized my “menu options.”

The remaining problem with this solution is that the loop is always faster than you, so no matter how short you press the button it will iterate through your list and only really show the first and last menu options. I’ll let you wrestle with how to solve that problem first before offering solutions.

Hope that helps!
Katie

Omigod! I didn’t see this until now, this is wonderful! Thanks!