форматирование символьных строк
- Войдите на сайт для отправки комментариев
Пнд, 12/03/2018 - 03:14
... uint32_t i = 0; double s = 1.2345; char msg[ 40 ]; sprintf( msg, "%d => %8.2f", i, s ); Serial.println( msg ); ...
В итоге получим вывод:
1000 => ?
Т.е. sprintf() функция есть, форматы %d, %s и т.д. - успешно работают. А формат %f/%e - нет. Почему? Хотя в описании форматов для printf() из avr-libc эти форматы (%f/%e) есть. Как можно форматировать строки?
При копировании фрагмента допустил ошибку, должно быть, естественно (для правильного понимания вопроса):
Причём вот так вывод вещественного значения (с приведением к строке, форматированием) нормально проходит:
И результатом будет 1.23 - с заказанным числом знаков после десятичной точки. Т.е. форматировать оно кое-как умеет...
sprintf искаропки не поддерживает форматный вывод с плавающей точкой. Используй dtostrf() или dtostre().
sprintf искаропки не поддерживает форматный вывод с плавающей точкой. Используй dtostrf() или dtostre().
Спасибо ... только пока не совсем понятен прототип (формат) их вызова.
sprintf искаропки не поддерживает форматный вывод с плавающей точкой.
Зато очень удобно для форматирования всех других типов. Чтобы не плодить последовательность N+1 вызовов Serial.print(). Как-то так:
#include <alloca.h> void setup() { Serial.begin( 9600 ); // устанавливаем последовательное соединение } void reply( boolean lng ) { unsigned long time = millis(); char *msg = (char*)alloca( 80 ); if( !lng ) sprintf( msg, ".%lu", time % 1000 ); else sprintf( msg, "%02lu:%02lu.%03lu", ( time / 1000 ) / 60, ( time / 1000 ) % 60, time % 1000 ); Serial.println( msg ); } void loop() { if( Serial.available() > 0 ) // есть доступные данные reply( '?' == Serial.read() ); Serial.flush(); delay( 300 ); }И в итоге:
dtostrf() или dtostre().
не совсем понятен прототип (формат) их вызова.
Документация по AvrLibC на сайте производителя контроллеров AVR. RTFM.
Зато очень удобно ... Как-то так:
Если printf Вам нужен только для вывода в поток (как в Вашем примере), то ещё удобнее делать это (выводить в поток) сразу, без запроса буфера. Например,
// Эти три строки пишем в начале файла #include <stdio.h> static int serial_fputchar(const char ch, FILE *stream) { Serial.write(ch); return ch; } static FILE *serial_stream = fdevopen(serial_fputchar, NULL); void setup(void) { stdout = serial_stream; // эта строка первая в setup // // А ТЕПЕРЬ ТУПО ПОЛЬЗУЕМСЯ printf // Serial.begin(115200); int a = 8; // Печатаем a в разных видах printf("a=%d, a=%02d, a=%04d, a=%05d, a=%06d\n", a, a, a, a, a); } void loop(void){}В принципе, можно там же (вместо NULL в строке 4) и scanf назначить. Можете попробовать, отлично работает.
Документация по AvrLibC на сайте производителя контроллеров AVR. RTFM.
Это именно я и смотрел ... но там много и не совсем понятно с параметрами... да и с возвращаемым значением.
Разобрался:
void setup() { Serial.begin( 9600 ); } void loop() { if( Serial.available() ) { // есть доступные данные Serial.read(); char msg[ 40 ] = "", flt[ 12 ] = ""; long r = random(); double s = r / 1000.; Serial.print( r, DEC ); Serial.print( " => " ); Serial.println( s, 2 ); sprintf( msg, "%ld => %s", r, dtostrf( s, 8, 2, flt ) ); Serial.println( msg ); } delay( 500 ); }В итоге:
Если printf Вам нужен только для вывода в поток (как в Вашем примере), то ещё удобнее делать это (выводить в поток) сразу, без запроса буфера. Например,
Любопытно.
Спасибо.
Кстати, это приём (назначение потока) будет работать с любым потоком - например, SoftSerial и большинство библиотек для LCD и OLED (Adafruit очень любит свои библиотеки для экранов от Stream наследовать).