I'm new to C++. How to make a menu without if() {} else {}
& switch() case
?
I made a menu on an array, but for some reason it doesn't compile. How to correct it?
typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);
class Menu {
public:
Menu() {
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
}
static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
cbDisplay = display;
cbSetTime = setTime;
cbSetAlarms = setAlarm;
alarmHours = alarmHours;
alarmMinutes = alarmMinutes;
cbSetAlarms(alarmHours, alarmMinutes);
}
// Used for menu.UpDown(dir) callback
static void UpDown(int8_t direction) {
updownFn(direction);
}
// Used for menu.Tab() callback
static void Tab() {
updownFnNum++;
updownFn = updownFns[updownFnNum % 5];
}
private:
static void updownNone(int8_t direction) { }
static void updownAlarmHours(int8_t direction) {
alarmHours += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownAlarmMinutes(int8_t direction) {
alarmMinutes += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownTimeHours(int8_t direction) {
timeHours += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static void updownTimeMinutes(int8_t direction) {
timeMinutes += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
static uint8_t updownFnNum; // 0-None, 1-AlarmH, 2-AlarmM, 3-TimeH, 4-TimeM
static cbd cbDisplay;
static cbt cbSetTime;
static cba cbSetAlarms;
static MenuFunction updownFns[5];
static MenuFunction updownFn;
};
uint8_t Menu::alarmHours = 0;
uint8_t Menu::alarmMinutes = 0;
uint8_t Menu::timeHours = 0;
uint8_t Menu::timeMinutes = 0;
uint8_t Menu::updownFnNum = 0;
cbd Menu::cbDisplay = NULL;
cbt Menu::cbSetTime = NULL;
cba Menu::cbSetAlarms = NULL;
MenuFunction Menu::updownFn = NULL;
Output:
In file included from app.ino:7:0:
menu.h: In constructor 'Menu::Menu()':
menu.h:9:109: error: cannot convert '<brace-enclosed initializer list>' to 'MenuFunction {aka void (*)(signed char)}' in assignment
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
Thank you!
2 Answers 2
The C++ language makes a distinction between an initialization and an
assignment. An initialization is the initial value you give to a
variable at the point where you are defining it. An assignment is the
use of the =
operator anywhere else. Also, the language does not allow
assigning the contents of an array as a whole. You can initialize an
array though.
This:
Menu() {
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes,
updownTimeHours, updownTimeMinutes};
}
is an attempt to assign a whole array. It cannot work. If you want to initialize the array, do it at the point where it is being defined, outside of the class definition:
MenuFunction Menu::updownFns[5] = {updownNone, updownAlarmHours,
updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
First, your updownFns[5]
can be contain 5 variable. And the last variable index can be 4 not 5 because of array index starts from 0.
Here is the code :
typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);
class Menu {
public:
Menu() {
updownFns[0] = updownNone;
updownFns[1] = updownAlarmHours;
updownFns[2] = updownAlarmMinutes;
updownFns[3] = updownTimeHours;
updownFns[4] = updownTimeMinutes;
}
static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
cbDisplay = display;
cbSetTime = setTime;
cbSetAlarms = setAlarm;
alarmHours = alarmHours;
alarmMinutes = alarmMinutes;
cbSetAlarms(alarmHours, alarmMinutes);
}
// Used for menu.UpDown(dir) callback
static void UpDown(int8_t direction) {
updownFn(direction);
}
// Used for menu.Tab() callback
static void Tab() {
updownFnNum++;
updownFn = updownFns[updownFnNum % 5];
}
private:
static void updownNone(int8_t direction) { }
static void updownAlarmHours(int8_t direction) {
alarmHours += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownAlarmMinutes(int8_t direction) {
alarmMinutes += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownTimeHours(int8_t direction) {
timeHours += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static void updownTimeMinutes(int8_t direction) {
timeMinutes += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
static uint8_t updownFnNum; // 0-None, 1-AlarmH, 2-AlarmM, 3-TimeH, 4-TimeM
static cbd cbDisplay;
static cbt cbSetTime;
static cba cbSetAlarms;
static MenuFunction updownFns[5];
static MenuFunction updownFn;
};
uint8_t Menu::alarmHours = 0;
uint8_t Menu::alarmMinutes = 0;
uint8_t Menu::timeHours = 0;
uint8_t Menu::timeMinutes = 0;
uint8_t Menu::updownFnNum = 0;
cbd Menu::cbDisplay = NULL;
cbt Menu::cbSetTime = NULL;
cba Menu::cbSetAlarms = NULL;
MenuFunction Menu::updownFn = NULL;
// MenuFunction Menu::updownFns = {};
But still code is not correct. if you look at the signature of this definition
typedef void (*cba)(uint8_t, uint8_t, uint8_t);
it takes 3 parameters. But inside the code, you give 2 parameter to the function
cbSetAlarms(alarmHours, alarmMinutes)
-
It's a typo, I've corrected it. But the error is the same.
typedef void (*cba)(uint8_t, uint8_t);
Andre– Andre2022年10月26日 07:48:45 +00:00Commented Oct 26, 2022 at 7:48 -
It's not typo, typo means something different. if you change typedef void (*cba)(uint8_t, uint8_t, uint8_t); to typedef void (*cba)(uint8_t, uint8_t); Code wil compile without errorsembeddedstack– embeddedstack2022年10月26日 07:50:34 +00:00Commented Oct 26, 2022 at 7:50
-
updownFns[0] = updownNone;
It gave: /tmp/cc3MHoSt.ltrans0.ltrans.o: In functionglobal constructors keyed to 65535_0_app.ino.cpp.o.4201': <artificial>:(.text.startup+0x144): undefined reference to
Menu::updownFns' <artificial>:(.text.startup+0x148): undefined reference to `Menu::updownFns' collect2: error: ld returned 1 exit status exit status 1 Error compiling for board Arduino Pro or Pro Mini.Andre– Andre2022年10月26日 07:51:45 +00:00Commented Oct 26, 2022 at 7:51 -
1There are several issue with your code. You can use like this Remove initilization from ctor and init static variable outside. MenuFunction Menu::updownFns[] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes }; But when you want to use updownFns it will give errors because of the function is private within this context also.embeddedstack– embeddedstack2022年10月26日 08:03:17 +00:00Commented Oct 26, 2022 at 8:03
-
I initialized the array outside of the class definition. No errors. I then used
updownFns
and no errors.Andre– Andre2022年10月26日 09:17:46 +00:00Commented Oct 26, 2022 at 9:17