Специальное форматирование чисел с плавающей запятой и преобразование их в массив символов.

У меня есть oled-дисплей, который может отображать только 4 цифры + десятичную точку. Мне нужен способ форматировать число в 4 значащие цифры; Затем мне нужно преобразовать это в массив из 5 символов (4 цифры и одно dp), прежде чем я смогу их отобразить.

Не знаю, как форматировать, чтобы исправить количество цифр, или как преобразовать в массив символов. Я немного поискал, и printf кажется решением (?), но мне с ним не повезло, поскольку он выдает всевозможные ошибки. если вы знаете, как заставить это работать, можете ли вы предоставить фрагмент кода, который компилируется без ошибок? спасибо.

, 👍0

Обсуждение

printf на AVR не поддерживает форматирование с плавающей запятой без некоторых настроек в файлах конфигурации построителя., @Juraj


1 ответ


2

Обычно решением является 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