строка+символ
- Войдите на сайт для отправки комментариев
возникла необходимость совершать различные операции со строковыми переменными.
пока операции с однозначно определёнными строками типа:
String text="123abc"; text=text+"32bc";
то проблем особых нет, а вот если возникает необходимость прибавить всего один символ, то начинается ужас.
text="123abc"+char(100);
судя по тому, что ничего похожего в примерах нет, это не правильно. преобразование
text="123abc"+String(char(100));
в подавляющем большинстве случаев приводит к полному зависанию дуины.
так вот всё же как правильно к строковой переменной прибавить один или несколько символов известных только по их коду?
При всём при этом задача усложняется тем, что данная строка выводится на TFT.LCD, в библиотеку которого засунута невесть какая таблица симвлов, с ASCII совпадающая только частично (например символ с кодом 1 отображается как кислый смайлик и т.п.).
http://arduino.cc/en/Reference/StringConcat
http://arduino.cc/en/Tutorial/StringAdditionOperator
именно там я и не нашел ответа: как к строке прибавить символ известный только по коду.
И поэтому решили попробовать вариант который в туториале описан в качестве примера "это работать не будет" :)
Давайте начнем немного с другого конца. Прежде чем решать задачу убедимся что мы правильную задачу решаем.
1. не уверен. всё что я о программировании знаю, это бессистемное самопознание. потому в строках, объектах и других умных словах частенько путаюсь
2. да, именно прибавлять, причём всё это происходит в процессе: строку разделить, ненужное выкинуть, нужное добавить, снова склеить в одну и тэдэ.
3. часть символов вычисляются, часть известны заранее.
данная строка выполняет роль буфера печати. т.к. вывод на экран по SPI больших массивов данных занимает довольно много времени, решил выводить инфу неспеша по таймеру (на данный момент 10 символов в секунду), чтобы высвободить временной ресурс для параллельных задач (обработка нажатий клавишь и т.п.)
в итоге строка имеет формат:
1. маркер начала, 2 координты (x;y), 3. размер шрифта, 4. текст. и снова маркер, новые координаты, шрифт, текст и т.д.
потому как очередь печати может ожидаться до 2х десятков строк (стока на экране минимальным шрифтом может влезать), то не хотелось плодить мегаколичество массивов различного назначения, а хотелось ограничится одной глобальной переменной для этих целей.
и ведь происходит печать по такому алгоритму, но не каждый раз. поиск ошибок выявил проблемы именно в строках где происходит прибавление символов к строковой переменной.
Честно говоря, даже чуть-чуть в затруднении что-же вам посоветовать.
С одной стороны объект String - проще в использовании. Особенно для новичка, всякие "разделить, выкинуть" и т.п.
С другой стороны, по сравнению с обычным string (который суть массив заканчивающийся нулевым символом) он более "тяжеловесен". Это калька с "взрослых языков на компьютере", где "килобайтом туда-сюда" рояля не играет.
Экономии на "количестве массивов" у вас не произойдет. Скорее даже "наоборот". Все эти строковые операции каждый раз будут порождать, опять-таки новый объект строку (который внутри, как ни крути, будет выделять массив под хранение данных).
Ну и еще минус String - что это, вообщем-то "ардуинистая фишка". Мало где используются, многие библиотеки портированные от "обычного Amtel" - ничего про нее не знают.
Да и, опять-таки, "отправлять строку порциями" - проще обычными строками-указателями. Отправил 20-ть байт - сместил указатель и т.п.
Вообщем-то "сделать как вы хотите" конечно можно. Вот например:
Но меня терзают сомнения что это "сильно окольный путь". "Разбирать строку" - а не проще изначально собирать ее из правильный кусков. да и вообще "все это упихивать в строку" не очень понятно зачем. Если нужно слать какие-то "байты", так байтами их и слать, SPI вроде это умеет.
Покажите весь свой скетч. Возможно вы пытаетесь выполнить "сложную работу" которую вообще не нужно делать.
это не последний вариант, в последнем ещё больше артефактов разных стадий тестов, отладок и ошибок (последний на недоступной щас машине), да и структура строки была изменена. здесь впринципе видно как я пытаюсь данные в строку запихать и как достать.
а по вашему примеру сразу вопрос (char)88 и char(88) по сишному идентичные записи?
Конечно "делов вкуса", можно идти и вашим путем. Но IMHO вы тут делаете очень много лишнией работы.
Зачем запихивать данные в строку, а потом их оттуда выпарсивать (тем более таким загадочным способом как charAt(1-2))?
С жестким кодингом "позиции параметра" - вы же потом повеситесь если вам, через пол-годика потребуется добавить еще 5-ток параметров :)
Зачем мешать "мухи и котлеты"? Данные отдельно, тексты - отдельно. Если хочется что-бы они были "жестко связанны между собой" (данные и текст) можно упихать их "в общий контекнер", только "контейнером" использовать не строку, а struct или классы. Которые как-бы для того и придуманы, что-бы разнотипные данные "объеденять" и было удобно с ними работать.
а по вашему примеру сразу вопрос (char)88 и char(88) по сишному идентичные записи?
Близкие, но не идентичный. Хотя во многих ситуациях будет работать "одинаково".
(char) - это "приведение типа". То есть на этапе компиляции жесткое указание компилятору "то что дальше считай char-ром". Как-бы некое локальное "переопределение типа". Но никаких новым переменных это не образует.
char() - это "конвертация типа". То есть у нас есть переменная какого-то типа, и а мы хотим попрбовать ее преобразовать в char
извините если сильно вмешиваюсь,eсли нужно добавлять строку к строке может воспользоваться функцией strcat(char* a,char* b)?
результат :
извините если сильно вмешиваюсь,eсли нужно добавлять строку к строке может воспользоваться функцией strcat(char* a,char* b)?
Что-вы, какое "вмешиваюсь"? Наоборот. "Молчащих в тряпочку" или приходящих на форум только когда у них проблема - и так хватает.
Да и кто-бы что не советовал - всегда есть шанс что он ошибается или не увидел более оптимальный путь. Поэтому "еще один помошник" - это всегда здорово.
Теперь по сути вашего предложения. То что вы описали - совершенно верно. Но это работа с обычными сишными строками. Это те строки которы string. А топик-стартер использует объект String - ардуиновскую "альтернативу". Предположительно более простую в использовании для новичка (хотя, лично я, тоже предпочел бы ваш подход).
А если глубже смотреть - то как раз вызывает глубокое сомнение, что "конкатенация строк" тут вообще нужна. На мой взгляд тут явная попытка использовать строки "не по назначению".
leshak, ваш примет, как и мой может печатать только одну строку. Например функция индикации времени отправляет на печать (т.е. в буфер) свои данные, через пол секунды срабатывает условие вывода данных в функции измерения температуры. соответственно буфер ещё не опусташен, печать ещё не завершена (строка времени это минимум 5 символов). В итоге данные в буфере должны накапливаться(координаты печати1+шрифт1+текст1+координаты2+шрифт2+текст2+и т.д.) и по мере печати на экран напечатанные символы должны исключаться из буфера высвобождая для будущих данных.
можно по вашему примету создать стркутуру, определить массив на базе этой структуры.. об этом я подумаю.
Но тут возникает вопрос. как происходит высвобождение памяти?
пример: берём строку
сейчас трока занимает 3 байта. если к строке прибавить.
будет 6 байт, далее
в итоге реально на железе после укорочения строки память высвободилась?
вероятно я глупые вопросы задаю, ну уж какие есть..
да, и аналогично для структуры
боюсь, что такой подход с накоплением данных в неограниченном буфере может захавать всю немногочисленную память дуинки
Согласен со всеми но выскажу свою точку зрения
Класс String замечательная штука, но мне кажется для Дуин и прочих контроллеров излишняя
Как только вы говорите String text="123"; то вы сжираете у контроллера память ну думаю минимум килобайт на подгрузку всех методов класса String обьявленных в WString.cpp
как только вы создаете второй String на 3 байта, то вы сжираете навскидку байт 200 на обьявление обьекта класса String
для Меги это в общем то не проблема, но для контроллеров с небольшим RAM я бы пользоволся обычным string с использованием обычных strcpy strcat и тд , а буфер можно иметь один, ну два, ну три
для промежуточных вычислений складываний и переписываний строк.
во, вот этот блок работает как задумывалось. смысла оптимизировать его уже нет. правильнее в будущем переписать библиотеку на экран, что бы была возможность печати по аналогичному методу