Pages: [1]   Go Down
Author Topic: string replace?  (Read 1096 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

does it exist? I could only find TextString which showed
void replace(char thisChar, char thatChar) - Replaces all the occurrences thsChar with thatChar

but I can't get it to work..

it errors for me.
I tried inString.replace(char* "<data value=", "");

and it says

error: expected primary-expression before 'char


I need to replace or find stuff as I'm trying to parse some xml..

thanks. sorry if this is a dumb question. I've been at it all morning and afternoon...
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Rock n' Rolling with Arduino.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

2 things:
First off, it looks like that function doesn't take a string/char array, it takes a single character, and replaces only that.

TextString has String::contains(char* Substring), but no replacement functions, as far as I can tell.

Try something like this, maybe:
Code:
//using 'MyString' to represent whatever your string is
char * MyString = whateveryourstringis.

//we find every instance of the string to delete, and cut it out
char * string_to_delete = "<data value=";
int length_to_delete = strlen(string_to_delete);
char * start_of_deleted_data = strstr(MyString,string_to_delete);

//strstr will return a NULL pointer if the substring wasn't found
//otherwise, it will return a pointer to the start of the substring
while(start_of_deleted_data != NULL)
{
  //delete the substring, by shifting everything in the string over by length_to_delete
  for (int i=0; i<length_to_delete; i++)
  {
     start_of_deleted_data[i] = start_of_deleted_data[i+length_to_delete];
  }
  //search for the next instance of the string
  char * start_of_deleted_data = strstr(MyString,string_to_delete);
}

My code there is NOT complete. At least one error I can see right away is that it will go a bit crazy if your string to delete is at the very end or near the end of your big string.

The second problem, that any solution will have, is possible memory leaks. If you're allocating your strings dynamically (using malloc), which is what TextString seems to do, then when you shorten a string, you have to make sure to free() the freed area.

If you allocate statically (declaring a big buffer, and using that), you can just overwrite that whenever new data comes in.

Let me know if this is helpful at all.

edit: I realize my example code can be kind of thick if you're not familiar with pointers or string manipulation, so I'll try to find some useful links, and explain my code a bit better, if you want.
« Last Edit: May 30, 2009, 11:42:10 am by YenTheFirst » Logged

It's not stupid, it's advanced

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6250
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi fyrebug, TextString has been replaced with  the String library. It has methods to find characters and strings and can replace characters. Do you really need to substitute strings in place rather than append found values to a new string?

Could you show an example (perhaps in pseudocode) of what you are trying to do.
« Last Edit: May 30, 2009, 12:48:35 pm by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi mem.

what I'm doing is reading xml lines from the web, and then try to get values from them.

example.
<data value="5"></data>

so I'd want to read the string and get back the number 5.
string replace seemed the easiest way. I could just remove the first and last part of the string and be left with only the number 5.

 @yenthefirst I completely appreciate your example I think I'm just not comfortable enough in arduino yet to fully understand it.
I'm coming from a php/actionscript background.
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6250
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the code I use to parse web pages with Arduino.  This fragment is part of an application that uses the Ethernet shield  and I have left out some of the Ethernet specific code but I hope it gives you an idea of how to do parsing.

This code uses two classes that I intend to  make into a library when I find the time. I hope the lack of documentation does not prevent its use as is.
Code:
class FindFieldClass {
  private:
     int  index;
     char *target;
     int  targetLen;
  public:
     void begin(char *target){ // set the target string to find
       this->target = target;    
       this->index = 0;
       this->targetLen = strlen(target);
     }
     boolean find(char c){  
        if( c == target[index])
        {
           if(++index >= this->targetLen)
              return true;
           else          
              return false;          
        }
        else{
           index = 0;
        }
     }  
};

class GetFieldClass {
  private:
     int  index;
     char startChar;
     char endChar;
  public:
     char  buffer[10]; // this buffer holds the field value if seek returns true

     void begin(char start, char end){ // set the start and end character that defines the field
       this->startChar = start;    
       this->endChar = end;
       index = -1; // index indicates position,  -1 means waiting for start char
     }
     boolean seek(char c){  // service function returns true when the field is found
         if( index == -1){
            if( c == this->startChar)
               index = 0;
         }
         else if( c == this->endChar){                      
            buffer[this->index] = 0; // terminate the string
            return true;
         }
         else{
           // its a field char so save in buffer
            buffer[index] = c;
            if( this->index < sizeof(buffer))
               this->index++ ;  
         }
         return false;
     }  
};

FindFieldClass findField;
GetFieldClass getField;


void setup()
{
  //  Ethernet.begin(mac, ip);
  Ethernet.begin(mac, ip, gateway, subnet);
  Serial.begin(9600);
  findField.begin("<data value="); // the field to search for

  delay(1000);

  Serial.println("connecting...");

  if (client.connect()) {
    Serial.println("connected");
    client.println("Your web page here"); // todo
    client.println("User-Agent: AVR ethernet");
    client.println();
  }
  else
  {
    Serial.println("connection failed");    
  }
}

void loop()
{

  if (client.available()) {
    char c = client.read();
    if (findField.find(c) == true)
    {
      getField.begin('\"', '\"');  // get the value between the quotes
      do
      {
          c = client.read();
      }
      while(getField.seek(c) == false);
      // after closing delimter has been found
     Serial.println(" !!! found field");
     Serial.println(getField.buffer);
     value = atof(getField.buffer);
     Serial.println(value);
    }
    ///---
    
    if (!client.connected())
    {
      Serial.println();
      Serial.println("disconnecting.");
      client.stop();
      delay( 30 * 1000); // wait 30 seconds  
    }
  }
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Rock n' Rolling with Arduino.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You wouldn't really need to use replace, you just need to find the number and copy it into a new string.

mem's class does basically the same thing, but wraps it up in an easy-to-use library.

Here's another example, this one should be easier to understand.
Two things to remember when dealing with strings on arduino:
1) strings are basically just arrays of characters. I think PHP treats them a bit differently than regular arrays, but on arduino, they're just arrays, with the last element being '0' (to mark the end of the string)

2)pointers point to the beginnings of arrays, or a place in arrays.
Code:
1: char  MyString[] = whateveryourstringis;

2: char  string_to_find[] = "<data value=";
3: int length_of_find = strlen(string_to_find);

4: char * start_of_field = strstr(MyString,string_to_find);

5: char * start_of_data = start_of_field + length_of_find;

6: char CopiedData[80];

7: int index=0;
8: while(start_of_data[index] != ''')
9: {
10:  CopiedData[index] = start_of_data[index];
11:  index++;
12:}
13:CopiedData[index] = 0;

Explanation:
(lines 1-4) First, find where the data field is. We find the string "<data value='", and point to that position.
As an example:
<someotherdata><data value='5'><otherstuff>
                              ^
(line 5) Then, we move a pointer over, to where the data actually starts
<someotherdata><data value='5'><otherstuff>
                                                  ^
(line 6) We'll hold our copied data in CopiedData.
(lines 7-13)Then, we'll loop, and copy all that data to CopiedData.

(line 10) In every loop, we copy over a single character from the data to our CopiedData buffer,
(line 11) and then go to the next spot
(line smiley-cool when we've reached the end of the data (the other ' ), we stop copying,
(line 13) and put a 0 at the end of the copied data to mark the end


Hopefully, this example is a bit easier to understand. smiley
Another thing to note, though: no matter how you get the data out of the string, you're going to have string data, not a number. So, if you actually have to use the number for something, you'll have to convert from that string to a number.
Logged

It's not stupid, it's advanced

Pages: [1]   Go Up
Jump to: