преобразование типов данных
- Войдите на сайт для отправки комментариев
Вс, 25/03/2012 - 20:23
Здравствуйте. Встала проблемма6 с компа приходят данные -строка с цифрами , которые разделены условными символами. Например "a -7897,15 b 1577,58 b 85979,89 c" a-начало c - конец b-разделитель.
Встала проблемма вытащить эти цифры из сторки. Проблемму я вообщем то решил, но код огромынй, и у меня есть подозрения, что я изобрел велосипед. Вот приммер кода.
String stroka="a-223.850b20,1744c"; String chislo=""; String zel=""; String drob=""; int zel_int; int drob_int; float drob_fl; float rezultat; char simw; void setup() { Serial.begin(115200); } void loop(){ int i=0; //Ищем позицию разделителя simw=stroka[i]; while (simw!='b'){ i++; simw=stroka[i]; } //Обрезаем строку chislo=stroka.substring(1,i); //Аналогично разбиваем число на целое и дробные части i=0; simw=chislo[i]; while ((simw!='.')&&(simw!=',')){ i++; simw=chislo[i]; } //объединяем целыую и дробную части zel=chislo.substring(0,i); drob=chislo.substring(i+1,i+3); zel_int=zel.toInt(); drob_int=drob.toInt(); drob_fl=(float(drob_int))/100; //проверяем знаки if(zel>0){ rezultat=zel_int+drob_fl; } else { rezultat=zel_int-drob_fl; } while(1){ Serial.println(rezultat); delay(2000); }
Подскажите, есть ли более аккуратные и оригинальные решения этой проблеммы? как грамотно организовать обменн данными? В моей задаче передаётся 5-6 чисел(отрицательные и дробные), в известном порядке
http://cpp.com.ru/shildt_spr_po_c/13/scanf.html
у меня не получилсоь разобраться с этой функцией.
откуда она считывает? записывает она я так понял в аргументы, которые прописываешь?
можно пример?
Не совсем в тему, но у объекта String есть фукция привидения toInt():
http://arduino.cc/en/Reference/StringToInt
Мне здорово помогла!
имхо, scanf тут не подходит - количество токенов переменное. лучше strtok
к примеру
только подправьте код в зависимости от количества знаков после запятой.
и еще учтите, что strtok кромсает оригинальную строку
Я бы лучше работал с объектом String (а не с массивом char) - у него куча полезных методов есть: http://arduino.cc/en/Reference/StringObject
Я бы посоветовал вообще не связываться с float!!! Работайте с unsigned long int и увидите насколько меньше станет проблем. дробные доли держите в уме и при крайней необходимости разделите на 10^x.
Согласен, мой дуино-опыт небольшой, но я уже понял геморность данного типа данных...
геморность, как и разруха - она не в типах данных, она в головах....
Реально - если ты, умник будешь сравнивать два одинаковых числа типа float то не факт, что они будут равны!!! Об этом куча статей и на своём опыте я лично в этом убедился. И появляется куча проблем. Например - ds18b20 - Если будешь получать температуру в float, то забив уставку на включения чего либо - не факт что оно включится - это факт, а ты тут глаголишь поносом!
что ж , ты только подтвердил предположение о разрухе в головах.....
Первое что выдал гугл. http://radiokot.ru/forum/viewtopic.php?f=20&t=68696
Я аргументирую своё мнение. Ты - просто звездишь, как нытик, оставшийся без конфеты. Ну вот и всё. С редкими исчезающими видами вонючих троллей в этой теме больше не общаюсь.
Когда ж вы тролли все представитесь???
что ж ты так убиваешься, ты ж так не убьешься, иди подучись как надо :)
какое мнение-то? одни вопли про про то, что тебе не нравится флоат. ну не умеешь - так и не пользуйся, ради бога, никто тебя не заставляет. но не навязывай свою ограниченность другим
сравнивать два одинаковых числа типа float то не факт, что они будут равны!!!
Как сравнить длины двух карандашей зная их длину в сантиметрах (в типе float) ? Нужно лишь договориться, что разность длин меньше миллиметра ничтожна.
bababababa, чтобы не мучиться со строками, передавайте данные в виде чисел - байтиков. Чтобы не изобретать велосипед, почитайте о протоколе firmata.
http://bigbarrel.ru/%D0%BA%D0%BE%D0%BD%D0%B2%D0%B5%D1%80%D1%82%D0%B0%D1%...
Доброго всем здравия. Я немного в тупике.
Для вывода на ЖКИ от Siemens s65 на контроллеле LS020...... цифры нужно преобразовть в символы.
со знаковой 16 битной проблем не было, itoa справилать, а вот с беззнаковой и 32 битными знак. и беззнак. что то не так.
Функция выглядит так:
Проблема следующая:
Предположем нужно вывести значение 123 - не вопрос, печатаеьт "123", при следующей интерации (предположем) значение становится 5, а выводится "125". Т.е. в 3-й строке обьявляемый и инициализируемый массив указателей, уже содержит значения с прошлой интерации, это как?
У вас проблема совсем не в преобразовании типов. В случае со 123 вы выводите на дисплей 3 знака которые в библиотеке работы с дисплеем преобразуются в набор точек матрицы дисплея и этот набор запоминается в буфере дисплея по нужным координатам. А когда выводите 5 то это один символ и в буфере дисплея затирается только необходимая для него область а та область где отображаются 1 и 2 не затрагивается. Это ваша забота, залить область отображения цветом фона перед очередным выводом.
hugoboss317, "Мама дорогая!" Ок, про реализацию промолчу.
Про затирание символов уже сказали.
Про 32 битные значения. Если параметр описан как uint16_t, то никакое 32 битное число в него не войдет. Кстати, 32 битное число - это 4 байта, а 4 байта в 5 символьный массив output не войдет, запросто, надо увеличить.
А если будет отрицательное число? Это вопрос на предмет подумать, задач известна только тебе.
Еще есть одна засада, хотя относительная. Значение x проверяется только после вывода символа, впрочем наверное это нормально, скорей всего в drawChar тоже есть проверки выхода за пределы экрана (легко проверить, если на вход подать значение больше чем S65WIDTH). Ну и y вообще не проверяется.
В общем есть о чем подумать ;)
Удачи!
мммм да, Хотя возрвзить не могу ничего так как сам дал мало ихформации но это ИМХО когда сильно длинный вопрос его не всегда дочитывают до конца.
Продолжу:
по затиранию, я чёт думал что понятно будет, что первые два аргумента функции "х" и "y" (::Print(uint8_t x, uint8_t y,)это координаты и затирать нужно будет если после "123" будет "5" печетать как "523", кстати так и печатаеи, всё норм, затираю. Так что Alex_Sk извини, но не то.
>> Про затирание символов уже сказали.
kisoft как ты мог подумать, что я это не учёл, ну прям оскорбил, да сильней чем в самом начале... :(
по выходу за пределы, да, действительно, это проверяется в drawChar, более того, я дважды перепроверил что бы это отслеживалось.
по int32_t и uint32_t то же самое, перегруженые функции, реализация та же, просто не стал выкладывать.
И вобще kisoft я просто в шоке. Вроде чётко спросил как тольк что обьявленный и тут же инициализированый массив указателей уже содкржит данные с предидущей интерации. какие затирания, какие выходы за пределы?
Да ну, я по доброму.
Во первых, скорей всего конструкция (нестандартная):
char *output = "xxxxx";
Каждый раз инициализируется одним и тем же адресом. Т.е. "xxxxx" хранится в глобальной секции, а не формируется в стеке. Потому такая фигня.
Потому мне сразу не понравилась реализация. Ну извини, если обидел, не хотел.
Та я тоже не всерьёз. Собственно разглядывал и непонимал чтож тебе в констркуции не понравилось. Ну это я на потом решил оставить.
по теме: что я не понимаю?
int val = 5;
а печатаем val и получаем 105.
А если, например, int val = 5; написать, тогда что выводится?
Т.е. в 3-й строке обьявляемый и инициализируемый массив указателей, уже содержит значения с прошлой интерации, это как?
А потому что не массив указателей, а указатель на массив.
Первый раз печатает правельно, я в порт посылаю, там всегда то, что и должно быть.
А вот к примеру если напечатать 100 а потом 5, то напечатает 105 и в порт летит 5
А потому что не массив указателей, а указатель на массив.
я бы даже сказал, указатель на строку
Даже вот так:
я бы даже сказал, указатель на строку
Ну да, а чему же тогда удивляться? Компилятор инициализирует указатель, а строку он не изменяет.
Я, если честно, даже не знаю обязан ли он разрешать что-то писать в эту строку. Обычно таким способом объявляют именно строки-константы. Так что да, согласен, выглядит непривычно.
Но может и ошибаюсь - я в этих сишных стандартах всё же как-то не очень. :)
Ну это совсем не константа (я про "xxxxx"), это всего лишь строка. Как я уже сказал, что она попадает в отдельный сегмен данных, который может быть перезаписан. Т.о. каждый раз при входе в функцию он получает одно и тоже значение.
Вот набросал тупой пример с которого можно начать. Он, возможно, не идеален, но он прост как три рубля. Теперь, когда он заработает, можно его "оптимизировать", если интересно. Этот скетч я на своем дедушке Леонардо мучал :)
А теперь замени строку 19 на твой вариант:
Надеюсь теперь понятней.
UPD: Смысл в том, что массив - это конкретное место в памяти, а указатель - это всего лишь ссылка на место. В отладчике бы это покрутить, сразу было бы видно.
мастер-класс :)
kisoft, а какие ограничения-разница в применении объявлений в старом-новом стиле ? или это для совмещения для старых платформ ? ....никак не пойму разницу :(
щас что можно применять ? почему нельзя просто - int ?
зачем и почему именно "int16_t" или "int8_t"?
Ну это совсем не константа (я про "xxxxx"), это всего лишь строка. Как я уже сказал, что она попадает в отдельный сегмен данных, который может быть перезаписан.
Это я согласен, на ардуине оно так и работает, знаю. Я про другое писал - обязано ли оно так работать, в соответствии со стандартом языка.
Вот, заинтересовался - попробовал похожую штуку в MSVC - куда уж стандартней! :)
Оказывается, не зря сомневался.
Компилится всё нормально, без ошибки - но при выполнении в 3 строке выскакивает исключение - Access violation writing.
А как раз потому что сегмент с такими строками не может быть перезаписан. Ну, то есть, на более крутых процессорах.
К ардуине это не относится - здесь выбора нет, сегмент всего один, для любых данных.
Не считая, конечно, программной флэш-памяти - но туда компилятор размещает данные только если его специально об этом попросить.
мастер-класс :)
kisoft, а какие ограничения-разница в применении объявлений в старом-новом стиле ? или это для совмещения для старых платформ ? ....никак не пойму разницу :(
щас что можно применять ? почему нельзя просто - int ?
зачем и почему именно "int16_t" или "int8_t"?
Иногда проще объяснить на примере, это я про "мастер-класс".
А теперь про типы. Собственно это не новый стиль, просто существуют разные типы данных, одни зависят от размера шины данных, другие - "независимые". Такое есть, возможно, в большинстве компиляторов (из тех, что я видел).
Фишка в том, что такие типы всегда имеют фиксированный размер. int16_t - всегда 16 бит, uint16_t - тоже, только беззнаковое. Я использовал это в примере, потому что у автора было так же. Вообще на эту тему лучше почитать, а то много всего нужно объяснять.
В приложении к большим процам, использование таких типов может при вести к приведению типов, грубо говоря, если проц 32 битный, а мы используем int16_t, то при записи переменной такого типа в регистр проца, будет приведение к 32 битам, а это лишняя команда. Короче, лучше почитай, если интересно, а то я щас нарассказываю сказок.
В Ардуино 8 бит (как правило), потому проблемы другие, использование таких типов позволяет " экономить" место, всегда чётко знать, сколько бит можно хранить в переменной, следовательно уменьшить шансы записать, например, в int8_t значение 512. Ну и использование int8_t вместо int, позволяет сэкономить один байт ;) В общем можно использовать любой вариант.
Upd: ещё один пример, это когда есть двоичный файл с жёсткой структурой, тогда считав данные из такого файла в структуру, не требуется "парсить". Плюс при переносе файла на проц с другой битностью, можно получить ошибку, потому что " вдруг" int станет размером в 32 бита и структура "поедет".
По поводу сегментов, я все таки хочу глянуть map , что быть уверенным в моём предположении, вт.ч. и на большом компе.
Если будет возможность, посмотрю по сегментам, отпишусь.
И ещё насчёт типов.
Титпы типа "int16_t" или "int8_t" - это скорее всё же не встроенные компиляторные типы, а определённые дополнительно.
Посмотрите файл "Arduino\hardware\tools\avr\avr\include\stdint.h " - там они все и описаны.
Я немного вернусь к своим баранам. char *output = "xxxxx"; это не запуск орбитальной станции в космос и почему вы все так поитесь этой конструкции я не пойму. Но т.к. я програмист великий, говорить о превосходстве чего то или недостатках я не буду. Мне подходит именно такое исполнение. Я внимательно рассмотрел то, что мне предложил kisoft. Это хорошо, просто и понятно НО .... я прихожу к тому, от чего ушёл, а именно:
Для вывода int16_t я вызываю функцию Print, которая вызывает функцию drawText которая вызывает функцию drawChar
Сначала по-поводу расположения переменных на большом компе и на МК.
1. На большом компе эта конструкция char *output = "xxxxx"; попадает в секцию, которая является неизменяемой (CONST), потому, при выполнении такая программа выпадает с ошибкой. Ошибка говорит о том, что прога лезет в защищенную область памяти. Логично.
2. На МК переменная output оптимизировалась и располагается сразу и намертво в SRAM (ОЗУ), причем этот указатель не меняется. Эта "константа" "xxxxx" не инициализируется при входе в функцию. Я смотрел в листинге.
Короче такая конструкция на мой взгляд некорректная и использовать её - быть самому себе "злобным буратино".
По-поводу ошибки, вот пример, как можно решить данную проблему и без itoa:
Здесь разница с исходным скетчем достаточно большая. А именно в том, что массив output теперь точно локальный и точно инициализируется при входе в функцию (я не проверял, Ардуины под рукой нет). Разницу выделил цветом. Позволил себе немного скорректировать некоторые моменты, уж извини.
Надеюсь прояснил некоторые тонкости, хоть и не всё, что я говорил понятно. Ну так можно и спросить, если что.
PS Ну и чтобы было понятно, я просто хотел помочь без наездов и распальцовки. В отличии от Лешака, я не умею так долго и нудно объяснять, потому я могу показаться грубым, если смотреть со стороны. Если человек нормально спрашивает, так ему и помочь приятно. ;)
Таки да, полностью рабочая конструкция и 100% ответ на мой вопрос. Нюанса с char *output = "xxxxx"; я конечно же не знал, теперь всё ясно. Не подумал что можно так char *lp_ptr = output; обьявить указатель на массив, точнее на его первую ячейку. (не так char *lp_ptr = output[]);
kisoft ты никого не не оскарблял и не грубил, напротив... Спасибо
P.S. По этому же. Почему получается следующее:
обявляется восьмибитная переменная предположим
шестнадцатибитная переменная
и ещё 32-х битная
имеются перегруженные функции для вывода этих переменных (не обращаем внимание на знаковые и беззнаковые)
, но "а" я могу выводить как uin16_t (первой) хоть она и uint8_t, а вот не "а" не "b" нельзя вывести второй функцией т.е как uint32_t
Если есть только два варианта Print с uint16_t и uint32_t, то a и b выводиться будут только методом 1, поскольку он ближе к их размеру (перед вызовом метода, сначала делается неявное преобразование a и b к uint16_t).
Но на всякую хитрость есть другая хитрость. Приведение типов. Например:
Print(..,(uint32_t)a,...)
Print(..,(uint32_t)b,...)
Есть еще вариант, из 16 битового вызывать метод 32 битовый, тем же приведением типов, чтобы не дублировать код:
Хотя, если честно, не совсем понятен смысл заводить два варианта для вывода 16 и 32 битовых значений, если можно оставить только 32 битовый вариант. Для пробы можно закомментарить 16 битовый вариант и попробовать без явного приведения типов.
Вот и меня не устраевает, точнее не совсем нравится нужны не 2 а 4 варианта вывода, для знаковых и беззнаковых
uint16_t пробовал закоментировать, уже не помню но жалуется что то на перегруженную функцию
Вот и меня не устраевает, точнее не совсем нравится нужны не 2 а 4 варианта вывода, для знаковых и беззнаковых
uint16_t пробовал закоментировать, уже не помню но жалуется что то на перегруженную функцию
.....форматированный вывод
Про ftdi не подскажу, у меня нет 2580 (я и не знал что такая есть).
С ftdi аккуратней, нуегонафиг.
Да это я с перепугу ошибся не 2580, 2560
Чего это нафиг? вобще есть это в меге?
Нафиг - потому что во-первых китайцы этот FT232 начали подделывать, а во-вторых FTDI всунул в свои драйверы защиту от этих подделок. Темы тут где-то были, ищите.
А так, если FT232 настоящий - думаю ни у кого никаких претензий к нему нет.
Перешёл по этому вопросу в другую тему http://arduino.ru/forum/programmirovanie/mega-i-displei-ot-siemens-s65#comment-104657
Посмотрите если не сложно