У меня есть целое число шириной 4 цифры, которое я конвертирую в строку с помощью sprintf. Предполагается, что этот массив строк представляет десятичное число XX.XX. например.
uint16_t Value;
char buff [10];
Value = 1234;
sprintf(buff,"%04d", (unsigned int)Value);
Я хочу отобразить это, скажем, на ЖК-дисплее или UART как 12.34. Самый простой (грубый) способ — проанализировать и вывести массив поэлементно, вставить десятичную точку, а затем вывести оставшуюся часть массива. Есть ли более элегантный способ сделать это?
Обновлено: Думаю, я немного упростил это. Число для печати может быть любым от 00.00 до 99.99.
sprintf(buff,"%04d", (unsigned int)Value);
Я предполагаю, что при необходимости это будет дополняться ведущими нулями. Основная причина таких искажений кодирования — отказ от операций с плавающей запятой и использования printf. Я бы передал строковый указатель функции, которая будет отображать символ за символом.
@pmg, если всегда предполагается печатать начальный «0», даже если Value меньше 1000, то разве формат не должен быть %02.%02u?
Да @JeffHolt ... или если ОП хочет, чтобы число было выровнено по правому краю с пробелом, правильный формат будет "%2u.%02u"
@JeffHolt Под %02.%02u (что неверно), я полагаю, вы имели в виду %02u.%02u.
@pmg, Приведения можно избежать с помощью 100u: printf("%u.%02u", Value / 100u, Value % 100u);.
@chux-ReinstateMonica Вы правы.



Если вы работаете только с целыми числами длиной 4 цифры, простым решением может быть:
#include <stdio.h>
int main() {
int number = 1234;
char buffer[200];
sprintf(buffer, "%.2f", number/100.0);
printf("%s\n", buffer);
return 0;
}
Обратите внимание, что в системах UNIX, как указано на странице руководства sprintf, точка может не создаваться, в зависимости от текущей локали linux.die.net/man/3/sprintf
Учитывая, что OP хочет «XX.XX», когда number = 123, вывод с "%.2f" имеет только 3 цифры.
@chux-ReinstateMonica ОП сказал, что они имеют дело с целыми числами из четырех цифр. 123 имеет ширину 3 цифры.
Честная оценка.,,,,,,
Если вы знаете, что всегда есть 4 цифры, вы можете сделать это без каких-либо дополнительных арифметических действий:
int main(void)
{
int number = 2500;
int bufsize = 64;
char buf[bufsize];
snprintf(buf, bufsize, "%d", number);
printf("%c%c.%c%c\n", buf[0], buf[1], buf[2], buf[3]);
return 0;
}
Вывод: 25.00
для представления десятичного числа XX.XX
Простой подход — преобразовать значение в формат с плавающей запятой, а затем распечатать.
// 0 to '0' pad as needed
// 5 for minimum text width as in XX.XX
// .2 for always 2 digits after the '.'
sprintf(buff,"%05.2f", (double)Value / 100.0);
Если вы хотите избежать математических вычислений с плавающей запятой, выведите целое и дробное число как две части.
sprintf(buff,"%02u.%02u", Value/100u, Value%100u); // Note the u in 100u
Обратите внимание, что Value — беззнаковый тип. При использовании знаковых типов нам нужно избегать '-' в дроби.
sprintf(buff,"%02d.%02d", iValue/100, abs(iValue%100));
Во всех случаях 16-битный uint16_t может иметь значения вне диапазона 1000-9999 («У меня есть целое число из 4 цифр»), и поэтому OP необходимо определить желаемый результат за пределами этого диапазона.
Простой метод, позволяющий застраховать Value < 10000, даже если мы «знаем», что Value не должно быть пятизначным:
Value %= 10000u;
sprintf(...
Примечание. Ни один из них не образует строку C с нулевым завершением. Часто API для ЖК-дисплея предлагает более простой (быстрый) вариант записи символов «n» на дисплей.
Если это микроконтроллер и вам не нужны все (громоздкие и, возможно, неиспользуемые) механизмы printf(), есть следующее:
void cnvrt( unsigned val, char buf[5] ) {
buf[4] = '0' + (val % 10); val /= 10; // Least Significant Digit
buf[3] = '0' + (val % 10); val /= 10;
buf[2] = '.'; // separator
buf[1] = '0' + (val % 10); val /= 10;
buf[0] = '0' + (val % 10); // MSD
}
Если val < 1000 или val > 9999, это все равно будет работать.
Или, возможно, вы хотите, чтобы это было в виде цикла:
void cnvrt( unsigned val, char buf[5] ) {
for( unsigned i = 5; i--; ) {
if ( i == 2 ) buf[ i-- ] = '.';
buf[ i ] = '0' + (val % 10);
val /= 10;
}
}
Ваш пример 1 похож на то, что я делаю. Пример 2 — более удачная реализация, и я думаю, что он будет работать с 00.00 до 99.99.
Возможно, вы могли бы сделать
printf("%u.%02u", (unsigned)Value / 100, (unsigned)Value % 100);