-3

What is the best way(optimized by speed) to convert a short number to ascii in C (-1,5,1000 to "-1","5","1000").

I need it for embedded MCU, so the sprintf() is not an option.

Thanks

user3428151
  • 449
  • 6
  • 23

1 Answers1

0

As @Potatoswatter succinctly comments, use standard itoa() is you have it.

As to what is fastest: best to profile candidate solutions. What works best on one platform may differ on another.

Below is an alternative implementation. Flowing is a tight recursive solution that does not need to reverse its results. It works for all int: [INT_MIN, INT_MAX] as it works with the negative side of int which is the same size or larger than the positive side.

static char *itoa10_helper(int n, char *s) {
  if (n <= -10) {
    s = itoa10_helper(n / 10, s);
  }
  *s = (char) ('0' - n % 10);
  return ++s;
}

char* itoa10(int n, char *s) {
  if (n < 0) {
    *s = '-';
    *itoa10_helper(n, s+1) = 0;
  } else {
    *itoa10_helper(-n, s) = 0;
  }
  return s;
}

#include <limits.h>
#include <stdio.h>
#define INT_MAX_SIZE (sizeof (int)*CHAR_BIT/3 + 3)

int main(void) {
  char buf[INT_MAX_SIZE];
  puts(itoa10(0, buf));
  puts(itoa10(123, buf));
  puts(itoa10(INT_MAX, buf));
  puts(itoa10(INT_MIN, buf));
  return 0;
}

A fast solution, that returns a pointer somewhere in the buffer provided follows:

#include <stdbool.h>

char* itoa10f(int n, char *buf) {
  char *s = buf + INT_MAX_SIZE - 1;
  *s = '\0';
  bool isnegative = n < 0;
  if (!isnegative) {
    n = -n;
  }
  do {
    *(--s) = (char) ('0' - n % 10);
  } while (n /= 10);
  if (isnegative) {
    *(--s) = '-';
  }
  return s;
}
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    In other words, use `itoa`. – Potatoswatter Apr 06 '15 at 14:41
  • In what standard is `itoa` "standard"? – AnT stands with Russia Apr 06 '15 at 15:56
  • @AnT `itoa()` is commonly found in many compilers over last decades: Unix, [Xenix](http://www.polarhome.com/service/man/?qf=itoa&af=0&tf=2&of=Xenix), Kernighan and Ritchie, Borland/Turbo C, and many embedded platforms, I've never seen it as a standard function in [C spec](http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents) nor is it presently (if ever) in [Linux](http://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux). It's common as the C standard alternative `sprintf(buf, "%d", i)` is expensive as in embedded platforms. – chux - Reinstate Monica Apr 06 '15 at 16:16
  • What is the value of CHAR_BIT? – user3428151 Apr 08 '15 at 06:14
  • @user3428151 `CHAR_BIT` is found in ``. It is often 8. Did not `#include #define INT_MAX_SIZE (sizeof (int)*CHAR_BIT/3 + 3)` compile for you? What compiler are you using? – chux - Reinstate Monica Apr 08 '15 at 13:26
  • it is compiled, It works, but still for my embedded issues it is slow, have 15 int numbers that i need to print over UART to PC, UART is 2M MCU 28MHz DATA ready sampled at 1.6Mh – user3428151 Apr 08 '15 at 14:03
  • @user3428151 1) consider transmitting as hexadecimal characters, certainly faster to convert to `0-9,A-F` than decimal. 2) A UART transmitting at 2M baud (2 Mbits/sec) cannot keep up with data sampled at 1.6MHz even if conversion time was 0 seconds unless code sends less than < 2.0 _bits_ per sample. Transmitting `"1000"` would take 4*10 bits. Suggest re-think / clarify goals. – chux - Reinstate Monica Apr 08 '15 at 15:07