Any way to do "Explode" array in Arduino?

// My array look like this in string
var str = ‘one|two|three|four’;

// is there a function like EXPLODE in Arduino?
Serial.println(explode(’|’, str, -1));

If not, any method to do something similar? Thanks in advance if anyone has any clue :slight_smile:

Try the "strsep()" function (in avr-libc or most standard C libraries.)

strsep()

Personally, I would go with strtok(). But whatever... http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html#ga6ace85338eafe22a0ff52c00eb9779b8

Personally, I would go with strtok().

I agree. strsep() is more like "explode()" from PHP/etc, but strtok() is more typical of C code, and more appropriate to limited-memory environments (like arduino.)

A more general approach is to use regular expressions. A caveat is that it takes more program memory (to hold the regexp parser). The advantages are you can look for more general things, like a “sequence of digits optionally preceded by a minus sign”.

For your particular example:

#include <Regexp.h>

char str [] = "one|two|three|four";

// called for each match
void match_callback  (const char * match,          // matching string (not null-terminated)
                      const unsigned int length,   // length of matching string
                      const MatchState & ms)      // MatchState in use (to get captures)
{
  Serial.write ((byte *) match, length);
  Serial.println ();
}  // end of match_callback 

void setup ()
{
  Serial.begin (115200);
  MatchState ms (str);
  ms.GlobalMatch ("[^|]+", match_callback);
}  // end of setup  

void loop () {}

I should point out that strtok is destructive, the regular expression parser is not. By “destructive” I mean the original string is modified.

[quote author=Nick Gammon link=topic=62761.msg455333#msg455333 date=1306914375] A more general approach is to use regular expressions. A caveat is that it takes more program memory (to hold the regexp parser). The advantages are you can look for more general things, like a "sequence of digits optionally preceded by a minus sign". [/quote]

Thanks a lot guys!!! Im gonna try that tonite. :)

Hi Nick, your code works perfectly. Thank you.
However, my programming is pretty bad. How do you assign the result to a variable?

The result you have now is to print out as:
one
two
three
four

How do I get something like:
var1 = one;
var2 = two;
var3 = three… and so on?

I was trying to do:
var = Serial.write ((byte *) match, length);

For sure it won’t work but you get the idea what I am trying to do.
Thanks again~

Instead of:

Serial.write ((byte *) match, length);
Serial.println ();

You can copy the result to a buffer. I should warn you that the buffer needs to be large enough to hold the string, because the regular expression parser just works on your original string (to save memory). For example:

char buf [20];
ms.GetMatch (buf);  // copies the match into buf

If you want to hold them all at once, then you need to get into dynamic memory allocation (because you need a buffer for each one).

Here is one way, which uses the Standard Template Library:

// Regexp parser.
//  http://gammon.com.au/Arduino/Regexp.zip

#include <Regexp.h>

// STL includes
// For STL downloads, see: 
//   http://andybrown.me.uk/ws/2011/01/15/the-standard-template-library-stl-for-avr-with-c-streams/

#include <iterator>
#include <vector>
#include <string>
#include <new.cpp>

using namespace std;

// where to store the words we find
vector<string> words;

// test data
char str [] = "one|two|three|four";

// called for each match
void match_callback  (const char * match,          // matching string (not null-terminated)
                      const unsigned int length,   // length of matching string
                      const MatchState & ms)      // MatchState in use (to get captures)
{
  words.push_back (string (match, length));  // add string to vector
}  // end of match_callback 

void setup ()
{
  Serial.begin (115200);
  MatchState ms (str);
  
  // find how many matches
  int count = ms.MatchCount ("[^|]+");
  
  // reserve exact number of items for efficiency
  words.reserve (count);
  
  // debug: show how many
  Serial.print ("Match count = ");
  Serial.println (count);
  
  // pull the words out (the callback will put them in the vector)
  ms.GlobalMatch ("[^|]+", match_callback);

  // debug: show the words we found
  Serial.println ("Words found in words vector:");
  
  // iterate over the vector
  for (vector<string>::const_iterator it = words.begin (); it != words.end (); it++)
    Serial.println (it->c_str ());
    
}  // end of setup  

void loop () {}

Debugging output:

Match count = 4
Words found in words vector:
one
two
three
four

Using this technique you now have in the “words” vector all the words we found, which you can keep for later use.

You will probably get people telling you this is not the most memory-efficient way of doing it, and that is true. It depends how much free memory you have.

That sketch used:

Binary sketch size: 7410 bytes (of a 32256 byte maximum)

After running it (and adding code to find the amount of free memory) I got this:

Memory free = 1515

So out of 2048 bytes of RAM, 1515 bytes are still available. Not too bad. That may or may not be acceptable to you.

My position is that regular expressions, and the STL, are useful tools which make programming easier. If you can afford the program memory, and the RAM, that they use (and in this case I have quite a bit of both over) then they save time and effort. If not, you need to use more fiddly techniques.