Go Down

Topic: Is there an easier way to extract a value from a string? (Read 568 times) previous topic - next topic

teddyz

This works:
Code: [Select]
void setup() {
  Serial.begin(115200);
    char l[] = "      <description>030 W/m2</description>";
   
    char * a = strstr(l, " W/m2");
    Serial.println (a); // prints " W/m2</description>"
    if ( a > 0 ) {
      * a = '\0';
      char * b = strstr(l, "<description>");
      Serial.println (b);  // prints "<description>030"
      strcpy (l, b + 13); // Remove the first characters, including "<description>"
      Serial.print ("..>");
      Serial.print (l);
      Serial.println ("<.."); // print "..>030<.."
      Serial.println (atoi(l)*2); // prints "60"
    }     
      l[0] = '\0'; // clear the line variable to test the next line.
}

void loop() {
}


I use it to find a value in a xml-web page. But is there an easier way to examine the line for the value?

And why does it work at all? I haven't included String.h. Because of Serial?

Nick Gammon

Just as a suggestion:

Code: [Select]

    char l[] = "      <description>030 W/m2</description>";


Don't use the variable name "l". It looks very much like one (1). In your code it is easy to confuse l and 1.
http://www.gammon.com.au/electronics

teddyz

Thanks!

But apart from a bad choice of variable name, it is as simple as it can be?

I am longing for a strBeween-function that I could call. That should be useful for many people. I Googled, and found that someone did it for php and c++. Can the latter be changed to compile in Arduino? The compiler complains about new and delete.


Code: [Select]
#include <iostream>
#include <cstring>

//returns substring of searchstr between delimiter1 and delimiter2
char* strbetween(char* searchstr, char* delimiter1, char* delimiter2) {
  //start of delimiter1 in searchstr
  //named betw as it contains substring to be returned
  char* betw = strstr(searchstr, delimiter1);
  //check that delimiter1 is found
  if (betw == 0) {
    return 0;
  }
  //start of delimiter2 in searchstr
  char* after_betw = strstr(searchstr, delimiter2);
  //check that delimiter2 is found
  if (after_betw == 0) {
    return 0;
  }
  //make betw point to start of substring to be returned
  betw += strlen(delimiter1);
  //check that betw is before delimiter2
  if (betw < after_betw) {
    int ret_len = after_betw - betw;
    char* ret = new char[ret_len+1];
    strncpy(ret, betw, ret_len);
    return ret;
  }
  else {
    return 0;
  }
}

void setup() {
  Serial.begin(115200);
  char* str = strbetween("Stephanie", "tep", "ie");
  Serial.println (str);
  delete[] str;
}

void loop() {
}


michinyon

I am a bit concerned by your code.  If you call this function more than once,  are you likely
to be losing memory by sticking nuls in the middle of a character array ?

If you want to extract the numbers in this string,  whats wrong with starting at the beginning,
look at each character until you find a digit 0..9,   then keep reading digits until you don't have
a digit,    and each digit you get,  multiply the previous number by ten and add the most recent
digit ?

zoomkat

Using String functions, you can find the location of the first > in the string, then capture the next ~4 characters, then do the atoi function.

http://arduino.cc/en/Reference/StringObject

http://www.arduino.cc/en/Tutorial/TextString
Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   8)

michinyon

Code: [Select]


int findnum( char* s)
{
   int n ;
   int status=0 ;
   while ( *s != '\0' )
   {
       if ( *s >= '0' && *s <= '9' )
       {
            if ( status == 0 ) // first digit encountered
            {
                n = *s - '0' ;
                status=1 ;
            }
            else // subsequent digits
            {
                n = (10*n)+(*s-'0') ;
            }
       }
       else
       {
            if ( status == 1 ) break ;
       }
       s++ ;
   }
   return n ;
}

zoomkat

There is a textfinder library that can search streaming strings for desired data. I think code has been posted to capture weather data from RSS feeds.

http://playground.arduino.cc/Code/TextFinder
Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   8)

johncc

If your format is quite fixed, don't overlook this possibility:
Code: [Select]

    char s[] = "      <description>030 W/m2</description>";
    int d = atoi(s+10);  // extract integer beginning at s[10]


John

Nick Gammon

If you want some fun you can always use regular expressions:

http://www.gammon.com.au/forum/?id=11063
http://www.gammon.com.au/electronics

PaulS

Quote
I am a bit concerned by your code.  If you call this function more than once,  are you likely
to be losing memory by sticking nuls in the middle of a character array ?

No. The array is static. It can contain any values and not leak memory. Memory leaks can occur only with dynamically allocated memory not being freed.

Go Up