Go Down

Topic: Is there an easier way to extract a value from a string? (Read 639 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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
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
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

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
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

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
Please post technical questions on the forum, not by personal message. Thanks!

More info:
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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy