Go Down

Topic: split string by delimiters (Read 120500 times) previous topic - next topic

UKHeliBob

I am afraid that however you refer to them, Strings, String objects, strings, C style strings or whatever there is always going to be confusion because they use the same word. 

Good luck with your campaign to educate people to use the right terms to refer to the right type of Strings but you are not going to get very far I think because by the time that people ask questions they have usually used String objects which are frowned upon here for a variety of reasons including bugs in previous versions of the Arduino IDE/compiler/preprocessor (I know not which)

Personally I still think that using string and String to refer to the two different methods of doing things is still valid in this forum but it does deserve an explanation of the difference when the terms are introduced.  I would suggest a sticky or a "Useful thread" explaining the difference but as many people don't appear to read any of the stickies and persist in posting code snippets not in code tags I don't think that will work.

I suspect that we will have to agree to differ on this.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

BigBobby

Good luck with your campaign to educate people to use the right terms to refer to the right type of Strings
You must be kidding.  I was done with the thread in the minutes it took to satisfy the OP.  You and your pal are the ones that have spent days chastising me for my capitalization.

And pretty much anyone with a good understanding of C/C++ is not going to assume that the Arduino has this convention for its String class.  Now that I'm aware of the convention, I agreed to use it (several posts ago).

If nothing else, hopefully this waste of bandwidth taught your pal something about C++.  Hopefully it also taught him to not be arrogant when "correcting" people.  When you do that and you're right, you look like a jerk.  When you do that and you're wrong, you look ridiculous.

christop

Code: [Select]

boolean LED_Read(void) {
  return ~true;
}

I just wanted to point out that ~true is the same as true (though it doesn't really make sense to bitwise complement a boolean value). If you want a false value, say "!true" or simply "false".

EasyGoing1

It's too bad Arduino doesn't use Java. The solution to this problem, for example, if your delimiter were a semi-colon would be this simple:

Code: [Select]

String[] items = serialString.split(";");


and WALLA! Instant array populated with each piece of the string between delimiters.
Mike Sims

Robin2

It's too bad Arduino doesn't use Java.
Heaven protect us.

It's bad enough that it uses C/C++

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

UKHeliBob

#35
Jul 10, 2017, 11:24 am Last Edit: Jul 10, 2017, 11:25 am by UKHeliBob
Heaven protect us.

It's bad enough that it uses C/C++

...R
I agree.  It would be so much better if it were programmed in MUMPS (Yes,  it is a real programming language)  :)
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Robin2

I remember hearing of MUMPS but I can't remember anything else about it. I am inclined to associate it with COBOL for some reason.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

UKHeliBob

As you might have gathered I wasn't entirely serious about programming an Arduino in MUMPS.  It has none of the nonsense of needing to declare variables before using them, all variables are globals, there are no data types and the program and database it uses are one and the same thing.  It does, however, have an excellent method for splitting delimited data !
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Robin2

As you might have gathered I wasn't entirely serious about programming an Arduino in MUMPS.  It has none of the nonsense of needing to declare variables before using them, all variables are globals, there are no data types
Ah ... someone, back in the day, who could not spell BASIC then  :)

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

jandresmartinez

Another way

Code: [Select]
void setup() {
    Serial.begin(9600);
}

void loop() {
    String data="$GPGGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh";
    int maxIndex = data.length() - 1;
    int index=0;
    int next_index;
    String data_word;
    do{
        next_index=data.indexOf(',',index);
        data_word=data.substring(index, next_index);
        Serial.print("Output line: ");
        Serial.println(data_word);
        index=next_index+1;
     }while((next_index!=-1)&&(next_index<maxIndex));

}


Outputs:
Code: [Select]
Output line: $GPGGA
Output line: hhmmss.ss
Output line: llll.ll
Output line: a
Output line: yyyyy.yy
Output line: a
Output line: x
Output line: xx
Output line: x.x
Output line: x.x
Output line: M
Output line: x.x
Output line: M
Output line: x.x
Output line: xxxx*hh

Shrimant_Patel

Finally I have a decent and simple String splitter , which splits a string by a given delimiter:

Thanks to "Peter Polidoro" for the idea of vector on Arduino and providing the header files:

Download the header files for vector from the link below and include it in your project, then follow my sample code below:

http://dl.platformio.org/libraries/archives/58/16806.tar.gz?filename=Vector_1.1.2_5825




Code: [Select]

#include <Vector>

//Splitter Method
void split(Vector<String> &MsgAry, String MsgStr, String delim) {
String Token;
while (Token != MsgStr) {
Token = MsgStr.substring.Substr(0, MsgStr.indexOf(delim));
MsgStr = MsgStr.substring(MsgStr.indexOf(delim) + 1);
MsgAry.push_back(Token);
}
}
//USAGE

void loop(){
         String Strtosplit = "Abc;CDE;EFG;DER;BABA;SHIVA" ; //Sample delimited string.
         
         Vector<String> VectStrAry; //Create a Vector

          // Pass the Vector, String to be splitted and the delimetter character to the splitter method
         split(VectStrAry, Strtosplit , ";");
         

         //Parse through the Vector elements as you do with an Array
for (int i = 0; i < MsgAry.size(); i++) {
Serial.println = Serial.println(String(MsgAry[i]));
}

        VectStrAry.empty; //Safety step to manually de-allocate the vector
}

//SERIAL OUTPUT
Abc
CDE
EFG
DER
BABA
SHIVA

christop

Code: [Select]

#include <Vector>

//Splitter Method
void split(Vector<String> &MsgAry, String MsgStr, String delim) {
 String Token;
 while (Token != MsgStr) {
 Token = MsgStr.substring.Substr(0, MsgStr.indexOf(delim));
 MsgStr = MsgStr.substring(MsgStr.indexOf(delim) + 1);
 MsgAry.push_back(Token);
 }
}


Unfortunately, that code has a few shortcomings:

  • The caller must make a copy of both MsgStr and delim when calling this function. This means more memory is required.
  • The function is finding the index of the delimiter in MsgStr twice. Once should be enough.
  • The function modifies MsgStr unnecessarily. It should search for the delimiter without taking a substring of the MsgString each time (indexOf can take a second argument, the index to start searching from).
Try to re-implement the function with this declaration:

Code: [Select]

void split(Vector<String> &MsgAry, const String &MsgStr, const String &delim);

Shrimant_Patel

@Christop thank you so much for bringing up the shortcomings , I appreciate it and I am going to implement it in my usage for sure:

Below is a much better implementation which I just tested on VC++ , I hope there are not too much nags when it runs on Arduino. It uses the <ssstream> header too. Any comments on the below improvements?

Code: [Select]

#include <iostream>
#include <sstream>
#include <vector>

using namespace std;
void split(vector<string> &MsgAry, const string &MsgString, char delim) {
stringstream ss(MsgString);
string item;
while (getline(ss, item, delim)) {
MsgAry.push_back(item);
}
}


Robin2

@Shrimant_Patel, the example in Reply #40 uses the String class. I suspect (but I'm not sure) that the example in Reply #42 also uses it.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

When using cstrings you use the strtok() function to split then.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

lastchancename

...and to summarise.
With frequent character array ('string'j manipulation, it is preferable to use c-strings rather than String class objects.  Reasons above and elsewhere.

For the OP, you can then use strtok() and other c-string functions to process and manipulate your c-string arrays without the overhead and potential for calamity which is incurred by Strings on a small memory processor.
Experienced responders have a nose for laziness, (they were beginners once)... Sure, there are trolls, chest-beaters, and pretenders - but the help you'll get here is about as good as it gets - if you try to help youself!.

Go Up