Перейти к содержанию
    

Convert 16-bit integer to ASCII with comma and signum

Есть 16-битовый знаковый результат с АЦП, нужно написать его в виде строки с целой и дробной частями и точкой в заданной позиции. Например, 336 нужно изобразить в виде +3.36. С выравниванием по правому краю. Рабочий пример показываю ниже. Использую буфер на 8 символов. Конец строки тоже входит в буфер, и поэтому число -0.32109 не помещается, будет выводиться в виде -.32109 (может, и не стоило так ограничиваться, но это позже всплыло). Пример не очень нравится, просто на скорую руку слепил. Если кому интересно поупражняться в программировании, покажите, как можно.

/*!*************************************************************************
 @brief	16-bit integer convert to ASCII with comma and signum
 @param	num - число для преобразования
 @param	str - строка из 8 символов: знак, цифры, точка, конец строки
 @param	pointpos - позиция точки в строке (1..6, количество мест перед ней)
 @param	showplus - записывать символ '+'
 @note	        при pointpos = 0, > 6 - точка не ставится
 */
void Half2TextPoint_conv(int16_t num, char *str, uint32_t pointpos, bool showplus)
{
char *strleft = str;		// левая граница строки (только для знака)
*(uint32_t *)(str	 ) = ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24;
*(uint32_t *)(str + 4) = ' ' | ' ' << 8 | ' ' << 16 | '\0'<< 24;
bool fract = true;			//  дробная часть рассчитана или не нужна
if (pointpos >= 1 && pointpos <= 6)  {
	*(str + pointpos) = '.';
	fract = false;			//  дробная часть нужна, пока не получена
}
char sign = ' ';
if (showplus)
	sign = '+';
if (num < 0) {
	sign = '-';
	num = -num;
}
str += 6;
do {
	if (*str == '.')  {
		str--;
		fract = true;
	}
	*str = num % 10 + '0';
	str--;
} while ((num /= 10) || !fract);	// пока нужна дробная часть
if (str < strleft) str++;	// проскочили из-за запятой в поз. 1 и числа < 1
	*str = sign;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

void Half2TextPoint_conv (int16_t data, char * str, int pointpos, bool showplus){
  static const int16_t pow10_table[] = {10000, 1000, 100, 10, 1};
  bool add0 = false;
  if (data < 0) {*str++ = '-'; data =-data;}
  else if (showplus) *str++ = '+';
  for (int i = 0; i < 5; i++){
    if (i == 5-pointpos) {
      if (!add0) *str++ = '0';
      *str++ = '.';
      add0 = true;
    }
    int16_t pow10 = pow10_table[i];
    int digit = 0;
    while (data >= pow10) {
      data -= pow10;
      digit++;
    }
    if (digit) {*str++ = ('0' + digit); add0 = true;}
    else if (add0) *str++ = '0';
  }
  *str = 0;
}

 

pointpos показывает количество знаков после запятой.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я предполагал попробовать преобразовывать в два этапа - сначала преобразовать число, потом добавить знак, вставить точку и нуль перед ней и после нее, если надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А printf точку в середину числа не вставит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А printf может всегда выводить знак, даже если "+"?

Да.

%-012.2f

Точно не понмю, но печатал всегда со знаком.

Вопрос в "ведущих" нулях. Надо курить реализацию форматов printf

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

Для IAR/MSP430 - отличается CLIB / DLIB

 

 

 

. . . .

Если вопрос только в установке формата (места точки и размерах целой-дробной частей)

то в (s)printf есть параметр *, через который можно в нее (приннтф) передавать эти значения.

Т.о. вместо написания отдельной ф-ии, возможно, достаточно будет

реализовать макрос-обертку с установкой требуемого формата

 

#define MyPrint(target, var, point_left_, point_right) \

sprintf( target, "%*.*f", point_left, point_right, &var) \

 

В работе я эту конструкцию не проверял, небыло необходимости.

Получится или нет - надо курить док на printf.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

После долгих мытарств решил делать так

static inline int IntToStr(int x, char str[], int d)
{
    int i = 0;
    
     do { str[i++] = (x % 10) + '0'; }
     while ((x /= 10) > 0);
     
    // If number of digits required is more, then
    // add 0s at the beginning
    while (i < d)
        str[i++] = '0';

    Reverse(str, i);
    str[i] = '\0';
    return i;
}

void FtoA(float n, char *res, int afterpoint)
{
    int ap = afterpoint;
    
     //signed?
    if(n < 0)
    {
        n *= -1;
        *res = '-';
        res++;
    }
    
    // Extract integer part
    int ipart = (int)n;
    
    // Extract floating part
    float fpart = n - (float)ipart;
        
    // convert integer part to string
    int i = IntToStr(ipart, res, 0);

    // check for display option after point
    if (afterpoint != 0)
    {
        res[i] = '.';  // add dot

        // Get the value of fraction part up to given no.
        // of points after dot. The third parameter is needed
        // to handle cases like 233.007
        //fpart = fpart * pow(10, afterpoint);
        while (ap)
        {
            fpart *= 10;
            ap--;
        }

        IntToStr((int)fpart, res + i + 1, afterpoint);
    }
}

хотя это немного не то что требуется. ну пусть висит.

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А printf может всегда выводить знак, даже если "+"?

Может

Да.

%-012.2f

%+012.2f

 

void Half2TextPoint_conv(int16_t num, char *str, uint32_t pointpos, bool showplus)
{
  char mod[]="%00.0f";
  if(showplus) mod[1] = '+';
  if(pointpos>6)  pointpos = 0; 
  mod[4] = pointpos+0x30;
  sprintf(str, mod, ((float)num/pow(10,pointpos)));
}

:santa2:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...