Динамический массив из String
- Войдите на сайт для отправки комментариев
Вс, 21/10/2018 - 21:10
Доброго времени суток и плодотворгого творчества!
Подскажите как создавать динамически массив элементов из типа String. Ниже я привел упрощенный код, где попытался показать суть проблему нежели реализацию самой задачи.
Значит с помощью malloc я пытаюсь создать массив sname из n элементов, потом получая значения в переменной name_buf записать в созданный массив sname. После всего этого получить результат на мониторе. Укажите мне на ошибки и как это исправить
... String *sname; byte n; array_name_key(sname,n); ... void array_name_key(String *sname, byte n) { // получаю заранее неизвестное количество элементов массива n n=(какое-то тут количество); sname = (String*) malloc(n * sizeof(String[28])); String name_buf; // Для составления строки byte size_s; // Для длины каждой строки size_s=(длина от 2 до 28); for(byte z=0;z<n;z++) { for(byte i=0;i<28;i++) { if(size_s>i)name_buf+=char((символ)[i]); } sname[z]=name_buf; } //Проверка работы for(int i=0; i<n; i++) { Serial.print(sname[i]); Serial.println(" "); } }
Если требуется все же углубиться в нормальный код, то он ниже
void setup() { ... String *sname; byte *key[8]; byte n; byte *addr; array_name_key(sname,key,n,addr); ... } void array_name_key(String *sname, byte **key, byte n, byte *addr) { n=0; byte *k; bool a=true; for(int m=0;m<511;) { a=EEPROM.read(m); if(a==true){m=m+38;} else { n++; m=m+38; } } //Выше отработалось нормально /* for(byte x = 0; x < 14; x++) sname[x] = (String*) malloc(n * sizeof(String));*/ sname = (String*) malloc(n * sizeof(String[28])); String name_buf; for(byte x = 0; x < 8; x++) key[x] = (byte*) malloc(n * sizeof(byte)); addr = (byte*) malloc(n * sizeof(byte)); byte z=0; byte size_s=0; for(int m=0;m<511;) { name_buf=""; a=EEPROM.read(m); if(a==true){m=m+38;} else { m++; size_s=EEPROM.read(m); m=m+2; addr[z]=m; for(byte i=0;i<28;i++) { if(size_s>i)name_buf+=char(EEPROM.read(i+m)); } sname[z]=name_buf; Serial.println(sname[z]); m=m+27; m++; for (byte x = 0; x < 8; x++) { EEPROM.get(m,key[x][z]); m=m+1; } z++; } } //Serial.println(n); //Проверка работы for(int i=0; i<n; i++) { Serial.print(sname[i]); Serial.println(" "); for(int j=0; j<8; j++){Serial.print(key[j][i], HEX);Serial.print(":");} Serial.println(""); } }
Вы бы еще русскими словами написали - просто тренируетесь или какую-то полезную задачу пытаетесь решить? В этих ваших a, m, x, z сам черт ногу сломит. Зачем вот вам String, если фактически делаете char[29]?
Я тренируюсь на полезной задаче.
К данными переменными у меня нет вопросов и проблема не в них.
Со String(ом) просто удобнее, но cделать я патаюсь String[i] (размер каждого стринга по 28), либо если char, то char[28][i]
Не понимаю как это можно применить в данной задаче... Понятно что String* s = new String(); создает элемент, но я не понимаю как тогда к нему обращаться, если мне нужно будет более чем 1 элемент. Если есть пример какой-нибудь, хотя бы из любой задачи, скиньте кусок кода, плиз
Не понимаю как это можно применить в данной задаче... Понятно что String* s = new String(); создает элемент, но я не понимаю как тогда к нему обращаться, если мне нужно будет более чем 1 элемент. Если есть пример какой-нибудь, хотя бы из любой задачи, скиньте кусок кода, плиз
В примере выше - массив из 20 элементов, созданных динамически. Если надо динамически менять размерность массива, то:
Ну и не забывать чистить всё правильно.
К данными переменными у меня нет вопросов и проблема не в них.
Так код вы нам предлагаете читать. Прочитать, разобраться в вашей идее, потом еще показать, где вы допустили ошибку. Не пытались никогда с закрытыми глазами незнакомый фотоаппарат разбирать и собирать? Ощущения примерно такие же - хер его знает, должен этот винтик тут стоять или его надо с соседним поменять.
a - булевый тип. При чении из памяти EEPROM, если получаю true, то блок памяти занят, false блок памяти свободно. Это условные обозначения, чтобы считать тот блок помяти, который заполнен полезными данными.
m - адрес ячейки памяти EEPROM
x - переменная для цикла чтобы перебрать массив
z - счетчик, показывающий сколько раз мы прошли цикл
Из всех переменных что спрашивались, важен только счетчик z.
Код что я выложил 2й, это просто более полный, а сама проблема отображена в 1м коде
Что я не так сделал?
Как применить delete тоже не понимаю
Что я не так сделал?
Как применить delete тоже не понимаю
1. Всё не так сделали;
2. Без обид, но - почитайте основы С++ - там как раз написано и про new/delete. Пересказ учебника - такое себе занятие.
Вам что надо? Прочитать из EEPROM сохранённые там строки в массив строк? Это делается сильно проще, чем у вас написано. Однако - всегда есть нюансы, например - может быть заранее неизвестно кол-во сохранённых строк. В общем случае это делается алгоритмически примерно так:
Код - навскидку писан, без претензий.
Сделал по той схеме что скинули, но что-то не понятно. Мне нужно вытащить за приделы функции полученный массив со всеми элементами. Может опять что не так?
Я пока удалил входные параметры функции для тього, чтобы разобраться в логике и в работе того алгоритмя, что скинули выше.
Не понятно почему в переменной array NULL+ch? NULL+ch != ch, уже проверял. Как вообще работать с delete мне понятно, мне не понятно как потом после удаления работать с полученными значениями. Мне та надо в функции создать массив и заполнить этот массив значениями, а потом за пределами функции с ними работать.
Пока что должным образом у меня не работает....
Мне та надо в функции создать массив и заполнить этот массив значениями, а потом за пределами функции с ними работать.
Почитайте, что такое "область видимости" в языке Си. Любая переменная или структура, например массив, созданная внутри функции - только внутри этой функции и видна. Более того, если переменная не обьявлена static. то при каждом выходе из функции она уничтожается, а при следующем входе в функцию создается вновь.
Чтобы работать с массивом снаружи - его нужно и создавать "снаружи", например обьявить глобальным.
Как вообще работать с delete мне понятно
Нет, непонятно. У вас утечка памяти в строке 55. Читайте основы языка, как минимум. Иначе это - разговор немого с глухим.
Чтобы работать с массивом снаружи - его нужно и создавать "снаружи", например обьявить глобальным.
С областью видимости все понятно, но вот как быть тогда с динамическим массивом?
Извращаться надо. Ардуина - это вам не Big PC, тут подобные вещи только через .... аккуратное программирование. Будете со своим динамическим массивом в push/pop играть - всю память мигом растеряете. Сборщика памяти тут нет, устранять дырки в куче никто не станет.
С областью видимости все понятно, но вот как быть тогда с динамическим массивом?
Правильно создавать/освобождать. Примеры - вам не помогут: вы начинаете бездумно оттуда копировать, в надежде, что оно само по себе заработает. С++ - это даже не пистолет, это - берданка, и выстрелить из такой берданки себе в ногу - как два пальца. Чем вы сейчас героически и занимаетесь вместо того, чтобы взять учебник по С++ - и почитать про динамическое выделение и освобождение памяти.
Сколько бы вам примеров ни давали - без понимания основ всё сведётся к тупой копипасте. С заведомо известным плачевным результатом на выходе.
Извращаться надо. Ардуина - это вам не Big PC, тут подобные вещи только через .... аккуратное программирование. Будете со своим динамическим массивом в push/pop играть - всю память мигом растеряете. Сборщика памяти тут нет, устранять дырки в куче никто не станет.
Я так понимаю, что полноценно динамических массивов тут быть вообще не может. Бездумных, в смысле. Потому как некое максимальное значение мы должны заранее предусмотреть. Ну, по крайней мере, я это так для себя понял, когда разбирался. Ибо тоже избалован Big PC. :(
Я так понимаю, что полноценно динамических массивов тут быть вообще не может. Бездумных, в смысле. Потому как некое максимальное значение мы должны заранее предусмотреть. Ну, по крайней мере, я это так для себя понял, когда разбирался. Ибо тоже избалован Big PC. :(
Чой-то? Всё есть в соответствии со стандартом С++. Можно выделять память, сколько заблагорассудится, пока менеджер памяти - может выделить запрошенный кусок. Когда не сможет - вернёт NULL, эту ситуацию, ессно, надо отрабатывать в программе.
Конечно, оперативки не вагон, но жить можно. Постоянно юзаю динамические массивы (да тот же String - внутри держит динамический массив) - и не вижу в этом никаких недостатков. Кроме, конечно, ограниченного размера оперативки.
Чой-то? Всё есть в соответствии со стандартом С++. Можно выделять память, сколько заблагорассудится, пока менеджер памяти - может выделить запрошенный кусок. Когда не сможет - вернёт NULL, эту ситуацию, ессно, надо отрабатывать в программе.
Я о том и говорю, что бездумно не получится. Надо все контролировать. Некоторые вещи, на которые закрывают глаза большие машины и мощные компиляторы, тут неприемлимы. Как в старые, добрые времена. :)
А что там будет, если типа такого устраивать:
Дырки же в куче понаделаются?
А что там будет, если типа такого устраивать:
Дырки же в куче понаделаются?
Могут и наделаться, конечно - всё зависит "от". Бейсбольной битой если вломить - сломается вообще всё :)
Мда... жаль толкогого ответа, кроме критики, так и не получил... Надеюсь на последний мой вопрос получу хотя бы толковый ответ.
Вопрос вот в чем, то что я получил вызывая функцию read_upd_struct мне нужно использовать все время работы устройства. При вызове данную функцию повторно, хочу как бы обновить массив данных. Для этого я сначала удаляю весь созданный массив динамически, а потом его снова создаю. Вроде утечек памяти я пока не наблюдаю. Вот мне бы хотелось спросить у знающих людей позволительно ли использования такого способа или же подход неграммотный, по хорошему надо как-то по другому?
Мда... жаль толкогого ответа, кроме критики, так и не получил...
Если вы считаете совет "читать учебник" критикой - тогда вообще никаких ответов не будет.