0

i want to convert int to char* in C without using itoa() function.

Because on my Linux Systems i itoa function is not there. i am using this code which i found from here

I want to run this function on Embedded devices also which are using Linux.

So i am looking for without use of itoa.

I dnt want to use sprintf also because its uses for just prints.

So any body please help me to figured out this problem.

Thanks

8
  • 2
    I dnt want to use sprintf also because its uses for just prints That makes no sense. Commented Apr 3, 2012 at 13:55
  • 1
    atoi would be useless, because it converts ASCII to integer, not vice versa. Commented Apr 3, 2012 at 13:55
  • 2
    Why do you say that sprintf is used for just print? it is not true. Commented Apr 3, 2012 at 14:02
  • 1
    @Matthias - that's why he wrote itoa and not atoi Commented Apr 4, 2012 at 13:50
  • 1
    @RoeeGavirel he wrote (edited) it after the comment. Commented Apr 4, 2012 at 14:05

5 Answers 5

7

Thing is snprintf is the perfect function for this:

char str[LEN];
snprintf(str, sizeof(str), "%d", num);
Sign up to request clarification or add additional context in comments.

3 Comments

snprintf for avoiding overflow, but otherwise the correct advice -- or just ignore me, because I can't read, apparently...
I didn't downvote, but stdio.h is generally banned from embedded systems. MISRA-C for example, bans stdio.h from all production code. Poor type safety and lousy performance are the main concerns. And since it is so easy for a programmer to write an itoa/atoi function, there is really no need to use stdio.h solely for that purpose.
@Lundin Ah, I see. I guess it makes sense :-)
5

Here is a simple snippet you can use. There are more elegant and advanced ways, but this gets the job done.

In embedded projects in the past, I have measured this to be approximately 1000 times more efficient than sprintf(). This code is also MISRA-C compliant.

void getDecStr (uint8_t* str, uint8_t len, uint32_t val)
{
  uint8_t i;

  for(i=1; i<=len; i++)
  {
    str[len-i] = (uint8_t) ((val % 10UL) + '0');
    val/=10;
  }

  str[i-1] = '\0';
}

7 Comments

I think you need some bright red flashing warning signs on this routine. First, it's going to pad the returned string with leading zeroes if the buffer is larger than absolutely necessary. Second, it doesn't handle negative numbers; granted, you declare it as taking unsigned, but the OP asked for an itoa() work-alike, which implies signed integers. I'd argue for "Third" being no radix parameter, but given the i_to_a() implementation the OP posted as an answer, I guess that part of the MS itoa() interface isn't important to him.
@WarrenYoung This is intentionally kept simple, modifications can be done to it to get more functionality. This function was written for realtime embedded systems, and therefore there is no functionality included in it that is not needed. Leading zeroes are there to make it deteministic.
Honestly, I just wanted to demonstrate how blatantly easy it is to write code like this on your own. Yet so many would-be programmers keep asking for atoi/itoa over and over... Instead of asking for fish, maybe learn how to catch the fish yourself. This is especially important if you work as a fisherman.
The padding is still a trap. If you pass a 100-character buffer, it ends up taking about 3.5x the time of the slowest other method I've benchmarked here. If you cut the buffer size to 10, it's about twice as fast as the fastest. It goes to show that you can bum code for speed if you know the exact characteristics of the input data, but I wouldn't suggest it as a general purpose function, without the warnings.
@WarrenYoung uint32_t will be 32 bit no matter platform.
|
3
#include <stdio.h>
#include <string.h>

#if 0
char *strrev(char *str){
    char c, *front, *back;

    if(!str || !*str)
        return str;
    for(front=str,back=str+strlen(str)-1;front < back;front++,back--){
        c=*front;*front=*back;*back=c;
    }
    return str;
}
#endif

char *itoa(int v, char *buff, int radix_base){
    static char table[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    char *p=buff;
    unsigned int n = (v < 0 && radix_base == 10)? -v : (unsigned int) v;
    while(n>=radix_base){
        *p++=table[n%radix_base];
        n/=radix_base;
    }
    *p++=table[n];
    if(v < 0 && radix_base == 10) *p++='-';
    *p='\0';
    return strrev(buff);
}

int main ()
{
  int i;
  char str[33];

  printf ("Enter a number: ");
  scanf ("%d",&i);

  itoa (i,str,10);
  printf ("decimal: %s\n", str);

  itoa (i, str, 16);
  printf ("hexadecimal: %s\n", str);

  itoa (i, str, 2);
  printf ("binary: %s\n", str);

  return 0;
}

5 Comments

This is the slowest of the options posted so far. On my test system with my test dataset, snprintf() took 17.1 sec, i_to_a() with the malloc() and associated required free() took 18.7 sec, i_to_a() modified to take a preallocated buffer took 15.2 sec, and your itoa() took 20.5 sec. Modifying your itoa() to add negative number support and radices up to 36 to make it compatible with the MS implementation bumped that up slightly to 20.7 sec. Nevertheless, +1 for being interesting. :)
1.negative numbers:int n -> int v, unsigned int n = v. 2.radices 2-36:"0123456789abcdef" -> "012...xyz". 3.Why slow : use / %. E.g.replace Montgomery_reduction. But What it does not have much speed is required for everyday use?
I don't have to take my point away,too. but tentatively tried to fix.
Thanks, I feel better now. :) In my own version, I didn't restrict negative numbers to base 10 only, but I see that's how MS did it. I suppose they were trying to allow hex/bin/oct output of values with the high bit set without having them display as negative. They should have defined uitoa() instead. Oh well.
yes, MS itoa is to understand and so put a minus sign only when the base 10. However, this does not mean that to limit the negative input.
0

Here is another solution (I used the function that user1089679 posted above and addressed the comments that most other users have made). Any feedback on the i_to_a function (and ideally on the whole program) would be appreciated. Please feel free to be as critical and detailed as you want (if you are nice while doing it, would be great too :)):

#include <stdlib.h>
#include <stdio.h>

int no_of_digits( int num, int radix );
char *i_to_a( char *str, int digit_count, int num, int radix );

int main()
{
  int num, radix;

  printf( "Enter a decimal number: " );
  scanf( "%d", &num );
  printf( "Enter radix: " );
  scanf( "%d", &radix );

  int digit_count = no_of_digits( num, radix );
  char *str = malloc( sizeof( char ) * ( digit_count + 1 ) );
  if( str == NULL )
  {
    printf( "Malloc failed in main, exiting.\n" ); //do additional error handling as needed
    return 0;
  }
  str = i_to_a( str, digit_count, num, radix );
  printf( "\nThe converted number as a string is: %s\n", str );
  free( str );
  return 0;
}

int no_of_digits( int num, int radix )
{
  int digit_count = 0;

  if( num < 0 )
    digit_count++;

  while( num != 0 )
  {
    digit_count++;
    num /= radix;
  }
  return digit_count;
}

char *i_to_a( char *str, int digit_count, int num, int radix )
{
  if( num == 0 )
  {
    *str = '0';
    return str;
  }
  if( num == -2147483648 )
  {
    str[0] = '-';
    str[1] = '1';
    for( size_t i = 2; i < digit_count; ++i )
        str[i] = '0';
    return str;
  }
  
  
  if( num < 0 )
  {
    num = -1 * num;
    str[0] = '-';
  }
  
  str[digit_count] = '\0';
  while( num > 0 )
  {
    str[digit_count-1] = num % radix + '0';
    num /= radix;
    digit_count--;
  }

  return str;
}

2 Comments

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
@Devlish Spirits: Actually, it is an answer to the question, if you read the whole answer. However, I agree with you that my first sentence should be saying so and I'll edit it right after this comment. Furthermore, my answer does not require "clarification from the asker" and if you think it does then please clarify. If you meant something else, please clarify as well.
-1

I found solution regarding this..

I am Happy to and i want which i expected.

#include <string.h>
#include <stdlib.h>

char *i_to_a(int num);

int main()
{

    char *str = i_to_a(4567);
    printf("%s",str);
    free(str);
    str = NULL;
return 0;

}
int no_of_digits(int num)
{
    int digit_count = 0;

    while(num > 0)
    {
        digit_count++;
        num /= 10;
    }

    return digit_count;
}


char *i_to_a(int num)
{
    char *str;
    int digit_count = 0;

    if(num < 0)
    {
        num = -1*num;
        digit_count++;
    }

    digit_count += no_of_digits(num);   
    str = malloc(sizeof(char)*(digit_count+1));

    str[digit_count] = '\0';

    while(num > 0)
    {
        str[digit_count-1] = num%10 + '0';
        num = num/10;
        digit_count--;
    }

    if(digit_count == 1)
        str[0] = '-';

    return str;
}

6 Comments

Just have in mind that this code leaks memory. Also, -1 for teaching to typecast the result of malloc in C. Read this and this. Remove the typecast and I'll remove the downvote.
@Lundin: Yes, main() should free the buffer, but IMHO i_to_a() shouldn't be allocating a buffer in the first place. There's no good reason it shouldn't take a preallocated buffer instead. Utility functions that allocate and return buffers are a code smell in my book. Since he's gone and diverged from the MS itoa() interface, he might as well add a length parameter, too, and check for buffer overrun.
@WarrenYoung I agree completely with everything you said.
You also need to check the malloc succeeded. if(str!=NULL) {printf("Malloc failed\n"); /* cleanup */ return;}
Fails for i_to_a(0). Fails for i_to_a(INT_MIN).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.