How to convert a string to a number

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
len17
 
Posts: 394
Joined: Sat Mar 14, 2009 7:20 pm

How to convert a string to a number

Post by len17 »

Here's a task that Arduino programming newbies often struggle with: Take a number represented as a string of ASCII digit characters (e.g. "12345") and convert it to an integer variable.

If the string is variable length and null terminated (the usual format for strings in C and Arduino), there's a built-in function to do it. Here's a simple sketch to demonstrate:

Code: Select all

#include <stdlib.h> // for the atol() function

#define numBufSize 11
char numStr[numBufSize] = "3141592654"; // just as an example

void setup()
{
  Serial.begin(115200);
  
  // Convert decimal string in numStr to an unsigned integer in num.
  // The string must be null-terminated!
  unsigned long num;
  num = atol(numStr);
  
  Serial.println(num);
}

void loop()
{
}
If the string is in a fixed length buffer with no null terminator character, it's a bit more complicated:

Code: Select all

#define numBufSize 11
char numStr[numBufSize] = { '0','3','1','4','1','5','9','2','6','5','4' }; // just as an example

void setup()
{
  Serial.begin(115200);
  
  // Convert decimal string in numStr to an unsigned integer in num.
  // The string is in a fixed size buffer.
  // There is no checking for invalid digit characters or number too large.
  unsigned long num = 0;
  for (int i = 0; i < numBufSize; i++) {
    num = num * 10 + (numStr[i] - '0');
  }
  
  Serial.println(num);
}

void loop()
{
}

User avatar
miax
 
Posts: 157
Joined: Tue Apr 05, 2011 11:41 am

Re: How to convert a string to a number

Post by miax »

Thanks for posting this Len! :)

I had seen atol() a few times but never tried it, I can definitely make use of this!

One other challenge I have to overcome is converting a 16-character string that holds a uint32_t (unsigned long), will atol() work for really big numbers? (like what we get out of millis()?

Happy new year! :)

Kris

User avatar
miax
 
Posts: 157
Joined: Tue Apr 05, 2011 11:41 am

Re: How to convert a string to a number

Post by miax »

Here is the crazy function I'm using now to convert a char[16] to unsigned long, and this one only actually works for 10 characters (not 16).

Code: Select all

// Convert an entire string of numbers (max 9) from char to unsigned int.
void XNPconvertSerialToNum()
{
  serialNumber = 0;
  // First flip the string around so we start from the back.
  sprintf(buffer1, "");
  bufferlen = strlen(serialnum);
  for(x = 0; x < bufferlen; x++) {
    if(x == 0) g = bufferlen - 1;
    if(x == 1) g = bufferlen - 2;
    if(x == 2) g = bufferlen - 3;
    if(x == 3) g = bufferlen - 4;
    if(x == 4) g = bufferlen - 5;
    if(x == 5) g = bufferlen - 6;
    if(x == 6) g = bufferlen - 7;
    if(x == 7) g = bufferlen - 8;
    if(x == 8) g = bufferlen - 9;
    if(x == 9) g = bufferlen - 0;
    sprintf(buffer2, "%c", serialnum[g]);
    strcat(buffer1, buffer2);
  }
  bufferlen = strlen(buffer1);
  if(bufferlen > SERIAL_LENGTHS) {
    bufferlen = SERIAL_LENGTHS;
  }
  // Now parse the individual numbers out. 
  sprintf(buffer3, "");
  for(x = 0; x < bufferlen; x++) {
    sprintf(buffer2, "%c", buffer1[x]);
    g = XNPconvertLetterToNumber();
    if(x == 0) {
      serialNumber += g;
    } else if(x == 1) {
      if(g > 0) {
        serialNumber += (g * 10);
      }
    } else if(x == 2) {
      if(g > 0) {
        serialNumber += (g * 100);
      }
    } else if(x == 3) {
      if(g > 0) {
        serialNumber += (g * 1000);
      }
    } else if(x == 4) {
      if(g > 0) {
        serialNumber += (g * 10000);
      }
    } else if(x == 5) {
      if(g > 0) {
        serialNumber += (g * 100000);
      }
    } else if(x == 6) {
      if(g > 0) {
        serialNumber += (g * 1000000);
      }
    } else if(x == 7) {
      if(g > 0) {
        serialNumber += (g * 10000000);
      }
    } else if(x == 8) {
      if(g > 0) {
        serialNumber += (g * 100000000);
      }
    } else if(x == 9) {
      if(g > 0) {
        serialNumber += (g * 1000000000);
      }
    }
  }
}
// This converts a String with a single number [0-9] and returns the numeric integer.xyzzy
int XNPconvertLetterToNumber()
{
  if(!strcmp (buffer2, "0")) return(0);
  if(!strcmp (buffer2, "1")) return(1);
  if(!strcmp (buffer2, "2")) return(2);
  if(!strcmp (buffer2, "3")) return(3);
  if(!strcmp (buffer2, "4")) return(4);
  if(!strcmp (buffer2, "5")) return(5);
  if(!strcmp (buffer2, "6")) return(6);
  if(!strcmp (buffer2, "7")) return(7);
  if(!strcmp (buffer2, "8")) return(8);
  if(!strcmp (buffer2, "9")) return(9);
}

User avatar
len17
 
Posts: 394
Joined: Sat Mar 14, 2009 7:20 pm

Re: How to convert a string to a number

Post by len17 »

Yes, atol() does 32-bit numbers. The number in my example has 32 significant bits, and it's printed to the serial port to prove that it works right. :)

User avatar
miax
 
Posts: 157
Joined: Tue Apr 05, 2011 11:41 am

Re: How to convert a string to a number

Post by miax »

Awesome, Thanks again Len!

I'll try that out and report back on how it works. :)

Cheers,

Kris

User avatar
miax
 
Posts: 157
Joined: Tue Apr 05, 2011 11:41 am

Re: How to convert a string to a number

Post by miax »

Lin,

atol() works like a charm. :) Thank you! You just shorted my code by almost 100 lines!

The longer method however did not seem to work, not that I need it, but here are some results:

NewConverter starting with [35233681], atol = (35233681), long method: (4030294960), OldStype :[35233681]

Thanks again for all the help. :)

Cheers!

Kris

User avatar
len17
 
Posts: 394
Joined: Sat Mar 14, 2009 7:20 pm

Re: How to convert a string to a number

Post by len17 »

From your code, I see you're using null-terminated strings, so atol() is the right way to go.

The other method is for fixed-length data. It knows how many digits there are so it just adds them all up. But in your case, your buffer has the digits ("35233681") followed by a null char and a few random unused bytes. Adding up all that will not give you the right answer.

stephanie
 
Posts: 295
Joined: Sat Dec 11, 2010 1:17 am

Re: How to convert a string to a number

Post by stephanie »

I don't know if this is re-inventing the wheel but this is the function I use for converting a string object to an integer value. In a sketch I was working on, I was using string objects rather than char arrays, and atoi didn't work with the string objects. This simple function just converts the string to a null terminated char array then uses atoi on that.

Cheers!

Code: Select all

int stringToNumber(String thisString) {
  int i, value, length;
  length = thisString.length();
  char blah[(length+1)];
  for(i=0; i<length; i++) {
    blah[i] = thisString.charAt(i);
  }
  blah[i]=0;
  value = atoi(blah);
  return value;
}

User avatar
philba
 
Posts: 387
Joined: Mon Dec 19, 2011 6:59 pm

Re: How to convert a string to a number

Post by philba »

If you're going to iterate over the string, might as well just add it up. Faster and smaller.

Code: Select all

int stringToNumber(String thisString) {
  int i, value = 0, length;
  length = thisString.length();
  for(i=0; i<length; i++) {
    value = (10*value) + thisString.charAt(i)-(int) '0';;
  }
  return value;
}

User avatar
waspinator
 
Posts: 3
Joined: Thu Oct 06, 2011 8:49 pm

Re: How to convert a string to a number

Post by waspinator »

Code: Select all

// convert arduino String to int
int stringToInt(String string){
  
  char char_string[string.length()+1];
  string.toCharArray(char_string, string.length()+1);
  
  return atoi(char_string);
}

User avatar
miax
 
Posts: 157
Joined: Tue Apr 05, 2011 11:41 am

Re: How to convert a string to a number

Post by miax »

Thanks for the replys! :) Unfortunately real-life took alot more of my time last year than in previous years, and I didn't really get alot of "Making" done in Q3/Q4 2012 and the first part of this year. Since then I've fallen in love with Robotics, and have had to weigh the pro's and con's of continuing/completing a number of projects I was working on. Had I been lucky-enough to work for a real Maker company, I'm sure my time would be much more Maker-involved.

As it stands, I have not worked on XNP for many months! As I learned more and more about XBee, I found it was alot easier and more efficient to use the built-in XBee mesh protocols that are available with the Series-2 pro modules. They cost a few more bucks per unit, but all packet processing is off-loaded on the XBee chip, leaving the micro-controller free to do other things. I plan to release a final version of XNP sometime this year, depending on my work, home and hobby/project schedule, but honestly the XBee protocols are making huge strides in capability, and XNP may or may not make sense anymore.

Still the challenge of converting strings to numbers At Very High Speed is always a good one, and I appreciate the responses! :)

Cheers,

Kris

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”