Author Topic: converting integers and fixed point to character sequence  (Read 5001 times)

0 Members and 1 Guest are viewing this topic.

Offline NiHaoMikeTopic starter

  • Super Contributor
  • ***
  • Posts: 9007
  • Country: us
  • "Don't turn it on - Take it apart!"
    • Facebook Page
converting integers and fixed point to character sequence
« on: February 20, 2014, 06:09:32 am »
How do I convert integers to ASCII character sequences for display on a LCD? I'm using a dsPIC and performance isn't critical, but is always nice. I also need to do the same for arbitrary fixed point values. (For example, one such variable might be 1/256 of a unit per LSB. And while the display code isn't performance critical, some of the DSP code that uses the fixed point values are.)
Cryptocurrency has taught me to love math and at the same time be baffled by it.

Cryptocurrency lesson 0: Altcoins and Bitcoin are not the same thing.
 

Online mariush

  • Super Contributor
  • ***
  • Posts: 5016
  • Country: ro
  • .
Re: converting integers and fixed point to character sequence
« Reply #1 on: February 20, 2014, 06:54:19 am »
The compiler (xc8 and others, most of them) has built in functions that do this job for you.

For example, open the XC8 user guide and search for sprintf or vsprintf ... then read the explanations for printf which explain how that function works.

xc8 user guide here: http://ww1.microchip.com/downloads/en/DeviceDoc/52053B.pdf

If you don't want to add a lot of code to your program and you only need to print a number, you can make one yourself.   

something like this

unsigned char digit[5];   // happy now?  sigh... must get some sleep.
unsigned byte digitpos = 5;
unsigned int number = 12345; // your number
unsigned int temp;
unsigned int remainder;
temp = number;
digit[4]=0;
while (temp > 0) {
 digitpos--;
 digits[digitpos] = temp mod 10;
 temp = temp / 10;
}
if (digitpos==5) digitpos = 4;

so you have  temp = 12345 , an array with 5 elements [ -, -, -, -, 0] , digitpos = 5;

temp > 0, yes it's 12345 => digitpos--; => digitpos = 4; digit[digitpos] = 12345 mod 10 = 5; = > array is [-,-,-,-5] , temp = temp / 10 = 1234
temp  > 0, yes it's 1234 => digitpos--; => digitpos = 4; digit[digitpos] = 1234 mod 10 = 4; = > array is [-,-,-,4,5] , temp = temp / 10 = 123

and so on,

and then you do a for (i = digitpos, i<5, i++)  print character digit [ i];

The above code should work with unsigned byte, unsigned char, unsigned int variables. int is maximum 65535 (5 digits). If you want to print larger numbers, you need to increase the array and redefine the digitpos to new value ( for example for a long variable (4 bytes) the maximum value would be 4,294,967,296 so you need to be able to store 10 digits.

There are other methods that use less cpu clocks, for example see the example towards the bottom of this page, which uses shift instead of divisions and precalculated tables (faster but may use more memory) : http://stackoverflow.com/questions/3694100/converting-to-ascii-in-c

or this code which converts any float, integer etc into a series of characters ... so you don't need to use sprintf but you'd neet to use the math library, for log10 and pow functions (xc8 has them)
http://stackoverflow.com/questions/2302969/how-to-implement-char-ftoafloat-num-without-sprintf-library-function-i/2303798#2303798
« Last Edit: February 20, 2014, 08:45:25 am by mariush »
 

Offline zapta

  • Super Contributor
  • ***
  • Posts: 6190
  • Country: us
Re: converting integers and fixed point to character sequence
« Reply #2 on: February 20, 2014, 07:30:57 am »
unsigned char digit[4];
;...
digit[5]=0;

These two lines don't seem to be compatible.

+1 for sprintf  or utoa() and the likes

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html
 

Online mariush

  • Super Contributor
  • ***
  • Posts: 5016
  • Country: ro
  • .
Re: converting integers and fixed point to character sequence
« Reply #3 on: February 20, 2014, 07:57:13 am »
Thanks, I corrected it. 

I'm tired, it's almost 10 am and I worked all night... fell into the classic trap of defining an array with 5 elements as digit[5], when in fact it's defined as digit[4] because you also count the 0 element.
When i double checked the code before posting, I corrected that but missed the second line of code.

 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: converting integers and fixed point to character sequence
« Reply #4 on: February 20, 2014, 08:32:25 am »
Quote
Thanks, I corrected it. 

It's still wrong.

Code: [Select]
unsigned char digit[4];
...
digit[4]=0;

"char digit[4]" yields an array 4 elements - digit[0] .. digit[3].

I hope you don't write much firmware :)

 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9930
  • Country: nz
Re: converting integers and fixed point to character sequence
« Reply #5 on: February 20, 2014, 10:56:11 am »
i vote for utoa() itoa() ltoa().. and all the others

much less complex than including all of the sprintf code
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline Rufus

  • Super Contributor
  • ***
  • Posts: 2095
Re: converting integers and fixed point to character sequence
« Reply #6 on: February 20, 2014, 03:20:08 pm »
i vote for utoa() itoa() ltoa().. and all the others

much less complex than including all of the sprintf code

I would vote for rolling your own with a bit more function that itoa() because you will often want to format right aligned into a fixed length string.

edit: for example
Code: [Select]
void
ltostr(long num, char *string, int size) {

    int neg = 0; 

    if(num < 0) {
        neg = 1;
        num = -num;
    }

    string[--size] = 0;
    size--;

    do {
        string[size--] = "0123456789"[num % 10];
        num /= 10;

    } while(size >= neg && num != 0);

    if(neg)
        string[size--] = '-';

    if(size >= 0)
        memset(string, ' ', size + 1);
}

Where size is the size of the string including terminator and leading digits which don't fit in size are discarded.
« Last Edit: February 20, 2014, 04:27:05 pm by Rufus »
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: converting integers and fixed point to character sequence
« Reply #7 on: February 20, 2014, 03:28:54 pm »
I wrote a ultoa() routine to convert an unsigned long to ascii string.

The same routine can also be used with a floating type.
================================
https://dannyelectronics.wordpress.com/
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: converting integers and fixed point to character sequence
« Reply #8 on: February 20, 2014, 04:15:20 pm »
Quote
The same routine can also be used with a floating type.

Yes, although it helps to be clear what happens in that case - the compiler will convert the float to an unsigned long, then call ultoa (as long as a prototype for ultoa is in scope).

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf