Форматирование строки для вставки десятичной точки

У меня есть целое число шириной 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. Я бы передал строковый указатель функции, которая будет отображать символ за символом.

Возможно, вы могли бы сделать printf("%u.%02u", (unsigned)Value / 100, (unsigned)Value % 100);

pmg 30.09.2023 18:37

@pmg, если всегда предполагается печатать начальный «0», даже если Value меньше 1000, то разве формат не должен быть %02.%02u?

Jeff Holt 30.09.2023 20:17

Да @JeffHolt ... или если ОП хочет, чтобы число было выровнено по правому краю с пробелом, правильный формат будет "%2u.%02u"

pmg 30.09.2023 20:21

@JeffHolt Под %02.%02u (что неверно), я полагаю, вы имели в виду %02u.%02u.

chux - Reinstate Monica 30.09.2023 21:31

@pmg, Приведения можно избежать с помощью 100u: printf("%u.%02u", Value / 100u, Value % 100u);.

chux - Reinstate Monica 30.09.2023 21:40

@chux-ReinstateMonica Вы правы.

Jeff Holt 30.09.2023 21:53
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
6
157
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Если вы работаете только с целыми числами длиной 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

Serpent7776 30.09.2023 20:12

Учитывая, что OP хочет «XX.XX», когда number = 123, вывод с "%.2f" имеет только 3 цифры.

chux - Reinstate Monica 30.09.2023 21:28

@chux-ReinstateMonica ОП сказал, что они имеют дело с целыми числами из четырех цифр. 123 имеет ширину 3 цифры.

Mehdi Charife 30.09.2023 21:46

Честная оценка.,,,,,,

chux - Reinstate Monica 30.09.2023 21:49

Если вы знаете, что всегда есть 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.

Mumbai Verve 01.10.2023 19:09

Другие вопросы по теме