Специальное форматирование чисел с плавающей запятой и преобразование их в массив символов.
У меня есть oled-дисплей, который может отображать только 4 цифры + десятичную точку. Мне нужен способ форматировать число в 4 значащие цифры; Затем мне нужно преобразовать это в массив из 5 символов (4 цифры и одно dp), прежде чем я смогу их отобразить.
Не знаю, как форматировать, чтобы исправить количество цифр, или как преобразовать в массив символов. Я немного поискал, и printf кажется решением (?), но мне с ним не повезло, поскольку он выдает всевозможные ошибки. если вы знаете, как заставить это работать, можете ли вы предоставить фрагмент кода, который компилируется без ошибок? спасибо.
@OM222O, 👍0
Обсуждение1 ответ
Обычно решением является sprintf()
, однако sprintf()
в AVR LIBC представляет собой урезанную версию без поддержки чисел с плавающей запятой.
Вместо этого вам нужно использовать dtostrf()
, чтобы получить задание готово:
dtostrf(val, 6, 4, buffer);
Цифры — это максимальная ширина строки (примечание: необходимо учитывать любой знак минус в этом значении) и количество десятичных знаков (6,4 дадут место для «0,0000», но не «-0,0000»). Убедитесь, что ваш буфер на один байт больше вашего текста, поскольку для его завершения необходимо иметь в конце нулевой символ.
Другой (неприятный) способ — использовать String
(хотя я бы никогда не рекомендовал использовать String
ни для чего):
String s(val, 4);
const char *buf = s.c_str(); // это указывает на внутренний буфер символов.
Действительно ли класс String в библиотеке Arduino настолько плох?, @Duncan C
В самом деле. Он использует динамическое распределение внутреннего хранилища данных, и это ужасная идея, когда у вас есть только 2 КБ., @Majenko
А как насчет объектов String, выделенных в стеке? Не будут ли они освобождены при возврате, поэтому избегайте фрагментации (очевидно, если вы не выделяете другие долгоживущие объекты в той же цепочке вызовов.), @Duncan C
@DuncanC, что такое строка Arduino, выделенная в стеке? Он по-прежнему использует realloc и освобождает из кучи. Выделение и освобождение памяти не является проблемой, а вот фрагментация — проблемой. Это также вызвано изменениями, внесенными в строку (перераспределение может привести к фрагментации)., @Jot
Если вы определяете строку как локальную переменную в функции или в выражении для составления строк из других строк, эти объекты String должны быть временными (в C++ объекты, назначенные локальным переменным в функциях, создаются в стеке и высвобождаются, как только как функция возвращает), @Duncan C
@DuncanC Строковый объект является локальным, но данные, которые он выделяет для выполнения своей работы, находятся в куче., @Majenko
Хорошо, но когда строка будет уничтожена, данные ее кучи будут освобождены., @Duncan C
@DuncanC дело не в количестве. Речь идет о фрагментации кучи. Локальные строки на самом деле хуже, *потому что* они освобождаются., @Majenko
Что ж, если вы находитесь в локальной функции, создаете несколько объектов, а затем возвращаетесь, и некоторые объекты сохраняются, а некоторые нет, у вас есть фрагментация. Если вы создаете только временные объекты и все они освобождаются, вы не вызываете фрагментации., @Duncan C
@DuncanC Я думаю, вам не хватает понимания того, как работает объект String. Да, это объект. Но это не *простой* объект. Сам объект выделяет память в куче с помощью malloc() и освобождает ее с помощью free(). Он также изменяет его размер с помощью Realloc(). Фрагментацию вызывает то, что происходит с объектом String в течение его жизни, а не простой факт существования объекта. Если вы создадите объект String, а затем удалите его снова, то, очевидно, вы не получите фрагментации. ... продолжение..., @Majenko
... Если вы создаете объект String, затем присваиваете ему значение, затем объединяете больше данных в конец, затем получаете подстроку, переназначаете ей что-то еще, к концу этого, кто знает, что у вас за куча выглядит как? Строки, если их экономно использовать для простых операций, могут быть полезными, однако риски их использования (когда вы не знаете, *как* правильно использовать и каковы опасности, связанные с ними) намного перевешивают небольшую выгоду. вы получаете от них. Каждый раз, когда я видел кого-то с проблемой «Мой Arduino случайно зависает», проблема была… продолжение…, @Majenko
Лечится удалением объектов String и повторной реализацией их с помощью символьных массивов. Каждый раз. Струны, которыми пользуется новичок, смертельно опасны. Строки, используемые пользователем среднего уровня, по-прежнему остаются минным полем. Струны, используемые профессионалами, — это то, чего вы никогда не увидите., @Majenko
Я ИТ-специалист с более чем 30-летним опытом. Я давно не работал на C++, и у меня мало опыта работы со строковыми объектами Arduino, поэтому я и спрашиваю. Каковы альтернативы использованию строк C? Мне вполне комфортно работать с C, но я привык к printf() и sprintf(), поэтому чувствую себя немного растерянным., @Duncan C
Давайте [продолжим обсуждение в чате](https://chat.stackexchange.com/rooms/90282/discussion-between-duncan-c-and-majko)., @Duncan C
- Хранение значений широты и долготы в виде символов с заданной точностью
- Кто-нибудь может привести пример извлечения данных из массива char?
- Преобразование из Float в Int дает странные результаты. Что я делаю не так?
- Вход Последовательного Монитора Arduino, шифрование 3DES
- Массив из существующих массивов
- Почему символы со значением выше 127 "дополняются" 1s длиной 16 бит, а символы со значениями 0-127 - нет?
- avrdude ser_open() can't set com-state
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
printf на AVR не поддерживает форматирование с плавающей запятой без некоторых настроек в файлах конфигурации построителя., @Juraj