small itoa() ????

11 posts / 0 new
Last post
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi,
i need to convert some integer value into char, and then print it on a LCD, and i need to convert some ASCII commands from UART to integers, but don't want to include stdio.h because its too bulky.
does anyone know are there any included functions which i could use for this???
thanx

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why don't you do what you're suggesting in the subject, and use itoa() then?

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.
Please read the `General information...' article before.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just including stdio.h doesn't add anything to your code. But when you actually use one of the functions defined in it then at link time the conpiler/linker ONLY pulls in the bits of libc that are involved in supporting the function/s that you have used. The chances are that the itoa() in the C lib is going to be as efficiently codes as anything you can come up with. But to give you an idea of how an itoa() can be done I've sometimes used something along the lines of:

char* my_itoa(int value, char *string, int radix)
{
	if(!string)
	{
		return NULL;
	}

	if(0 != value)
	{
		char scratch[34];
		int neg;
		int offset;
		int c;
		unsigned int accum;

		offset =32;
		scratch[33] = '\0';

		if(radix == 10 && value < 0)
		{
			neg = 1;
			accum = -value;
		}
		else
		{
			neg = 0;
			accum = (unsigned int)value;
		}

		while(accum)
		{
			c = accum % radix;
			if(c < 10)
			{
				c += '0';
			}
			else
			{
				c += 'A' - 10;
			}
			scratch[offset] = c;
			accum /= radix;
			offset--;
		}
		
		if(neg)
		{
			scratch[offset] = '-';
		}
		else
		{
			offset++;
		}

		strcpy(string,&scratch[offset]);
	}
	else
	{
		string[0] = '0';
		string[1] = '\0';
	}

	return string;
}

which is used in the form:

char buff[40];
int x = 37215;

	my_itoa(x, buff, 10);

which converts 'x' to a string of characters in 'buff' using base 10.

However you'll note that this uses strcpy() from libc anyway, if you really want to avoid the library stuff being dragged in you'll need to implement your own version (*p++ = *q++ kind of thing)

Cliff

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi

maybe that these ym functions can help you. The first is for small number and the second for 32 bit number.

void LCD_PrintAsDec (u16 num) //for vlue from 0 to 999
//or void LCD_PrintAsDec (u08 num) //for vlue from 0 to 254
{ 
u08 temp1;
u08 temp2;
u08 temp3;

temp1 = 0x30 + (num %10);
num /= 10;

temp2 = 0x30 + (num %10);
num /= 10;

temp3 = 0x30 + (num %10);
num /= 10;

if (temp3 == 0x30) LCD_SendByte (0x20);  
else LCD_SendByte(temp3); 

if (temp2 == 0x30 && temp3 == 0x30) LCD_SendByte (0x20); 
else LCD_SendByte(temp2); 

LCD_SendByte(temp1); 
} 
void USART_PrintAsDec(u32 num)
{
    //support max 0xffffffff (32 bit) in dec 4 294 967 295
    //print argument as decimal
    char string[14];//we work with max 4 294 967 295 its 10 num and 1 char for "end string" 
    char *p;
    p = string;
    
    do //do becouse if we use only while it not vork for num =0
    {
    *p = 0x30 + (num %10);
    num /= 10;
    
    if ( (p-string)%4 == 2)  { p++; *p = 0x20;}
    
    p++;
    }while (num !=0);//do
    
    p--;                 //this is here for fix num like 132 or 123 456,
    if (*p != 0x20) p++; //becouse if its not here it write "123" like " 123" (with space)
                        
    while (p--  != string) 
    {
    USART_SendByte (*p); 
    }

}//printasdec

and here is function to read integrs from usart

u32 USART_GetsNumber (void)
{
u32 sec = 0;
u08 c;

while (1)
{
    c = USART_ReceiveByte();
    delayms (1);//for some terminal
    
    USART_SendByte(c);
    
    if (c == 0xD) //0xd = Enter
        {
        return sec;
        }
    else if (c == '\b') //'\b' = BackSpace
        {
        sec /= 0xA;
        USART_SendByte (0x20);
        USART_SendByte ('\b');
        }
    else if (sec) 
        {
        c = c - 0x30;//its work becouse 0x30 is 0, 0x31 is 1 ... and 0x39 is 9
        sec *= 0xA; //* 10 in decimal
        sec += c;       
        }
    else 
        {
        c -= 0x30;
        sec = c;
        } //if   
    }//while
} //GetsUSARTNUmber
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a compact routine for printing a number in various bases. Not exactly what you need, but you can easily modify it.

//
// Print a number in the given base 
//
void print_number (int base, int unsigned_p, long n)
{
    static char chars[16] = "0123456789abcdef";
    char *p, buf[32];
    
    if (!unsigned_p && n < 0) {
        UART_SendByte('-');
        n = -n;
    }
    
    p = buf + sizeof (buf);
    *--p = '\0';

    do {
        *--p = chars[n % base];
        n /= base;
    } while (n != 0);
    
    while (*p)
        UART_SendByte(*p++);
}

/Jesper
http://www.yampp.com
The quick black AVR jumped over the lazy PIC.
What boots up, must come down.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi

nice function Jesper. But why are base and unsigned_p defined as int and not char (or even bit)??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For historical reasons. You can change it to uint8_t

/Jesper
http://www.yampp.com
The quick black AVR jumped over the lazy PIC.
What boots up, must come down.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or you might do what K&R did:

//NOTE: stolen from K&R p. 64 itoa function
void itoa(int n, char s[])
{
	int i, sign;
	
	if ((sign = n) < 0) // record sign
		n = -n;			// make n positive
	i = 0;
	do {	// generate digits in reverse order
		s[i++] = n % 10 + '0'; // get next digit
	} while ((n /= 10) > 0); // delete it
	if (sign < 0)
		s[i++] = '-';
	s[i] = '\0'; // add null terminator for string
	reverse(s);
}


//NOTE: stolen from K&R p. 62 reverse function
// reverse: reverse a string s in place
void reverse(char s[])
{
	int c, i, j;
	
	for (i = 0, j = strLen(s)-1; i < j; i++, j--){
		c = s[i];
		s[i] = s[j];
		s[j] = c;
	}
}

Do it backwards then reverse the number. Those guys are way cleverer than me. (But who is surprised?)

Smiley

FREE TUTORIAL: 'Quick Start Guide for Using the WinAVR C Compiler with ATMEL's AVR Butterfly' AVAILABLE AT: http://www.smileymicros.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here a version which does not use divisions (only for base 10)

void itoa( int val, char *s )
{
  char *p;
  unsigned char d, i;
  unsigned char zero;
  unsigned int test;
  unsigned int uval = val;
  

  p = s;
  
  if( val < 0 ){
    uval = -val;
    *p++ = '-';
  }

  zero = 1;

  i = 4;
  do{
    i--;   
    if ( i==0) test = 10;
    else if ( i==1) test=100;
    else if ( i==2) test=1000;
    else test=10000;

    for( d = '0'; uval >= test; uval -= test )
    {
      d++;
      zero = 0;
    }
    if( zero == 0 )
      *p++ = d ;
  }while( i );

  *p++ = (unsigned char)uval + '0';
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanx guys you helped me alot!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And after 6 years, you helped me too!

Here's a modified version for unsigned long long used with an RFID reader.

void ulltostr(unsigned long long val, char *s ) 
{ 
  char *p; 
  unsigned char d, i; 
  unsigned char zero; 
  unsigned long long test; 
  unsigned long long uval = val; 
  
  p = s; 

  zero = 1; 

  i = 12; 
  do{ 
    i--;    
    if ( i==0) 		test =10; 
    else if ( i==1) test =100; 
    else if ( i==2) test =1000; 
    else if ( i==3) test =10000; 
    else if ( i==4) test =100000; 
    else if ( i==5) test =1000000; 
    else if ( i==6) test =10000000; 
    else if ( i==7) test =100000000; 
    else if ( i==8) test =1000000000; 
    else if ( i==9) test =10000000000; 
    else if ( i==10) test=100000000000; 
    else if ( i==11) test=1000000000000; 
    else if ( i==12) test=10000000000000; 
    
    for( d = '0'; uval >= test; uval -= test ) 
    { 
      d++; 
      zero = 0; 
    } 
    if( zero == 0 ) 
      *p++ = d ; 
  }while( i ); 

  *p++ = (unsigned char)uval + '0'; 
}