Converting a string to integer in C for arduino

426 Views Asked by At

I'm trying to use the ATOI library function in C for Arduino to convert a string to an unsigned int. Out of all number data types I have chosen unsigned int as the number range does not need to be negative, and does not need a large positive number range. The highest would be 300000.

After researching I have found that the maximum number ATOI can spit out is 32767 before it then starts producing garbage (according to this forum post https://forum.arduino.cc/t/maximum-atoi-string/87722 ).

I have had a look around at some other library functions to handle a number of this size, but they seem to support other number data types (such as long, signed ect) but i'm a little oferwhelmed with one that would suit best, and just wanted to check here first to see if anyone else knew of a solution.

Thanks in advance.

2

There are 2 best solutions below

0
Lundin On BEST ANSWER

The atoi (family of functions) should never be used for any purpose, since they don't have proper error handling.

The strtol (family of functions) should be used instead. It is equivalent except it has error handling and supports other bases than decimal as an option.

Furthermore, you seem unaware that AVR is using 16 bit integers, so an unsigned int will only have the range 0 - 65535. If you need numbers up to 300000, you must use unsigned long.

Therefore the function you are looking for is strtoul from stdlib.h. Usage:

#include <stdlib.h>
unsigned long x = strtoul(str, NULL, 10);

Please note that using the default "primitive data types" of C in embedded programming is naive. As you've noticed, they are nothing but trouble since their sizes aren't portable. Professional programmers always use stdint.h types and never anything else. In this case uint32_t.

7
kcsoft On

You can try implementing your own, something like this


const unsigned long fast_atoi_map [] = {
  0, 10, 20, 30, 40, 50, 60, 70, 80, 90,
  0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
  0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000,
  0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000,
  0, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000,
};

unsigned long fast_atoi(char *str, unsigned char length) {
  unsigned long val = 0;
  const unsigned long *imap = fast_atoi_map + (length - 2) * 10;
  while (length-- > 1) {
    val = val + *(imap + (*str++ - '0'));
    imap -= 10;
  }
  return val + (*str - '0');
}