Printing elements of an array to OLED

Felicitations fellow malefactors,

I am writing the elements of an array to an OLED display like:

char *keys[] = {"Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m", "Gm", "G#m"};

display.setCursor(32, 0);
display.println(keys[keySelect()]);

The elements of the array are musical keys. The elements are indexed by keySelect() (which is a function that reads a potentiometer and returns an integer from 0-11).

This works, but I was wondering if this is "bad form", i.e., using a function as an indexer like that.

Also, I don't know why
char *keys[] = {"Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m", "Gm", "G#m"}; works.
While
char keys[] = {"Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m", "Gm", "G#m"};
does not.

Sincere thanks for any advise.
TonyA

I generally tell Ops (you in this case) that if code works, use it. It simply too complex a task to take you through an introductory programming tutorial: many, many on the Internet.

If you do not understand array pointers, a Google search will reveal sites that can explain:
Arduino char array pointers for display functions at DuckDuckGo

This is indeed a odd thing in the C-language.
A normal variable is this: int i = 3;
However, when a text is declared, then it can be placed somewhere by the programmer, or you can let the compiler and linker put it somewhere.

char myText[10] = "Hello";      // The text "Hello" is located at 'myText'.
char *otherText = "World";      // The compiler/linker puts the text "World" somewhere.

It is the same for an array:

char myArray[][4] = { "Am", "A#m" };   // all the text is in the array
char *otherArray[] = { "Am", "A#m" };  // every piece of text can be anywhere

The char keys[] = {"Am", "A#m"}; is not valid. An array of characters is a single piece of text.

That makes it also possible to call a function with a text: Serial.println("Tomato");
The text "Tomato" is not specifically located somewhere with a variable, the compiler/linker puts it somewhere.

Have you used PROGMEM ? Then a mistake is easily made. There is a good explanation to get both the text and the array of pointers in PROGMEM: https://www.arduino.cc/reference/en/language/variables/utilities/progmem/ That needs extra effort, to force the compiler and linker to put everything in PROGMEM.

No.

But if you need your code to perform another action (in addition to printing the note to the display), then it would not be a good idea to call the keySelect() function a second time to get the note for use by that other action, because the function might not return the same value both times. In that case it would be better to assign the result from keySelect() to a local variable, then use that variable when printing to the screen and for the other action.

this is wrong as the initialising array you pass does not hold element of the type you declared.

This would be legit
char keys[] = {'a', 'b', 'c'}; // a char is denoted by us of a single quote

but in your case "Am" is not a char (you used double quotes and more than one symbol), it's a string literal so the type is a pointer to constant characters (const char *)

➜ proper form to use

const char *keys[] = {"Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m", "Gm", "G#m"};

if you want a char array, you need to make it 2D and reserve enough space for the longest string literal you have in the initialiser + 1 for the hidden null end marker.

char keys[][4] = {"Am", "A#m", "Bm", "Cm", "C#m", "Dm", "D#m", "Em", "Fm", "F#m", "Gm", "G#m"};

this form consumes more memory though as "Am", "Bm", "Cm" etc only require 3 bytes and not 4 but by definition in an array all elements need to have the same type (here it would be and array of 4 characters ➜ char[4])

Thanks for this explanation, exactly what I was questioning. I will look at PROGMEM.

Exactly what I was wondering, thanks.

Thank you for this clarification, I understand now.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.