Using classes for LCD keypad menu.

I am having some trouble with my class. I originally wanted a 2d array so I could have [name, item1, item2] etc but cant hold different value types so I am trying classes. I can't get the basics right. I am just trying to assign a string to a menu object on initialisation.

For example if I try:

class Menu
{
public:
  Menu(String name);
};

Menu::Menu(String name)
{
  String myname=name;
}

Menu EC_PH("EC and PH");

void setup() {
  Serial.begin(38400);

}

void loop() {

  Serial.println(EC_PH.myname);
  delay(1000); 

}

I get 'class Menu' has no member named 'myname'. Isnt a member of the class an object anyway? Pardon my insolence.

I originally wanted a 2d array so I could have [name, item1, item2] etc but cant hold different value types

An array of struct instances could hold different types:

struct stuff
{
   char name[10];
   someOtherType item1;
   anotherType item2;
};
typedef struct stuff Stuff;

Stuff myStuff[3];

I get 'class Menu' has no member named 'myname'.

So, where in the class:

class Menu
{
public:
  Menu(String name);
};

do you think you've define a member named myname?

Creating a local variable in the constructor:

Menu::Menu(String name)
{
  String myname=name;
}

is pointless, since the local variable will go out of scope as soon as the constructor ends.

It is unlikely that the snippet of error message you posted was the first message, or the complete message.

It is more likely that the compiler first told you that it has no idea what a String is. Which is a pretty good indication that you shouldn't be using String.

Isnt a member of the class an object anyway?

Not necessarily. It the class member type is int, the variable is not an object.

I read that a structure is the same as a class but its variables are public by default, and I also have to download a library for this functionality. So I thought it would be easier just to create a menu class to hold the different variable types. The only experience I have with classes is a first year programming course in Python.

I thought the constructor could be used to initialize variables in the object at the top of the class hierarchy? So each Menu class object will have a myname variable which is created on initialization? Please explain what I am trying to do versus what should be done.

I thought variables were just instances of objects from the data type class? So constructors are only for defining functions belonging to the class not variables belonging to the object? I was trying to work from this Morse example class:

class Morse
{
  public:
    Morse(String pin);
    void dot();
    void dash();
  private:
    String _pin;
};
Morse::Morse(String pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
}


void Morse::dot()
{
  digitalWrite(_pin, HIGH);
  delay(250);
  digitalWrite(_pin, LOW);
  delay(250);  
}

void Morse::dash()
{
  digitalWrite(_pin, HIGH);
  delay(1000);
  digitalWrite(_pin, LOW);
  delay(250);
}

This saves the argument pin to a private variable _pin, but I want the variable to be accessable, and obviously a char or String. I will use the struct library if I must, but would like to learn a bit about classes as well.

So all I had to do was:

class Menu
{
public:
  String myname;
  Menu(String name);
};

Menu::Menu(String name)
{
  myname=name;
}

I will try use char instead of String. But now I think I should use structures, please explain:

struct stuff
{
   char name[10];
   someOtherType item1;
   anotherType item2;
};
typedef struct stuff Stuff;

Stuff myStuff[3];

What does myStuff[3] return? Can I do e.g myStuff[3].name and mystuff[3].item1? How can I accomplish this using classes (for education only), is it a class inside a class?

In the above line typedef struct stuff Stuff;, what is Stuff and myStuff and where are they defined?

So I tried:

struct stuff
{
   char name[10];
   int item1;
   int item2;
};
typedef struct stuff Stuff;

Stuff menu1;
//menu1.item1=13;
void setup() {

}

void loop() {


}

As soon as I include menu1.item1=13; I get: expected constructor, destructor, or type conversion before "." token

I read that a structure is the same as a class but its variables are public by default

Not exactly. A struct is a C feature. A C++ struct can have methods, but that’s rather unusual. A C struct can not.

A class without methods is a waste of time.

and I also have to download a library for this functionality.

Nonsense.

I thought the constructor could be used to initialize variables in the object at the top of the class hierarchy?

The construct can be used to initialize variables. What this has to do with “the top of the class hierarchy” or what that means is not clear.

So each Menu class object will have a myname variable which is created on initialization?

Not unless you define a variable in the class to hold the value.

Please explain what I am trying to do versus what should be done.

How can I explain what you are trying to do when you can’t?

I thought variables were just instances of objects from the data type class?

Some are. Some aren’t. It depends on the variable type.

int i = 0;

i is not an instance of a class.

Blob *pPile = new Blob();

pPile is an instance of the class Blob;

Blob heap;

heap is an object of the Blob class.

This saves the argument pin to a private variable _pin, but I want the variable to be accessable

It does, and _pin IS accessible from all member functions. Why do you think it isn’t?

I will use the struct library if I must, but would like to learn a bit about classes as well.

There is no struct library. Learning about classes is good. Stumbling along clueless isn’t. Get a C++ book. Read it. Study the examples.

So all I had to do was:

But that is wrong. myname should not be a String and it should not be public.

What does myStuff[3] return?

Pancakes with maple syrup.

The question doesn’t make sense, any more than the answer does. An array declaration doesn’t return anything.

Can I do e.g myStuff[3].name and mystuff[3].item1?

No. myStuff is an array with three elements. The elements are numbered 0, 1, and 2. You could do:

strcpy(myStuff[0].name, "PaulS");
strcpy(myStuff[1].name, "syphex");

How can I accomplish this using classes (for education only), is it a class inside a class?

class Stuff
{
    private:
       char name[10];
       someType item1;
       anotherType item2;

   public:
      Stuff( char *someName);
};

Stuff::Stuff(char *someName)
{
    strcpy(name, someName);
}

In the above line …, what is Stuff and myStuff and where are they defined?

“Stuff” is an alias for “struct stuff”. myStuff is an array of objects of type Stuff (or struct stuff). Where they are defined should be obvious.

As soon as I include menu1.item1=13;
I get: expected constructor, destructor, or type conversion before “.” token

Executable code needs to be in functions.

byte aDonut;

struct stuff
{
  char name[10];
  int item1;
  int item2;
};
typedef struct stuff Stuff;

Stuff menu1;

void setup()
{
  menu1.item1=13;
}

void loop()
{
}

results in

Binary sketch size: 678 bytes (of a 258,048 byte maximum)

when the board type is Mega.

Your right; I should pose a more general question of my layout, and how to go about implementing it.

For each "menu", I want a "name" variable for the title to flash. These "menu's" will be traversed by moving up and down on the keypad and may include an "option" menu for things like enabling autoscroll etc...

Each menu will have an arbitary number of "items", each "item" will need to store its: *starting position on the LCD screen *index in the current menu (or somehow none-indexed if none-selectable, ie a display of the average over time) *value of type int or float (possibly char)

For example, the "EC and PH" menu will need at least two items, the EC and the PH. Say I want both on the top line of my 2x16 RGB LCD keypad, with EC at the top left, and PH at the top right:

EC: PH: index: (0,0) index: (1,0) starting pos: (1,0) starting pos:(9,0)

Then when that menu is selected, the cursor for the LCD screen is set to the corresponding starting position of the current index, and draw the item and the value so EC:1.5. So now if I push the "right" button, the index will change by (+1,0), and the cursor position is set to (9,0). So I suppose to draw each item I need to cycle through an array of the index's, which points to the starting positions and values, how to arrange this using a struct is confusing for me.

Then the question is sub menu's (please don't flame me I don't want to use other people's libraries I don't need that much modulation, I want to learn). What if I want one of the "items" to be an option menu inside the EC and PH menu? That has its own "items" such as "auto dosing on/off", or "set min" and "set max" etc... I am guessing I would have to use pointers, so one of the "values" of an "item" is a pointer to another structure somehow, can this work?? But variable scope is kicking my ass atm... please help.

PaulS: There is no struct library. Learning about classes is good. Stumbling along clueless isn't. Get a C++ book. Read it. Study the examples.

Thank you for taking the time to write your lengthy response, im sorry I haven't the knowledge and experience to clearly articulate my question.And Im sorry to seem like im floundering, and maybe I am in over my head but in the end, I can read syntax and examples all I want; but as im sure you know (or may have forgotton), it is different to apply in practice for a newb.

All I could think was to make two structs, one for the items, and one for the menus. Heres what I have so far: (I know it wont compile im just asking if this is the way to go or not)

struct submenu
{
   char name[10];
   byte xpos;  //position on LCD screen
   byte ypos;
   byte xindex;
   byte yindex;
   //pointer to either menu or item member
};
typedef struct submenu EC_PH;

EC_PH EC;   //points to item.EC
EC_PH PH;  //points to item.PH

struct item
{
   char name[10];
   byte xpos; //position on LCD screen
   byte ypos;
   byte xindex;
   byte yindex;
   float value; 
};
typedef struct item EC; 
typedef struct item PH; 

EC sensorinput;
EC setpoint; 
PH sensorinput;
PH setmin;
PH setmax;

void setup(){
//import member settings 
   submenu.EC.xpos=1;
   submenu.EC.ypos=0;
//...
}

void loop(){
  submenu.EC.pointer=*item.EC
  item.EC.sensorinput.value=readsensor();
  item.EC.setpoint.value=setbyuser();
//...
}

Am I heading in the right direction at all? I know it looks like a horrible amalgamation of structs and I kind of just threw * astriskes to flag where I thought a pointer might be used. But can I refer to item.EC and submenu.EC to distinguish between the groups? How to do this with classes and inheritance properly?

I have a question about pointers in my code below:

struct item
{
   char name[10];
   byte xpos; //position on LCD screen
   byte ypos;
   byte xindex;
   byte yindex;
   float value; 
};
typedef struct item; 

item EC;
item PH;

struct menu
{
   char name[10];
   byte xpos; //position on LCD screen
   byte ypos;
   byte xindex;
   byte yindex;
   item* iaccessptr; 
   menu* maccessptr;
};
typedef struct menu EC_PH; 

EC_PH mEC;
EC_PH mPH;


void setup(){
  mEC.iaccessptr=&EC;
}

void loop(){
}

Is it bad to link structs together like this? Since the address used by the pointer changes after a while or something? I was hoping to save them to an array like this: [mainmenu][submenu][item]

Or is this bad?

Is it bad to link structs together like this?

No.

Since the address used by the pointer changes after a while or something?

No, the address of the pointer doesn't change. The address pointed to doesn't change unless you change it.

typedef struct item;

A typedef statement is used to assign an alias. The thing that you want to create an alias for is "struct item". Where is the alias?

What you have here is now a situation where struct and item mean the same thing. Not at all what you want.

PaulS: typedef struct item;

A typedef statement is used to assign an alias. The thing that you want to create an alias for is "struct item". Where is the alias?

What you have here is now a situation where struct and item mean the same thing. Not at all what you want.

In the code I posted previously where I had item alias's EC and PH the menu members could only point to an item, now they can point to other menu items as well. So I was thinking about just creating seperate items for e.g PH setmin and setmax so I don't need to create a new alias if I just want to store a single value as im not sure the two methods can coexist or if I'll have more single value items than not. I should have just commented it out.

Can I point to an alias so that only its members can be accessable? So e.g when EC_PH, only be able to choose from mEC and mPH to point to? Such as EC_PH* accesspointer;? e.g I want to have the "alias" EC_PH as the first dimension of my array [EC_PH][submenu][item]; Where submenu only contains menu members of the EC_PH alias.

I want to have the "alias" EC_PH as the first dimension of my array [EC_PH][submenu][item]; Where submenu only contains menu members of the EC_PH alias.

No, you can't. The dimension value for an array has to be an integer value. A struct is not an int.

I think you are mixing up terminology, here.

Perhaps what you need is a menu node and a submenu node. A menu node would have a list of submenu items, either as an array of fixed size or as a linked list. A submenu item would be very similar, except that it has no parent. You could, of course, get by with just one type if you include special handling for NULL as the parent of a menu item.

PaulS:

I want to have the “alias” EC_PH as the first dimension of my array [EC_PH][submenu][item]; Where submenu only contains menu members of the EC_PH alias.

No, you can’t. The dimension value for an array has to be an integer value. A struct is not an int.

I think you are mixing up terminology, here.

Perhaps what you need is a menu node and a submenu node. A menu node would have a list of submenu items, either as an array of fixed size or as a linked list. A submenu item would be very similar, except that it has no parent. You could, of course, get by with just one type if you include special handling for NULL as the parent of a menu item.

Well I know I can’t substitute it directly, it would be an int that corresponds to EC_PH. I wanted a way to check which members are part of a type, so I can point to them with an array. Really its just a way to organise groups of objects so they “belong” to something which can access them in a hierarchical way, I guess thats what linked lists are but I have no experience with them.

Are linked lists supported automatically? Again a google search seems to show I need to download a library and if so, which one do you recommend?

Again a google search seems to show I need to download a library and if so, which one do you recommend?

In this case, google is wrong. You need to develop your own linked list software.

PaulS:

Again a google search seems to show I need to download a library and if so, which one do you recommend?

In this case, google is wrong. You need to develop your own linked list software.

Looks like I need to use templates. Do I have to develop my own template library as well? All for an LCD menu?

Or can I just replace the pointer variable in the menu struct with an array of pointers? Or do I create a new structure for the “nodes”. In other words, how do I implement these “nodes” and can it be done with structs?

Looks like I need to use templates.

No, you don't.

Do I have to develop my own template library as well?

No.

All for an LCD menu?

Apparently, since you are making this far to complicated. Now that you don't seem to have a clue what you need to do, it's time to look at some of the functioning menu libraries,

Or can I just replace the pointer variable in the menu struct with an array of pointers?

I wouldn't. The pointer should point to the first node in a linked list.

In other words, how do I implement these "nodes" and can it be done with structs?

Of course it can. That's why I suggested structs and linked lists in the first place.

Sorry I think I misunderstood. I thought a "linked list" was an entirely new functionality that had to be implemented using a library. After some wikipedia I see a "node" is really just an object which points to another, which I assume can be the member of a struct.

Basic Properties

Objects, called nodes, are linked in a linear sequence

The problem is I don't want to link in a linear sequence. I need one object, to point to a group of objects, or one member of a struct to a group of members. From what I can tell, having a next and a previous pointer can only form linear links. Thats why I thought an array of pointers instead. Or do you create a seperate struct just for the nodes or something I don't understand? Sorry if I completely missed the point.

I really would like to try it for myself and not just resort to being a script kiddie. Maybe what I am trying to implement is a data tree structure.

Whats wrong with:

struct menu
{
   char name[10];
   menu* menulist[4]; //pointer to group members
   menu* menu_previous; //pointer to previous menu
   float value;
   
};

menu EC_PH;
menu EC;
menu PH;
menu PH_setmin;
menu PH_setmax;

void setup(){
  EC_PH.menulist[0]=&EC;
  EC_PH.menulist[1]=&PH;
  PH.menulist[0]=&PH_setmin;
  PH.menulist[1]=&PH_setmax;
}

void loop(){
}

Except that now each menu creates an array of size 4, though some menu's will need less. How bad is it to have unused arrays like this? Obviously trying to add a menulist throws the non-static member error, is this where I need classes?

The problem is I don't want to link in a linear sequence.

I no longer know what you want to do. A menu has a list of items. That list of items can be a linked list. The menu item is a struct that contains a pointer to the first item in the list. Each item in the list points to the next item or to NULL if the item is the last item in the list.

Frankly, I think you need to go back and re-read your first post in this thread. I believe that there is a fundamental problem. You are NOT at the point where you can create your own menu library.

PaulS:

The problem is I don’t want to link in a linear sequence.

I no longer know what you want to do. A menu has a list of items. That list of items can be a linked list. The menu item is a struct that contains a pointer to the first item in the list. Each item in the list points to the next item or to NULL if the item is the last item in the list.

Frankly, I think you need to go back and re-read your first post in this thread. I believe that there is a fundamental problem. You are NOT at the point where you can create your own menu library.

What do you mean? I clearly explained/demonstrated an example of the layout I wanted. I did research on terminology so I could better understand your unclarified reference to “nodes”, when I don’t know what nodes or linked lists are exactly except that they contain pointers. I showed you a compiling code example of what I was trying to do, it is not a full implementation, when you “select” the PH menu from the EC_PH menu it contains the two options “PH_setmin” and “PH_setmax”, obviously they would be the last items in that tree/list and would contain a list of NULL pointers and a value. If I used a class I could have a default constructor and an optional constructor for differentiating between “item” and “menu” object initialisation, allowing each “node” to have an arbitrary amount of pointers to other nodes. Not like a “list” or a “train”, but a “tree”.

What you say makes no sense.

A menu has a list of items. That list of items can be a linked list. The menu item is a struct that contains a pointer to the first item in the list. Each item in the list points to the next item or to NULL if the item is the last item in the list.

That sounds like your saying a “menu has a list of items”, “the menu item is a struct” = “menu has a list of structs, each pointing to the first struct in the list”.

Each item in the list points to the next item or to NULL if the item is the last item in the list.

Each struct in the list points to the next struct or to NULL. So now I have to create a bunch of seperate structs, and add them to a list that I can only traverse sequentually? What are the members for then?

How is this a menu? It might as well be a FIFO list. Unless you are somehow implying that in this linear “list” of “structs”, each structure contains a number of “links”. Otherwise how will the PH “menu” point/link to both PH_setmin and PH_setmax?

You may say I can’t create my own menu’s, but I have learned alot so far trying to apply the information you encouraged me to read to a practical use. The best way to learn how to code is by coding isn’t it? Everyone has to start somewhere, so what is the point in just offering discouragement? At least suggest areas where I might improve such as “read more about pointers, classes etc…” and not just a blanket statement “You dont know what your doing just give up”.

What you say makes no sense.

At the top of the IDE is a menu. It has several items in the menu - File, Edit, Sketch, Tools, and Help. That looks like a list to me.

A node (an instance of a struct) could have a name ("File", "Edit", etc.) and a list of nodes that are the sub-menu items.

The node whose name is "File" would contain a pointer to the node whose name is "Edit", which would contain a pointer to the node whose name is "Sketch.

The node whose name is "File" would ALSO contain a pointer to a node whose name is "New". The "New" node would point to the "Open" node AND to NULL (since New has no child menu).

You should be able to see that any given node points to the next item vertically or horizontally, depending on how you choose to present the menu, and it contains a pointer to the (first item in the) list to be displayed in the other direction.

If you choose not to look at how other menus are defined/implemented, I'm sorry, but I won't be able to offer any more help.

If you choose to look at other menu creation libraries, or menu techniques used in other applications, you'll see that each is nothing more than (part of) a pair of linked lists.

That's why I keep harping on linked lists. But, you keep rejecting that idea. I don't know what else to say.