How to pull an int from char string

Here is a quick sample sketch describing what I am trying to accomplish.

char signal;
int signalStrength;

void setup(){}
void loop(){
  signal='+CSQ: 18,0';//code to be parsed
  //extraction code I need help with
  signalStrength='18';//pull just the number 18 as an int.
  //This number will change and can be a number from 1 - 99. So, either single or dual digit. 
}

I am new to arduino so If you could post an example, that would help. Thanks in advance.

char signal;
  signal='+CSQ: 18,0';//code to be parsed

No, sorry, 10 into one doesn't go.

  signal='+CSQ: 18,0';//code to be parsed

Sorry, like I said, I am new at this. Used to PHP. This is just an example code btw. So for this corrected code,

String signal;
int signalStrength = 0;

void setup(){}
void loop(){
  signal="+CSQ: 18,0";//code to be parsed
  //extraction code I need help with
  signalStrength=18;//pull just the number 18 as an int.
  //This number will change and can be a number from 1 - 99. So, either single or dual digit. 
}

How would I make this function to pull the number from the string to an int?

same as in PHP? with sscanf() ?

ironchariot:
Sorry, like I said, I am new at this. Used to PHP. This is just an example code btw. So for this corrected code,

I have a program I wrote for a different purpose, but part of it may help you. I just ripped this out of my code and edited it slightly for your use... may need a touch or two... but the idea is there:

int parse (const char *str)
{
        const char *find = "+CSQ: ";
        char *ptr;
        int x, y;
        int length;

        length = strlen (find)-1; /* how many chars to find */
        ptr = str; /* pointer to string */

        y = 0;

        /*
         *  "|     |<--- parse to here
         *  "+CSQ: 18,0 <-- then atoi() the value
         */

        for (x = 0; x < count; x++) {
                if (str[x] == find[y]) {
                        if (y == length) {
                                ptr += x; /* move pointer to start of number */

                        } else {
                                y++;
                        }

                } else {
                        y = 0;
                }
        }

        return atoi (ptr);
}

Use: int value = parse ("your string");

Hope this helps you......

Krupski:
I have a program I wrote for a different purpose, but part of it may help you. I just ripped this out of my code and edited it slightly for your use... may need a touch or two... but the idea is there:

I may be doing it wrong. I keep getting

error: invalid conversion from 'const char*' to 'char*'

on

ptr = str; /* pointer to string */

Simple code you can try by sending your string via the serial monitor.

String readString, number;

void setup() {
  Serial.begin(9600);
  Serial.println("number test"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(2);  
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
    Serial.print("readString is: ");
    Serial.println(readString); //see what was received
    Serial.println();

    // expect a string like +CSQ: 18,0
    number = readString.substring(6, 10); //get characters from readString 

    Serial.print("number String is: ");
    Serial.println(number); //see what substrring is
    Serial.println();

    //int will get numerals until it reaches a non numeral character
    int  n = (number.toInt()); 
    
    Serial.print("your number is: ");
    Serial.println(n);

    readString="";

  } 
}

ironchariot:

Krupski:
I have a program I wrote for a different purpose, but part of it may help you. I just ripped this out of my code and edited it slightly for your use... may need a touch or two... but the idea is there:

I may be doing it wrong. I keep getting

error: invalid conversion from 'const char*' to 'char*'

on

ptr = str; /* pointer to string */

Yeah I goofed. As I said, I pulled it out of another program I had and tried to tie up the loose ends.

The "int parse (const char *str)" thing should be "int parse (char *str)" (take out the "const" part).

Here's the whole demo.... tested too!

void setup (void)
{
	Serial.begin (115200);
	char *string = "+CSQ: 18,0";
	int value;
	value = parse (string);
	Serial.print ("Parsed ");
	Serial.print (value, DEC);
	Serial.print (" from ");
	Serial.print (string);
	Serial.println();
}

void loop (void)
{
}

int parse (char *str)
{
        const char *find = "+CSQ: ";
        char *ptr;
        int x, y;
        int length;
	int count = strlen (str);

        length = strlen (find)-1; /* how many chars to find */
        ptr = str; /* pointer to string */

        y = 0;

        for (x = 0; x < count; x++) {
                if (str[x] == find[y]) {
                        if (y == length) {
                                ptr += x; /* move pointer to start of number */

                        } else {
                                y++;
                        }

                } else {
                        y = 0;
                }
        }

        return atoi (ptr);
}

Krupski:

ironchariot:

Krupski:
I have a program I wrote for a different purpose, but part of it may help you. I just ripped this out of my code and edited it slightly for your use... may need a touch or two... but the idea is there:

I may be doing it wrong. I keep getting

error: invalid conversion from 'const char*' to 'char*'

on

ptr = str; /* pointer to string */

Yeah I goofed. As I said, I pulled it out of another program I had and tried to tie up the loose ends.

The "int parse (const char *str)" thing should be "int parse (char *str)" (take out the "const" part).

Here's the whole demo.... tested too!

void setup (void)

{
Serial.begin (115200);
char *string = "+CSQ: 18,0";
int value;
value = parse (string);
Serial.print ("Parsed ");
Serial.print (value, DEC);
Serial.print (" from ");
Serial.print (string);
Serial.println();
}

void loop (void)
{
}

int parse (char *str)
{
        const char *find = "+CSQ: ";
        char *ptr;
        int x, y;
        int length;
int count = strlen (str);

length = strlen (find)-1; /* how many chars to find /
        ptr = str; /
pointer to string */

y = 0;

for (x = 0; x < count; x++) {
                if (str[x] == find[y]) {
                        if (y == length) {
                                ptr += x; /* move pointer to start of number */

} else {
                                y++;
                        }

} else {
                        y = 0;
                }
        }

return atoi (ptr);
}

That did it!!!!! Thank you. I have spent days on this. I need to buy you a beer.

Seems way more complicated than using sscanf().

int parse(char *str)
{
int count = 0;

        sscanf(str, "+CSQ:%d", &count);

        return(count);
}

And sscanf could easily be used to parse all the other fields as well.

--- bill

bperrybap:
Seems way more complicated than using sscanf().

int parse(char *str)

{
int count = 0;

sscanf(str, "+CSQ:%d", &count);

return(count);
}




And sscanf could easily be used to parse all the other fields as well.

--- bill

Thanks Bill. This is a lot shorter. I am having an issue with it, which is my fault. In the original post, I said the content of my string was:

+CSQ: 18,0

I got this from serial data copied to a string from a GPRS chip. It turns out that what is really saved in the string is this.

AT+CSQ

+CSQ: 18,0

I am a total newbee when it comes to this stuff. How can I modify your code to read those line breaks?I tried this but it didnt work.

int parse(char *str)
{
int count = 0;

        sscanf(str, "AT+CSQ/n/n+CSQ:%d", &count);

        return(count);
}

Easy to understand code:

//number parse 12/13/13 zoomkat
String readString, numberString;

void setup() {
  Serial.begin(9600);
  Serial.println("number test"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(2);  
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    } 
  }

  if (readString.length() >0) {
    Serial.print("readString is: ");
    Serial.println(readString); //see what was received
    
    // expect a string like AT+CSQn\n\n+CSQ: 18,0
    int pos = readString.indexOf(' ');
    numberString = readString.substring(pos+1); //get characters from readString 

    Serial.print("number String is: ");
    Serial.println(numberString); //see what substrring is
    
    //int will get numerals until it reaches a non numeral character
    int  n = (numberString.toInt()); 
    
    Serial.print("your number is: ");
    Serial.println(n);
    Serial.println();

    readString="";
    numberString="";
  } 
}

ironchariot,
it is worth spending some time reading over the documenation and getting familiar with these types of libC functions.
My choice is to use the 40+ year old functions that were created to make life easier whenever possible, rather
than write custom string parsing since it often is not necessary.
(But then I've been using unix platforms for more than 30 years)
Once you start to get familiar with them you will find that they tend to be very consistent.
Another good thing is that versions of these functions tend to available across many languages.

A few things:
A newline is not /n a newline is \n
Keep in mind that a newline is considered white space and not a normal character when parsing the line for input.
There is information about the parsing of white space if you read the man page
for sscanf()

If all you want to do is throw away the first 2 strings before a number, then that would be:

int parse(char *str)
{
int count = 0;
        sscanf(str, "%*s%*s%d", &count);
        return(count);
}

If you want an EXACT match, then use this:

int parse(char *str)
{
int count = 0;
        sscanf(str, "AT+CSQ\n\n+CSQ:%d", &count);
        return(count);
}

If you just want the integer just after a colon you could use:

#include <string.h>
int parse(char *str)
{
char *p;
int count = 0;
        p = strrchr(str, ':'); // find last colon
        if(p)
        {
                p++; // skip over colon
                count = atoi(p);
        }
        return(count);
}

And like I said before the nice thing about sscanf() is that you could also use it to extract
whatever you want/need into other variables
in case you want/need other information from the string besides this single number.
i.e. you might want to look at the various other strings returned.

--- bill

Also: