3

Without resorting to standard library utoa, I'm looking for source code of utoa so I may customise it for specific project. I have unsigned integer (32 bits) with output such as 0xFFFF_FFFF

I also looking for source code for unsigned integer and half word to string in binary format.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Riscy
  • 843
  • 4
  • 13
  • 28

6 Answers6

7

Try this:

char *dec(unsigned x, char *s)
{
    *--s = 0;
    if (!x) *--s = '0';
    for (; x; x/=10) *--s = '0'+x%10;
    return s;
}

You call it with a pointer to the end of a caller-provided buffer, and the function returns the pointer to the beginning of the string. The buffer should have length at least 3*sizeof(int)+1 to be safe.

Of course this is easily adapted to other bases.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Thank, I give it a go for base 16 (hex). – Riscy Aug 03 '11 at 02:47
  • For base 16 you'll need to either special-case digits <10 and >=10 separately or use Kerrek's string indexing solution. – R.. GitHub STOP HELPING ICE Aug 03 '11 at 03:01
  • Very clever! I have a question though: why do you decrease the pointer to assign the null terminator at the beginning of the function? It seems to me that you are loosing one byte of the buffer that way. Why not *s = 0? – Nedo Apr 16 '20 at 08:22
  • 1
    @Nedo: By "end" I meant one past the last index, i.e. `buf + sizeof buf`. IMO this is the standard idiom foror "end" in C; the other version has off-by-one quirks comparable to one-based indexing. – R.. GitHub STOP HELPING ICE Apr 16 '20 at 14:47
3

Theres a lot of itoa source files easily found on google... That should give you what you want, eg. itoa from opensource.apple.com

Or write it from scratch, it's not too hard.

sg7
  • 6,108
  • 2
  • 32
  • 40
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
1

Most of the functions mentioned/suggested here uses modulus % operator, which is very expensive for embedded system.

So using divide by 10 idea is the only prominent option I guess. Here it is:

/*for byte which is 3 digit most*/


void itoa(unsigned char value,char *desitination)
{
desitination[0] = '\0';
desitination[1] = '\0';
desitination[2] = '\0';
desitination[3] = '\0';//you at least 4 char array, last char is NULL
while (value >= 100)
{
    desitination[0]++;
    value -= 100;
}
desitination[1] = '0';

while (value >= 10)
{
     desitination[1]++;
     value -= 10;
}
value+= '0';
desitination[2] =value;
}
Biddut Mitra
  • 165
  • 4
1

That's not terribly hard. Keep dividing by 10 and use the remainder mod 10 as an index into "0123455679". You build this up from right to left, so you have to buffer the result and return it in reverse:

char * utoa(unsigned int n)
{
  char * res, buf[30]; // long enough for largest number
  unsigned int i, counter = 0;

  if (n == 0)
    buf[counter++] = '0';

  for ( ; n; n /= 10)
    buf[counter++] = "0123456789"[n%10];

  res = malloc(counter);

  for (i = 0; i < counter; ++i)
    res[i] = buf[counter - i - 1];

  return res;
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 5
    I'm struggling to resist giving -1 to a useless-use-of-`malloc` as an answer to an **embedded systems** question... – R.. GitHub STOP HELPING ICE Aug 03 '11 at 01:49
  • Well, you have to put the result *somewhere*. I trust the OP is flexible enough to adapt this to her needs, as this detail has clearly nothing to do with the basic algorithm! – Kerrek SB Aug 03 '11 at 01:53
  • That's why I didn't -1 it. But really, those of us who know better should be setting a good example, rather than leaving it to the OP to fix the solution (and I'd guess a good half of question-askers would "fix" your answer to use a `static` buffer rather than a caller-provided buffer, which is not a good thing...) – R.. GitHub STOP HELPING ICE Aug 03 '11 at 01:57
  • 1
    By the way, indexing into `"0123456789"` is just a really inefficient way to write `'0'+n`, and the latter is not a hack, it's required to work as part of the language. – R.. GitHub STOP HELPING ICE Aug 03 '11 at 02:13
  • The former allows for arbitrary symbols, though :-) But use whatever floats your boat. (About "really inefficient": My method causes **one** additional assembly instruction over `'0'+n%10`...) – Kerrek SB Aug 03 '11 at 02:17
  • 2
    And 11 bytes of constant string data. :-) In PIC libraries, it can also introduce a GOT-register dependency (for relative addressing) into a function that otherwise would have been purely position-independent even without `-fPIC`. – R.. GitHub STOP HELPING ICE Aug 03 '11 at 02:30
1
#include <stdint.h>
#include <string.h>

char * utox(uint32_t n) {
    static char hexstr[sizeof(n)*2+1];
    char * p = hexstr + sizeof(hexstr) -1;
    int x;

    memset(hexstr, '0', sizeof(hexstr));

    *p-- = '\0';

    while (n) {
        x = n % 16;
        if (x < 10)
            *p-- = '0' + x;
        else
            *p-- = 'A' + x - 10;

        n /= 16;
    }

    return hexstr;
}

This should do it, it zero pads. Simply changing the type of n in the function parameters will make it work for any integer type/size.

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43
  • Obviously, this solution is not thread-safe. (Not that the OP cited that as a requirement.) – EboMike Aug 03 '11 at 16:31
  • It is an embedded system, usually this is fine unless he wants to use that in a ISR or with a threaded RTOS. I like this solution most of the time because I can be sure of the array bounds so its safer. It is trivial to instead of manage the array myself, operate on a pointer. – Vinicius Kamakura Aug 03 '11 at 16:42
  • My preferred solution is to have the caller pass a buffer (and buffer size) in. But hey, many roads lead to Rome... – EboMike Aug 03 '11 at 21:58
0

There are many implementation of itoa. This is one of them which takes under consideration base from 2 to 36:

/**
 * C++ version 0.4 char* style "itoa":
 * Written by Lukás Chmela
 * Released under GPLv3.

 */
char* itoa(int value, char* result, int base) {
    // check that the base if valid
    if (base < 2 || base > 36) { *result = '\0'; return result; }

    char* ptr = result, *ptr1 = result, tmp_char;
    int tmp_value;

    do {
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    } while ( value );

    // Apply negative sign
    if (tmp_value < 0) *ptr++ = '-';
    *ptr-- = '\0';
    while(ptr1 < ptr) {
        tmp_char = *ptr;
        *ptr--= *ptr1;
        *ptr1++ = tmp_char;
    }
    return result;
}

More variations can be found here which includes speed performance of the various implementations.

sg7
  • 6,108
  • 2
  • 32
  • 40