Как сделать лучше?

Maka
Offline
Зарегистрирован: 24.10.2015

Есть функция:

void _setTime() {
  byte h = Clock.getHour(h12, PM);// получаем часы
  byte m = Clock.getMinute();     // минуты
  byte s = Clock.getSecond();     // и секунды из ds3231
  // проверка на количество разрядов в hh mm и ss и печать на экран 2004. Если что-то меньше 10, 
  //печатаем пробел перед цифрой
  if ((h >= 10) & (m >= 10) & (s >= 10)) lcd.printfAt(5, 1, "%d:%d:%d", h, m, s);
  else if ((h < 10) & (m >= 10) & (s >= 10)) lcd.printfAt(5, 1, " %d:%d:%d", h, m, s); // если часы меньше 10, печатаем пробел перед ними
  else if ((h >= 10) & (m < 10) & (s >= 10)) lcd.printfAt(5, 1, "%d: %d:%d", h, m, s);
  else if ((h >= 10) & (m >= 10) & (s < 10)) lcd.printfAt(5, 1, "%d:%d: %d", h, m, s);
  else if ((h >= 10) & (m < 10) & (s < 10)) lcd.printfAt(5, 1, "%d: %d: %d", h, m, s);
  else if ((h < 10) & (m >= 10) & (s < 10)) lcd.printfAt(5, 1, " %d:%d: %d", h, m, s);
  else if ((h < 10) & (m < 10) & (s >= 10)) lcd.printfAt(5, 1, " %d: %d:%d", h, m, s);
  else lcd.printfAt(5, 1, " %d: %d: %d", h, m, s);
  h = lcd.inputTimeHourAt(5, 1, 0, 23, h);// функция ввода с помощью энкодера и печати. номер, строка, 
  //нижний лимит, верхний лимит, значение по умолчанию.
  Clock.setClockMode(false);
  Clock.setHour(h);
  m = lcd.inputTimeMinAt(7, 1, m);
  Clock.setMinute(m);
  s = lcd.inputTimeSecAt(10, 1, s);
  Clock.setSecond(s);
  while (lcd.getEncoderState() != eButton);
}

 

Она вызывается обработчиком меню. lcd.printfAt() функция библиотеки этого самого меню. Она основана на printf, и выводит строку с нужной позиции на lcd 2004. Все работает, но мне не нравится код с if и else if, вероятно можно краше как то. По сути вопрос, можно ли как-то изменять форматирующую строку printf, то есть добавлять пробелы в зависимости от количества разрядов выводимого?

 

negavoid
Offline
Зарегистрирован: 09.07.2016
printf( "%02d", h );

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Ага, уже ответили.

 

Maka
Offline
Зарегистрирован: 24.10.2015

Да пробовал, printf в ардуине урезаный, не работает.

upd Все работает, круто. Спасибо!

sadman41
Offline
Зарегистрирован: 19.10.2016

Не урезанный, стало быть, или урезанный таки? Мужики спрашивают, волнуются...

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

%f  у его обрезанный. Дак добрые луди пользують dtostr()

Maka
Offline
Зарегистрирован: 24.10.2015

DetSimen пишет:

%f  у его обрезанный. Дак добрые луди пользують dtostr()

Спасибо, чуствую пригодится.

А как вместо нуля пробел печатать?

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Выравнивать. Влево или вправо. Чти, я не помню. 

Maka
Offline
Зарегистрирован: 24.10.2015

Круто, чту.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Maka пишет:

А как вместо нуля пробел печатать?

Ноль убрать

printf( "%2d", h );

или

printf( "%-2d", h );

как больше нравится (это разное выравнивание)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

DetSimen пишет:

%f  у его обрезанный.

У него не %f обрезанный.

printf получает адрес переменной и по указанному в текстовой строке формату считает, что по стандарту Си там должна лежать нормальная 8-байтовая double. А у AVR double имеет длину 4 байта, вот и получается облом. Кстати, на Due и stm32 этой проблемы нет, т.к. там обычная 64-разрядная double. И, соответственно, printf нормально работает.

Так что printf работает и на Ардуино. Но не везде.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Чёт Вы напутали.

sadman41
Offline
Зарегистрирован: 19.10.2016

А вот как принтф отучить писать +0 при %+4ld? А то не всегда этот оптимизм уместен.

Maka
Offline
Зарегистрирован: 24.10.2015

ЕвгенийП пишет:

Maka пишет:

А как вместо нуля пробел печатать?

Ноль убрать

printf( "%2d", h );

или

printf( "%-2d", h );

как больше нравится (это разное выравнивание)

 

Спасибо за разжевывание! Уже переписал все. Не пойму, как проглядел выравнивание.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

sadman41 пишет:

А вот как принтф отучить писать +0 при %+4ld? А то не всегда этот оптимизм уместен.

Лучше было не приучать :)

Ибо «ваистену» сказано: «+ The result of a signed conversion always begins with a plus or minus sign» (ISO/IEC 9899-2018, разд. 7.21.6.1 (6))

sadman41
Offline
Зарегистрирован: 19.10.2016

:( 

Температуру удобно выводить. Потому что ежели в поле с выравниванием её совать, то выходит "-    30C" на отрицательной. А с модификатором "+" всё красиво "    -30C"

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

А модификатор "пробел"? Не подходит?

sadman41
Offline
Зарегистрирован: 19.10.2016

Хм... как я его просмотрел... Интересный вариант, мерси. Теперь мучений добавилось: оставить " +15" и "  +0" или согласиться на "  15" и "   0" - вот в чём вопрос...

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

замени в буфере плюс пробелом, да и сё

ну или весь буфер влево сдвинь. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Да у меня строка составная выводится на LCD. Поэтому и snprintf заюзал - чтобы самому с выравниванием не страдать.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

sadman41 пишет:

Поэтому и snprintf заюзал

 

А чем выводите? Если какой-нить бильбитекой, произведённой от Stream, так можно и без "s" - прямо printf на экран натравить.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:

Да у меня строка составная выводится на LCD. Поэтому и snprintf заюзал - чтобы самому с выравниванием не страдать.

Красиво! Хоть ИЭК и не люблю, но задумался над таким корпусом.

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

А чем выводите? Если какой-нить бильбитекой, произведённой от Stream, так можно и без "s" - прямо printf на экран натравить.

Самопалом из char[] буфера в PCF8574... Памяти в обрез, поэтому один и тот же буфер и под входные данные с сети и под вывод куда попало. Так что пока вот самый "дешёвый" для меня выход - snprintf_P(buffer, NNN, PSTR(" ... "). ...);

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Ну дак найди потом в buffer[]  плюсик, да замени на пробел

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

Да у меня строка составная выводится на LCD. Поэтому и snprintf заюзал - чтобы самому с выравниванием не страдать.

А зачем составная? Выводи каждый тип данных в свою позицию дисплея - вот тебе и выравнивание

sadman41
Offline
Зарегистрирован: 19.10.2016

Во-первых - это красиво...

Во-вторых: какой будет "своя" позиция при выводе числа от 0 до 99 со знаком, при условии выравнивания его по правой стороне? 

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

Во-вторых: какой будет "своя" позиция при выводе числа от 0 до 99 со знаком, при условии выравнивания его по правой стороне? 

По-моему, посчитать правую координату совсем не трудно. Во всяком случае проще, чем подбирать позицию в составной строке. Ну не мне тебе обьяснять, как выяснить, сколько разрядов в числе :)

Вот тут я и знак вывожу, и число разрядов после запятой меняю, чтобы все числа ровно в столбик вывести:

sadman41
Offline
Зарегистрирован: 19.10.2016

Зачем позицию подбирать? Или меня сегодня давлением придавило так, что я не совсем понимаю почему куча вычислений с расчётом позиции и кол-ва забивочных пробелов чтобы не получить " ++2C", будет экономней, чем: 

snprintf_P(buffer, sizeof(buffer), PSTR("\x0CIN : %+4ld\xDF\C %3ld%% %2ld%c\n\t%4ld mm %4ld PPM\n\n\nOUT: %+4ld\xDF\C %3ld%%"), indoorTemperatureLevel, indoorHumidityLevel, howLongWork, animationChars[animationStep], insidePressureLevel, co2Level, outdoorTemperatureLevel, outdoorHumidityLevel);

​printToPCF8574LCD(&SoftTWI, buffer);

Да и позиционирования-то у меня в функции, вобщем-то, нет - просто байстстриминг в I2C экспандер.

 

b707
Offline
Зарегистрирован: 26.05.2017

Да ладно, проехали : )Тебе так удобнее, а мне - эдак.  Хотел картинкой похвастать :)

sadman41
Offline
Зарегистрирован: 19.10.2016

Так я без претензии. Моё знание не системное, порой даже какие-то простые штуки упускаю из виду. Поэтому и интересуюсь - может есть способ проще, экономней.