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

user1089679
  • 2,328
  • 8
  • 41
  • 51

4 Answers4

7

Thing is snprintf is the perfect function for this:

char str[LEN];
snprintf(str, sizeof(str), "%d", num);
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • snprintf for avoiding overflow, but otherwise the correct advice -- or just ignore me, because I can't read, apparently... – tbert Apr 03 '12 at 14:01
  • 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 Apr 04 '12 at 13:04
  • @Lundin Ah, I see. I guess it makes sense :-) – cnicutar Apr 04 '12 at 13:50
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';
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    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. – Warren Young Apr 04 '12 at 13:48
  • 1
    @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. – Lundin Apr 04 '12 at 14:11
  • 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. – Lundin Apr 04 '12 at 14:11
  • 1
    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. – Warren Young Apr 04 '12 at 14:17
  • @WarrenYoung Why would anyone ever pass a buffer longer than 11 characters to the function? ULONG_MAX = 4294967295. 10 digits + 1 null term as worst case. Also, "len" in this case is the number of digits that the function should hand out, _not_ the buffer size. – Lundin Apr 04 '12 at 15:40
  • "ULONG_MAX = 4294967295". On 32-bit platforms, yes. And, you've never just casually defined a "big enough" buffer? Anyway, these comments are the warning. :) – Warren Young Apr 04 '12 at 17:14
  • @WarrenYoung uint32_t will be 32 bit no matter platform. – Lundin Apr 04 '12 at 20:50
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;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • 1
    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. :) – Warren Young Apr 04 '12 at 13:30
  • 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? – BLUEPIXY Apr 04 '12 at 13:50
  • I don't have to take my point away,too. but tentatively tried to fix. – BLUEPIXY Apr 04 '12 at 15:12
  • 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. – Warren Young Apr 04 '12 at 17:20
  • 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. – BLUEPIXY Apr 04 '12 at 22:32
-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;
}
user1089679
  • 2,328
  • 8
  • 41
  • 51
  • Just have in mind that this code leaks memory. Also, -1 for teaching to typecast the result of malloc in C. Read [this](http://c-faq.com/malloc/mallocnocast.html) and [this](http://stackoverflow.com/questions/1565496/specifically-whats-dangerous-about-casting-the-result-of-malloc). Remove the typecast and I'll remove the downvote. – Lundin Apr 04 '12 at 13:04
  • 1
    @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. – Warren Young Apr 04 '12 at 13:41
  • @WarrenYoung I agree completely with everything you said. – Lundin Apr 04 '12 at 14:03
  • You also need to check the malloc succeeded. if(str!=NULL) {printf("Malloc failed\n"); /* cleanup */ return;} – jmc May 16 '12 at 08:53
  • Fails for `i_to_a(0)`. Fails for `i_to_a(INT_MIN)`. – chux - Reinstate Monica May 05 '15 at 17:28
  • As for the _(0)_ case, it's enough to reverse the _whiles_ into _do-whiles_ – jalooc Oct 29 '15 at 17:51