Добавление строк в массив
- Войдите на сайт для отправки комментариев
Ср, 16/07/2014 - 18:57
День добрый. Есть массив строк:
char* strings[] = {}
Можно ли в него, динамически, добавлять строки? При попытке сделать так:
strings[0] = "test";
Ругается, что не может привести string к char*. Если же я воспользуюсь такой конструкцией:
char strings[2]; strings[1] = "test";
То всё ок.
Все просто:
можно сделать как предложл San4es,но гораздо правильнее использовать динамические массивы
во вторых он предлагает использовать класс String,что скажеться на памяти программы.
если же в ходе дейсвия нужно менять размер массива то такой способ вам не подойдет ,нужно изначьлно указывать компилятору что вы хотите массив в динамической области памяти :
для изменения резмера массива используеться :
в случае с переменной типа char ,для присвоения можно пользоваться обычным '=' :
для присвоения значений типа 'строк' используеться метод strcpy();
То что хочет автор это двухмерный массив, в одном измерении хранятся указатели на строки, во втором сами строки (массив символов). Т.е. Это массив указателей на массивы
организовать это проще статически. Статическое распределение контролируется на этапе компиляции, помогает избежать ошибок. К тому же динамическое выделение в итоге может потребовать больше места во флэш и немного больше в ram
Так ли уж нужна динамика? Почему бы не выделить статически нужное пространство? Многие задачи это позволяют
Если автор расскажет больше, возможно и ответы будут более адекватные.
Часто бывает, что не факт, что автор понимает, как правильно реализовать задачу и ставит вопрос о своем, возможно, не совсем правильном решении задачи.
День добрый.
Моя цель - разбить строку, по какому-нибудь разделителю (пусть это будет пробел), затем каждый кусок этой строки поместить в массив. А сам массив передать в другую функцию, где исходя из размера этого массива алгоритм может варьироваться.
Непосредственно я хочу получать с serial'а команду, передавать нужному обработчику, который будет выполнять те или иные действия.
В идеале, первым параметром в строке должно идти имя обработчика. Сам обработчик я хотел бы вызывать "магическим" методом. Т.е. использовать первый кусок строки, как имя функции. Можно ли так сделать? Т.е. если не привязываться к синтаксису какого-либо языка, попробую привести "асбтрактный" пример:
Допустим на вход передана строка 'cam record move'. В результате разделения получаем массив:
0 => "cam",
1 => "record",
2 => "move"
В итоге мы вызываем функцию, куда параметром передаем массив:
cam({cam, record, move});
mixail844 вообщем-то теорию изложил. только "на практике", без кровавого опыта (и даже с ним) от всей динамичности - лучше отказатся. Если есть хоть какая-то возможность.
Оно то и когда нормальные дебагер есть, ошибки с выделением/освобождением памяти - практически неизбежны и одни из самых трудно-уловимых, а уж тут-то, когда у нас только Serial.println можно будет головой рохнутся когда "память потечет".
Да еще нужно будет предусматривать "а что делать когда память закончится" (и надеятся что в этот же момент у нас стек/куча тоже не переполнятся).
Да еще "дефрагментация свободной памяти" и проч. прелести
Вообщем IMHO гораздо проще выделить массив с небольшим запасом. И просто завести какую-то переменную счетчик, в которую вы сами руками отмечаете "сколько ячеек в нем уже занято". Заняли ячейку - увеличили счетчик. Нужно освободить (последнюю) - уменьшили его на единицу.
Вы думаете почему, скажем старые мобилки в своих спецификаях имеют "телефонная книга на 200 номеров" (хотя памяти может быть и больше). Вот поэтому :) Потому что "так проще в реализации и безопастней".
Лично я, на ардуине, использую динамическое выделение, только когда, в принципе на момент компиляции уже известно сколько памяти потребуется. Просто "известно это в другом месте" и "выделение происходит только один раз, при старте скетча" (вообщем практически не отличается от статического выделения).
Скажем пишу какой-нибудь класс "обработчик кнопок". И не хочу его заранее ограничивать сколько кнопок он умеет обрабатывать. Массив пинов - я передам ему в конструктор. Внутри мне требуется для обработки кнопок, еще несколько массивов "прошлое состояние кнопки, когда нажимали и т.п.". Вот эти массивы и я выделю динамически. Один раз. Но дефакто, когда я буду инициализировать класс "обработчик кнопок" я ему точно скажу "сколько нужно выделить", еще в момент компиляции я знаю "сколько же у меня кнопок", на ходу они появляться/исчезать - не будут.
Я ошибся или вы хотите парсить json? Поищите - вообщем-то уже есть либы для этого.
string.split(' ') - неа :)
гуглите фунцию strok()
Т.е. использовать первый кусок строки, как имя функции.
не получится. Похоже вы явно из javascript пришли к нам. В скомпилированной прошивке никаких именно фукнций нет. И, в отличие от java и C# никаких reflection тоже нет.
Так что запускать какую-то фукнцию, по текстовой строке, типа можно только примерно так:
И если вы потом, захотите что-бы и какая-то myFunc2 запускалась, по команде, то "просто ее написать" - не получится. Опять нужно будет "в обработчке", для нее дописывать вызов
и д.т.
Можно это будет конечно, как-то свернуть с использованием структур-массивов, но все равно каждую функцию которую "можно вызывать", прийдется "ручками регистрировать".
P.S. А еще посмотрите на фунцию sscanf(), тоже при разборе может пригодится. Только нельзя тупо смотреть в справочник по C/C++ и пользвоать эти функции. Нужно перепроверять. В Arduino часть из них реализована в "урезанном варианте". Скажем sprint() по справочнику умеет и с целыми и с вещественными числами работать, а в ардуино-вариате только с целыми. Вещественные - выкинуты для экономии.
Допустим на вход передана строка 'cam record move'. В результате разделения получаем массив:
0 => "cam",
1 => "record",
2 => "move"
В итоге мы вызываем функцию, куда параметром передаем массив:
cam({cam, record, move});
для этого нужно всего лишь такая конструкция :
допустим вы получили некий массив из Serial и разбили его при помощи strtok(); на масив tempBuff[] = {"cam","record","move"};
далее вам просто нужно знать какая функция нужна для запуска :
поскольку функция сравнения строк ( strcmp(); ) может вернут 3 значения : 0 - в случае если строки равны, 1 - если левая строка лексиграфически больше правой, и -1 если наоборот. то в случае равенства строк,для "истины" в констукции if,необходимо использовать логическе НЕ
по той же причине ,возвращаемых значениях функсии strcmp() ,использовать оператор switch - case, вряд ли получиться.
Я бы так делал задачу. Во первых список функций у нас ограничен и известен на момент компиляции. Поэтому я бы сделал массив статических строк прямо во флэш (PROGMEM) и в этом массиве задал бы полный перечень поддерживаемых функций.
Далее, при парсинге входящей строки я бы делал поиск строки по своему массиву во флэш. Найдя там команду получаю индекс комманды в моем массиве. Этот индекс дальше использую или в switch для вызова функции или делая выборку из другого массива во флэш где заданы адреса функций с тем же интекслм что и команды.
Такое же преобразование параметров функции из текста в число(индекс) я бы сделал до вызова команды. Тогда от текста мы полностью избавляемся на момент парсинга и до вызова других функций
всю тему не читал, изв.
>> Найдя там команду получаю индекс комманды в моем массиве. Этот индекс дальше использую или в switch для вызова функции или делая выборку из другого массива во флэш где заданы адреса функций с тем же интекслм что и команды.
я делал примерно также:
1. с десяток функций (обработчиков сообщений) с одинаковым прототипом:
bool MSG_PING_REQ_handler()
{
...
return true;
}
2. массив указателей на обработчики
bool (*handlers[]) () = { 0, MSG_PING_REQ_handler, MSG_ENH_PING_START_handler, MSG_ENH_PING_TEST_handler, MSG_ENH_PING_END_handler, MSG_ENH_PING_REQUEST_handler, MSG_GET_VCC_REQ_handler, MSG_GET_TEMP_REQ_handler, MSG_GET_FREE_RAM_REQ_handler};
3. из входящего сообщения получаю его тип (byte reqMsgType). Тип равен номеру обработчика в массиве.
4. вызываю обработчик, получаю результат
bool result = (*handlers[reqMsgType]) ();
5. плюс: отсутствуют лишние if-ы и case-s
прочитал тут: http://stackoverflow.com/questions/252748/how-can-i-use-an-array-of-func...