Динамический массив в структуру
- Войдите на сайт для отправки комментариев
Вс, 10/01/2021 - 20:24
Доброго всем! Подскажите как реализовать такое:
struct TMenu {
char ItemName[];
byte ItemCount;
byte SelectItem;
byte LastActiveItem, LastTopItem;
};
const TMenu Menu1 {
{
"Item1",
"Item2",
"Item3",
"Item4",
},
4, 0, 0, 0};
const TMenu Menu2 {
{
"Item1",
"Item2",
"Item3",
"Item4",
"Item5",
"Item6",
},
6, 0, 0, 0};
Мне нужны константные Menu1, Menu2, Menu3...
Но компилятор выдает:
exit status 1
too many initializers for 'char [0]'
Может как-то по другому можно создать константы Menu1, Menu2... без TMenu?
Какое-то сплошное противоречие вижу здесь.
По-русски опишите, что вы пытаетесь сотворить.
Это же очевидно. Он хочет сюда -
charItemName[], запихнуть вот это -"Item1", "Item2", "Item3", "Item4"Только вот при таком подходе я даже и не знаю с чего начать, коротко то не получится :)
хочет сюда -
charItemName[], запихнуть вот это -"Item1", "Item2", "Item3", "Item4"Верно. Я если правильно понял, так просто это сделать не получится.
Хотелось бы структуру заполнить на этапе компиляции. Ладно, буду искать другие варианты.
Можно конечно в TMenu указать максимально возможное кол-во Item'ов, но это как-то не очень...
Только вот при таком подходе я даже и не знаю с чего начать, коротко то не получится :)
Подход можно изменить, если я соображу как :)
Храните в структуре не массив, а указатель на заранее оформленный массив.
Значит в структуру запихивайте указатель на список.
Хм.... правильно я сделал:
const char *ItemName[] { "Item1", "Item2", "Item3", "Item4", }; struct TMenu { char *Items; byte ItemCount; byte SelectItem; byte LastActiveItem, LastTopItem; }; const TMenu Menu1 { *ItemName, 4, 0, 0, 0};?
Ну, почему не получится?
Замените
charItemName[];наconst char*ItemName[];и поставьте его последним элементом структуры - всего делов.struct TMenu { byte ItemCount; byte SelectItem; byte LastActiveItem, LastTopItem; const char *ItemName[]; }; const TMenu Menu1 { 4, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", } }; const TMenu Menu2 { 6, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", } };Или Вы их менять в процессе работы собираетесь?
Хм.... правильно я сделал:
Нет, конечно. Кратность указателей нарушена. Как делать правильно я Вам написал в прошлом посте.
Я так не могу... Про последнее место у меня даже мысля не шевельнулась :(
Хм.... правильно я сделал:
Нет, конечно.
Угу, хотя скомпилировать то скомпилировалось, но при обращении:
Serial.print(Menu1.ItemName[2]);
Выдал:
Ну, почему не получится?
Замените
charItemName[];наconst char*ItemName[];и поставьте его последним элементом структуры - всего делов.struct TMenu { byte ItemCount; byte SelectItem; byte LastActiveItem, LastTopItem; const char *ItemName[]; }; const TMenu Menu1 { 4, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", } }; const TMenu Menu2 { 6, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", } };Или Вы их менять в процессе работы собираетесь?
Ну ведь они же константы, их уже по определению менять нельзя. Ок. Спасибо, сейчас буду пробовать вашу идею.
Про последнее место у меня даже мысля не шевельнулась :(
А поставьте себя на место компилятора. ХЗ ж сколько ему места надо, как остальное размещать? Получится, что у разных экземпляров структуры одно и тоже поле находится на разном расстоянии от начала! А так, если переменное поле последнее, то все поля во всех структурах начинаются с одних и тех же смещений - всё разместил, а этот - как получится.
Ну ведь они же константы, их уже по определению менять нельзя.
Точно? Это Вам так кажется, никакие они не константы :-)
struct TMenu { byte ItemCount; byte SelectItem; byte LastActiveItem, LastTopItem; const char *ItemName[]; }; const TMenu Menu1 {4, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", } }; const TMenu Menu2 {6, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", } };Выдает:
Код приводите полностью. Потому, что никто не знает что у Вас там ещё написано, а судя по посту #11 Вы совсем не понимаете что пишете.
И да, кстати, чем компилируете, название, версия.
Код приводите полностью.
struct TMenu { byte ItemCount; byte SelectItem; byte LastActiveItem, LastTopItem; const char *ItemName[]; }; const TMenu Menu1 {4, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", } }; const TMenu Menu2 {6, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", } }; void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: }Весь код. Просто хотел попробовать идею...(
И да, кстати, чем компилируете, название, версия.
Ардуино IDE 1.8.10
А поставьте себя на место компилятора. ХЗ ж сколько ему места надо, как остальное размещать? Получится, что у разных экземпляров структуры одно и тоже поле находится на разном расстоянии от начала! А так, если переменное поле последнее, то все поля во всех структурах начинаются с одних и тех же смещений - всё разместил, а этот - как получится.
Это как раз очевидно. Поэтому других вариантов и не придумл.
Весь код. Просто хотел попробовать идею...(
Странно, потому, что у меня всё отлично компилируется, любуйтесь
Вы точно ничего от нас не скрываете? :-)
Хм, ну и я вроде как не вру:
Как вставить картинку? (
Более того, не только компилируется, но и работает.
Вот такой код
struct TMenu { byte ItemCount; byte SelectItem; byte LastActiveItem, LastTopItem; const char *ItemName[]; }; const TMenu Menu1 {4, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4" } }; const TMenu Menu2 {6, 0, 0, 0, { "Item1", "Item2", "Item3", "Item4", "Item5", "Item6" } }; void setup(void) { Serial.begin(57600); Serial.println("Start!!!"); Serial.println(Menu2.ItemName[0]); Serial.println(Menu2.ItemName[1]); Serial.println(Menu2.ItemName[2]); Serial.println(Menu2.ItemName[3]); } void loop(void) {}выдаёт в монитор порта вот это
Как видите, всё правильно.
Правда у меня IDE 1.8.12. Попробуйте апгрейдироваться, чем чёрт не шутит.
Для ESPшек не компилируется.
struct TMenu { byte ItemCount; byte SelectItem; byte LastActiveItem; byte LastTopItem; const char **ItemName; }; const char *forMenu1[]={ "Item1", "Item2", "Item3", "Item4"}; const char *forMenu2[]={ "Item1", "Item2", "Item3", "Item4", "Item5", "Item6"}; const TMenu Menu1 {4, 0, 0, 0, forMenu1}; const TMenu Menu2 {6, 0, 0, 0, forMenu2}; void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: }IDE 1.8.9
Вы точно ничего от нас не скрываете? :-)
Нет, просто не могу (не умею) вставить картинку сюда :(
Более того, не только компилируется, но и работает.
Как видите, всё правильно.
Правда у меня IDE 1.8.12. Попробуйте апгрейдироваться, чем чёрт не шутит.
Ну фик его знает.... может попробовать обновить IDE. Вон выше тоже не компилится, но версия ИДЕ еще меньше чем у меня....
Для ESPшек не компилируется.
struct TMenu { byte ItemCount; byte SelectItem; byte LastActiveItem; byte LastTopItem; const char **ItemName; }; const char *forMenu1[]={ "Item1", "Item2", "Item3", "Item4"}; const char *forMenu2[]={ "Item1", "Item2", "Item3", "Item4", "Item5", "Item6"}; const TMenu Menu1 {4, 0, 0, 0, forMenu1}; const TMenu Menu2 {6, 0, 0, 0, forMenu2}; void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: }IDE 1.8.9
Не вижу проблемы. В IDE нормально всё. А чего говорит?
А вот вариант из #25 скомпилировался и работает.
Не вижу проблемы. В IDE нормально всё. А чего говорит?
Скорее всего было сказано про Ваш вариант кода
AsNik, так я и говорю, попробуйте апгрейдироваться.
У меня же и компилируется и работает нормально, сами видите.
Только,, не советовал бы я Вам такие извращения использовать. Прикиньте, что там, например, sizeof будет выдавать.
AsNik, так я и говорю, попробуйте апгрейдироваться.
У меня же и компилируется и работает нормально, сами видите.
Только,, не советовал бы я Вам такие извращения использовать. Прикиньте, что там, например, sizeof будет выдавать.
:)))) Но работает же :)
Только,, не советовал бы я Вам такие извращения использовать.
Вот. А я хотел бы чтоб без сюрпризов. Так как Вы уже поняли, что программист я не очень. Это мое хобби...
Поэтому много тонкостей не знаю.
А что с вариантом из 25? Те-же вроде грабли могут быть, верно же? Если нет ничего более менее стабильного варианта, буду наверное пока 25 пробовать.... Спасибо.
sizeof , при всей простоте требует аккуратного обращения. Часто вы его используете ? Есть правильные операторы для этого, честные - - strlen например.
Я вот, поему то не боюсь указатель на массив указателей :)
А что с вариантом из 25? Те-же вроде грабли могут быть, верно же?
Хотя там подставляются константы через указатель на указатель.... И вроде должно на этапе компиляции все размеры быть известны...
Вроде нормально все.
void setup() { Serial.begin(115200); Serial.println("Start!!!"); Serial.println(Menu1.ItemName[0]); Serial.println(sizeof(forMenu1[0])); Serial.println(sizeof(Menu1.ItemName[0])); Serial.println(strlen(forMenu1[0])); Serial.println(strlen(Menu1.ItemName[0])); }Скажите еще вот что. Если переделать немного так:
Это пока все строки в массиве одного размера.
Это не правильно ни разу.
А вот список это правильное решение, я его в самом начале предложил.
Поищите linkedList
Скажите еще вот что. Если переделать немного так:
Сам подход неправильный.
Меня делается списком. Тогда Вам не нужны эти извращения и ходить по нему удобнее.
Я как-то приводил рыбу как это делать и там же в теме вроде и какие-то вопросы были, я отвечал, посмотрите. Лучше сделайте списком по образу и подобию того примера.
Не совсем понял, я в каждой константе использую свой массив...
Просто если добавить/убрать пункт в массиве, уже не нужно изменять это в const TMenu MenuN {..}
В Micromenu все эти извращения уже оформлены из идеи в работающий исходник.
Я как-то приводил рыбу как это делать и
Если честно, то я видел в интернете и такое меню и еще много подобных вариантов. Но с моим уровнем знаний, я не осилю пока это.... У меня немного не совсем то меню, какое вы думаете... Там будет и меню и экраны как бы одно целое. В общем это не рассказать словами. Хотя я уверен, что вы мою задачу сделали бы по другому, но я попробую пока так.
Скажите еще вот что. Если переделать немного так:
Это не правильно ни разу.
Наврал. В данном случае, если код из #25, как раз все будет правильно.
Наврал. Тут как раз все будет правильно.
А я уж было поник)
Это по другим "стандартным меню" и linkedList. Вот к примеру если у меня будет такой список на экране:
Name Enable State
Item1 <On> <Off>
Item2 <On> <On>
Item3 <Off>
>Item4 <On> <Off>
Item5 <Off>
Item6 <On> <Off>
(ну соответственно будут видны только 4 строки на LCD2004)
Причем управляться будет все одним энкодером с кнопкой. Например короткое нажатие на пункте мы переходим на экран ItemN, а при удержании меняем последнее (State) значение в строке <On-Off-On> с учетом Enable. А вот Enable меняется в другом месте...
А у другого меню свои "заморочки".... Как то так.
Я сейчас внимательно почитал "рыбу" из #40 и думаю в методе show можно отрисовать строку как мне нужно, а обработать короткое или длинное нажатие кнопки на элементе тоже можно. Вообще теоретически я там разобрался в обоих примерах. Но использование некоторых "приемов" типа
for(SMenuItem * ptr = children; ptr; ptr = ptr->next) {немного затрудняет в редактировании "под себя"Вообще очень интересно было скомпилировать эту рыбу. Все прокомментировано. И даже с указателями, которых я не очень понимаю, в данных примерах я вроде разобрался. И вообще, помимо меню я там много другого узнал.... Спасибо от души!
Читайте по теме двусвязные списки на Си, например: https://prog-cpp.ru/data-dls/
А разве подобный массив char'ов не двумерный ?
По мне так его нужно объявлять как:
char itemName[][];
с точным указанием размера хотя бы правого члена, если есть список инициализаторов.
В общем это не рассказать словами.
То, что нельзя рассказать словами, невозможно и запрограммировать.