Arduino Forum

Using Arduino => Programming Questions => Topic started by: kalreg on Mar 17, 2016, 04:42 pm

Title: split string by delimiters
Post by: kalreg on Mar 17, 2016, 04:42 pm
Hello,

i have obviously easy to solve problem but cant find out the solution. My sketch looks like this:


Code: [Select]
String serialResponse = "";
char sz[] = "Here; is some; sample;100;data;1.414;1020";

void setup()
{
 Serial.begin(9600);
 Serial.setTimeout(5);
 delay(5000);
 char *p = sz;
 char *str;
 while ((str = strtok_r(p, ";", &p)) != NULL) // delimiter is the semicolon
   Serial.println(str);

}

void loop()
{
if ( Serial.available()) {
 serialResponse = Serial.readStringUntil('\r\n');
 Serial.println(serialResponse);
}
}


I simplified a sketch so you can focus on my problem. As you can see in setup function i cut sz[] to pieces after each semicolon which is declared as delimiter.
I also listen to Serial port and if I have any incoming data I want to send it back as a confirmation.
the question is - how to mix both of those functions? I want to send via serial data, read it with readStringUntil, cut it by delimiter and send parts back to serial. In other words i want to put string from serialResponse use it as if it is sz[].
The problem i've reached while trying to do it by myself is that readStringUntil returns string, but strtok need chars and i have no idea how to mix it. Can you help me please?
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 17, 2016, 04:49 pm
Quote
readStringUntil returns string
Does it return a String or a string ?  It looks like the former.

Have a look at Serial input basics (http://forum.arduino.cc/index.php?topic=288234.0) to see how to read the serial input into a string (array of chars).
Title: Re: split string by delimiters
Post by: BigBobby on Mar 17, 2016, 05:01 pm
You're mixing up "Strings" (https://www.arduino.cc/en/Reference/String) with "String Objects" (https://www.arduino.cc/en/Reference/StringObject) (and you aren't the first person).  These links should clear it up.

The String Object has a method to return a String, upon which your code can operate:
Code: [Select]

#include "Arduino.h"

String serialResponse = "";
char sz[] = "Here; is some; sample;100;data;1.414;1020";

void setup()
{
 Serial.begin(9600);
 Serial.setTimeout(5);
}

void loop()
{
  if ( Serial.available()) {
    serialResponse = Serial.readStringUntil('\r\n');

    // Convert from String Object to String.
    char buf[sizeof(sz)];
    serialResponse.toCharArray(buf, sizeof(buf));
    char *p = buf;
    char *str;
    while ((str = strtok_r(p, ";", &p)) != NULL) // delimiter is the semicolon
      Serial.println(str);
  }
}


If you type "Here; is some; sample;100;data;1.414;1020" into the serial monitor, the results will be:

Quote
Here
 is some
 sample
100
data
1.414
1020
Note that this is pretty inefficient, however.  You'd be better off making a function doesn't use a String Object, but just parses the serial input and builds a String directly.  At that point, you might as well parse the fields as you receive them and then operate upon them once the "\r\n" is received.
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 17, 2016, 05:09 pm
Quote
You'd be better off making a function doesn't use a String Object, but just parses the serial input and builds a String directly
You'd be better off making a function doesn't use a String Object, but just parses the serial input and builds a string directly
Title: Re: split string by delimiters
Post by: kalreg on Mar 17, 2016, 06:38 pm
Thank you for your answer. I'll try it in a moment.
You suggest to operate on individual chars coming from Serial until delimiter is reached if I understand correctly. Maybe I will however i guess code should be more complicated and I am not sure if efficiency of your code isnt enough for me. Anyways thank you for help... i have to become more familiar with all those strings, chars and so on.. that kind of knowledge is no necessery with php or javascript :)
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 17, 2016, 07:48 pm
Quote
I am not sure if efficiency of your code isnt enough for me.
Each character, and hence the whole string/String, will take just as long to arrive however it is dealt with.  In terms of the Arduino the characters arrive quite slowly which leaves plenty of time to process them. 

9600 baud is very slow
Title: Re: split string by delimiters
Post by: zoomkat on Mar 18, 2016, 12:30 am
Lots of ways to parse a captured character strings. The below uses the String functions. In this example the data string uses a comma "," to separate the data parts and a "*" to mark the end of the total data packet. 

Code: [Select]

//zoomkat 11-12-13 String capture and parsing 
//from serial port input (via serial monitor)
//and print result out serial port
//copy test strings and use ctrl/v to paste in
//serial monitor if desired
// * is used as the data string delimiter
// , is used to delimit individual data

String readString; //main captured String
String angle; //data String
String fuel;
String speed1;
String altidude;

int ind1; // , locations
int ind2;
int ind3;
int ind4;
 
void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 11-12-13"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 90,low,15.6,125*
  //or 130,hi,7.2,389*

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '*') {
      //do stuff
     
      Serial.println();
      Serial.print("captured String is : ");
      Serial.println(readString); //prints string to serial port out
     
      ind1 = readString.indexOf(',');  //finds location of first ,
      angle = readString.substring(0, ind1);   //captures first data String
      ind2 = readString.indexOf(',', ind1+1 );   //finds location of second ,
      fuel = readString.substring(ind1+1, ind2+1);   //captures second data String
      ind3 = readString.indexOf(',', ind2+1 );
      speed1 = readString.substring(ind2+1, ind3+1);
      ind4 = readString.indexOf(',', ind3+1 );
      altidude = readString.substring(ind3+1); //captures remain part of data after last ,

      Serial.print("angle = ");
      Serial.println(angle);
      Serial.print("fuel = ");
      Serial.println(fuel);
      Serial.print("speed = ");
      Serial.println(speed1);
      Serial.print("altidude = ");
      Serial.println(altidude);
      Serial.println();
      Serial.println();
     
      readString=""; //clears variable for new input
      angle="";
      fuel="";
      speed1="";
      altidude="";
    } 
    else {     
      readString += c; //makes the string readString
    }
  }
}

Title: Re: split string by delimiters
Post by: aarg on Mar 18, 2016, 12:37 am
Does it return a String or a string ?  It looks like the former.

Have a look at Serial input basics (http://forum.arduino.cc/index.php?topic=288234.0) to see how to read the serial input into a string (array of chars).
+1
That will allow you to use strtok(). The String class is not a good idea on the Arduino, due to a significant risk of heap fragmentation as memory usage increases beyond the size of a trivial sketch, which will cause random crashes and freezing.
Title: Re: split string by delimiters
Post by: BigBobby on Mar 18, 2016, 03:44 pm
You'd be better off making a function doesn't use a String Object, but just parses the serial input and builds a string directly
Heh...fine..."string" instead of "String."

If I saw someone write code where variable and Variable were different things though, I'd slap them.

But here Arduino is expecting string and String to be super clear to all of the people getting confused.
Title: Re: split string by delimiters
Post by: Robin2 on Mar 19, 2016, 10:41 am
But here Arduino is expecting string and String to be super clear to all of the people getting confused.
It's not the fault of the Arduino folks. It is a C/C++ thing.

...R
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 19, 2016, 01:36 pm
Quote
But here Arduino is expecting string and String to be super clear to all of the people getting confused.
Avoid any confusion by always using strings (lowercase s)
Title: Re: split string by delimiters
Post by: BigBobby on Mar 19, 2016, 05:13 pm
By which standard?  The class was "std::string" in the 1998 standard upon which avr-gcc is based (https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Standards.html#Standards).  Even as of the 2014 standard they make no mention of string vs String -> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)

Although I rarely use C++ in embedded programming, I have several other compilers that support it.  Here's code for IAR Workbench for ARM set to Strict:
Code: [Select]

#include <iostream>
using namespace std;

int main()
{
    string test;
    String test2;

    return 0;
}


The only error I get is "Error[Pe020]: identifier "String" is undefined".

The first place I've ever seen the convention of "string" vs "String" is the Arduino documentation, and frankly it's stupid.  I've only been on these forums a few months and already seen many cases where people were confused.  I can't blame them for not picking up on a capitalization convention.  I mean really...with that convention, how am I supposed to write a title or start a sentence about "strings?"
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 19, 2016, 05:32 pm
Quote
with that convention, how am I supposed to write a title or start a sentence about "strings?"
Example :
strings make better use of memory than Strings in the limited memory environment of most Arduinos.
Title: Re: split string by delimiters
Post by: BigBobby on Mar 19, 2016, 05:59 pm
Example :
strings make better use of memory than Strings in the limited memory environment of most Arduinos.
Ok, and we both agree that a convention that can't be discussed without breaking grammar rules is stupid?

Bah...I've sat on standards committees before...if you suggested a convention like this professionally you'd be laughed out of the room for good reason.  This forum itself contains many examples as to why!
Title: Re: split string by delimiters
Post by: mrburnette on Mar 19, 2016, 06:04 pm
and another way

Code: [Select]
/*
  GPS serial read and sentence detection
  Derrived from work by M. Ray Burnette on the PSoC code published on Hackster.io/RayBurne
  Compiler board: Nano
  Arduino 1.7.3 & 1..7.8 // 6/09/2015 & 1/17/2016
    Sketch uses 504 bytes (1%) of program storage space. Maximum is 30,720 bytes.
    Global variables use 16 bytes (0%) of dynamic memory, leaving 2,032 bytes for local variables. Maximum is 2,048 bytes
*/

#include <stdlib.h> // for function atoi()

// Global variables
uint8_t hour, minute, seconds;          //, year, month, day;
uint8_t day, month, year;

char    buffer[9];
char    nmea[120];

// double  atof(const char *str);       // elimited Limor's float implementation

boolean DayLightSavings;                // Pin 3.4
uint8_t GMToffset = 4;
uint8_t Flag = 1;
uint32_t  c = '\0';
int8_t  k   = 0 ;

boolean DSTime_Read(void) {
  return true;
}

void GLCD_WRITE( char *x ) {
}

void glcd_write(void) {
}

void glcd_clear(void) {
}

void glcd_tiny_draw_string(int x, int y, char* c) {
}

char UART_UartGetChar() {
  char i = '\0';
  return i;
}

void LED_Write( boolean PinState) {
}

boolean LED_Read(void) {
  return ~true;
}

void setup(void)
{
    DayLightSavings = DSTime_Read();        // Pin# Normally true (HIGH)

    if(! DayLightSavings) GMToffset += 1;
}

void loop(void)
    {
        if (Flag == 1)
        {
            GLCD_WRITE("Waiting on GPS") ;
            // Flag = 0;
       
        c = UART_UartGetChar();     // Get received character or null
        if (c) 
        {
            if(c == '$')            // $ start of NMEA sentences
            {
                for(k=0; k<5; k++)  // need 5 characters for sentence type
                {
                    LED_Write( ~LED_Read() );   // flicker LED for activity
                    do {
                        c = UART_UartGetChar();
                    }
                    while (! (c));
                    nmea[k] = c;    // G + P + R + M + C
                    // sprintf(buffer + k, "%c", c) ;  // only for debug
                }

                LED_Write( LOW );                   // LED off
                if (strstr(nmea, "GPRMC"))
                {
                    do {
                        do {
                            c = UART_UartGetChar();
                            LED_Write( ~LED_Read() ); // flicker LED
                        } while (!(c));
                        nmea[k] = c;
                        ++k;
                    } while ( !( c == '*' ) && k < 120) ;   // marker
                    LED_Write( LOW );                       // LED off
                    // Inspiration: Limor Fried's Arduino GPS lib
                    char *p = nmea;
                    p = strchr(p, ',') + 1;   // position after 1st comma
                    // float    timef  = atof(p);
                    // uint32_t  time  = timef;
                    uint32_t  time  = atoi(p);
                              hour  = time / 10000;
                            minute  = (time % 10000) / 100;
                           seconds  = (time % 100);
                    // output to GLCD
                    sprintf(buffer, "              %s","");  // clearbuffer
                   
                    // this corrects time to the West but not the date!!!
                    if( hour > GMToffset) {
                        hour = hour - GMToffset;
                    } else {
                        hour = (hour + 24) - GMToffset; }

                    // correct midnight to follow standard format
                    if (hour == 24) hour = 0;

                    if (hour < 10) {
                        if (DayLightSavings) {
                            sprintf(buffer, "EDT:  %d", hour);
                        } else {
                            sprintf(buffer, "EST:  %d", hour);
                        }
                    } else {
                        if (DayLightSavings) {
                            sprintf(buffer, "EDT: %d%d", hour);
                        } else {                       
                        sprintf(buffer, "EST: %d%d", hour); }
                    }
                    if (minute < 10) {
                        sprintf(buffer + 7, ":0%d", minute);
                    } else {
                        sprintf(buffer + 7, ":%d%d", minute); }
                    if (seconds < 10) {
                        sprintf(buffer + 10,":0%d%s", seconds);
                    } else {
                        sprintf(buffer + 10, ":%d%d%s", seconds); }
                    sprintf(buffer + 13, "%s", "\0");
                    if(Flag == 1)
                    {
                        Flag = 0;
                        glcd_clear() ;
                        delay(250) ;
                    }
                    // OUTPUT the TIME on GLCD
                    glcd_tiny_draw_string(0, 4, buffer);
                    glcd_write() ;
                    // Parse to integer date field
                    p = strchr(p, ',') +1;  // A/V?
                    p = strchr(p, ',') +1;  // lat
                    p = strchr(p, ',') +1;  // N/S?
                    p = strchr(p, ',') +1;  // lon
                    p = strchr(p, ',') +1;  // E/W?
                    p = strchr(p, ',') +1;  // speed
                    p = strchr(p, ',') +1;  // angle
                    p = strchr(p, ',') +1;  // move pass for date DDMMYY
                    // nmea date field looks like: 090914 (European)
                    uint32_t fulldate = atoi(p);
                    day     = (fulldate / 10000);
                    month   = (fulldate % 10000) / 100;
                    year    = (fulldate % 100);
                    sprintf(buffer, "              %s","");  // clearbuffer
                    if (day < 10) {
                        sprintf(buffer, "0%d", day);
                    } else {
                        sprintf(buffer, "%d%d", day); }
                    if (month < 10) {
                        sprintf(buffer + 2,"-0%d", month);
                    } else {
                        sprintf(buffer + 2,"-%d%d", month); }
                    sprintf(buffer + 5, "-20%d%d%s", year);
                    sprintf(buffer + 10,"%s",'\0');
                    // OUTPUT the DATE on GLCD
                    glcd_tiny_draw_string(0, 2, buffer);
                    glcd_write() ;
                }   // if (strstr(nmea, "GPRMC"))
            }       // if(c == '$')
        }           // if(c)
      }             // flag
    }               // loop()


/* [] END OF FILE */
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 19, 2016, 06:10 pm
Quote
Ok, and we both agree that a convention that can't be discussed without breaking grammar rules is stupid?
If you insist on not breaking grammar rules

Using strings makes better use of memory than Strings in the limited memory environment of most Arduinos.


How about a discussion about an iPhone ?

iPhones are far too expensive
Title: Re: split string by delimiters
Post by: zoomkat on Mar 19, 2016, 06:21 pm
Quote
I mean really...with that convention, how am I supposed to write a title or start a sentence about "strings?"
Kind of like blind men describing an elephant. In this programming environment, a "string" usually refers to an ordered set of bytes, "c-strrings" refers to a method of placing the bytes in a memory location with a null byte appended to the byte string to delimit that byte string in that memory location. A "String" refers to a method of storing byte strings in memory locations using a dynamic indexing system for those strings. Note that some of the info put out by some is more opinion than technical fact, or depends on specific conditions to validate that opinion.
Title: Re: split string by delimiters
Post by: BigBobby on Mar 19, 2016, 06:40 pm
If you insist on not breaking grammar rules

Using strings makes better use of memory than Strings in the limited memory environment of most Arduinos.


How about a discussion about an iPhone ?

iPhones are far too expensive
iPhone is a proper noun.  Proper nouns are normally capitalized all of the time, but Apple is just cool like that.  I imagine the grammar rule would be "use whatever case was used by the person who created the name," but that wasn't a grammar rule I had to worry about when I was in school.

A string is a noun resulting from a naming convention.  It would normally follow all of the rules applicable to the capitalization of nouns.

I don't see why we can't just talk about strings like they do in the C++ spec.  It's worked for decades.  Sure, sometimes people would confuse "strings" with "string objects," but with a sentence or two it'd be cleared up.

Now in this forum, we have threads where people confuse "strings" with "string objects," and people act like saying "string" and "String" back to them is supposed to clear things up.  I don't know who decided to try this experiment, but it didn't work.
Title: Re: split string by delimiters
Post by: Robin2 on Mar 19, 2016, 08:00 pm
Now in this forum, we have threads where people confuse "strings" with "string objects," and people act like saying "string" and "String" back to them is supposed to clear things up.  I don't know who decided to try this experiment, but it didn't work.
There are 37.5 angels on the head of my pin.

...R
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 19, 2016, 08:07 pm
Quote
There are 37.5 angels on the head of my pin.
Are they actually on the pin or are they floating ?
Title: Re: split string by delimiters
Post by: Robin2 on Mar 20, 2016, 09:42 am
Are they actually on the pin or are they floating ?
Maybe I need PULLUPs ? (or PULLDOWNs ?)

...R
Title: Re: split string by delimiters
Post by: BigBobby on Mar 21, 2016, 06:12 pm
Heh...I hope I came across as half-serious in this thread.  I'll call them "string" and "String" if that's how things are in Arduinoland...

I sort of had this Arduino stuff thrust upon me, however.  Usually when I switch to a new embedded system I just have to read a micro datasheet and a compiler manual.

With Arduino you have this whole layer on top of that...
Title: Re: split string by delimiters
Post by: mrburnette on Mar 21, 2016, 09:11 pm
<...>
With Arduino you have this whole layer on top of that...
Yes.  The noise responses are just routine forum static.

Arduino is IMO a two-layer extra: the Arduino "language" abstractions and the hardware abstractions known as the "core".  Even early 8-bit AVR arduinos were somewhat different; for example one hardware serial device in Uno to three in the Mega2560, etc.  Also, some uC boards such as the Leonardo were native USB and capable of multiple USB profiles.

The above hardware variances simply mandate that you have a small collection of board/uC printouts to be able to mentally contemplate the resource.
(https://camo.githubusercontent.com/8c6286b38b37ec592982e020b8aa6bd86f968981/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f752f35303236313733312f57696b69253230576f726b2f4475652d70696e6f75745f74696e7947325f302e322e706e67)

Unlike soft microcontrollers such as the Cypress PSoC line which has extensive internal switched fabric mapped by VHDL, the Arduino pinout and circuit layout are rather limited in flexibility.

But, the core concept can lead to many development boards that are somewhat restricted in tools to have a second life un Arduino land: example STM32F103 which was used in the Maple series and now a very complete $4 arduino: http://www.stm32duino.com


Ray
Title: Re: split string by delimiters
Post by: BigBobby on Mar 21, 2016, 10:34 pm
Arduino is IMO a two-layer extra: the Arduino "language" abstractions and the hardware abstractions known as the "core".
Hmm...interesting point about the two layers.

I have yet to use any Arduinos other than the Uno, where the hardware abstractions have been a bit of an annoyance (I was so thrilled the first time I tried to use an I/O, and discovered that the proper way to do it was to use special names that the Arduino had assigned as opposed to what's in the datasheet).  In order to make the same code work on different Arduinos, however, that is what they needed to do.
Title: Re: split string by delimiters
Post by: mrburnette on Mar 22, 2016, 01:02 am
<...>
In order to make the same code work on different Arduinos, however, that is what they needed to do.

In the beginning, I agree.  I think now, the focus is to use the same IDE because Arduino IDE use is widespread; even if the Arduino "core" forces inefficiencies; that is, the IDE and wide selection of libraries often outweigh performance.  If you doubt this, just take a look at any Adafruit library and note the numerous #ifdef statements sprinkled throughout thecode in order to support various manufacturer's hardware (models.)

Code: [Select]
// https://github.com/somhi/ESP_SSD1306
#ifdef __AVR__
 #include <avr/pgmspace.h>
#elif defined ESP8266    //Added for compatibility with ESP8266 BOARD
#else
 #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#endif


Other libraries are for more complex.

Ray
Title: Re: split string by delimiters
Post by: -dev on Mar 22, 2016, 01:54 am
Quote from: BigBobby
the hardware abstractions have been a bit of an annoyance
If you're into Object-Oriented solutions, you should check out Cosa (https://github.com/mikaelpatel/Cosa).  It has the best HW abstraction I've ever seen.  If you think C++/OO cannot be efficient, you'll be very surprised, especially if you look at the generated assembly.  It's much faster than any "native" Arduino core libs.  Cosa's SPI and UART performance is unbeaten, I believe.  Zippy, yet very readable.

Cosa is really an alternative "framework" or "core".  Many boards and devices have been integrated by the author, so they are very consistent in style, unlike the hodge-podge you get with Arduino libraries from different authors (with different skill levels, I might add).  Be sure to see the Doxygen-generated online docs here (https://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/index.html).

Cosa apps can still be built with the Arduino IDE by selecting a different "Board" (e.g. Cosa UNO instead of Arduino UNO).  It also offers a slick makefile system, leaving the IDE waaay behind.

Cheers,
/dev
Title: Re: split string by delimiters
Post by: Robin2 on Mar 22, 2016, 10:43 am
I'll call them "string" and "String" if that's how things are in Arduinoland...

....SNIP....

With Arduino you have this whole layer on top of that...
The confusing usage of String and string that you are complaining about is NOT an Arduino issue - it is a C/C++ issue.

Quote
Heh...I hope I came across as half-serious in this thread.
You may be serious but I can't see how your interventions have been any assistance to the OP.

...R
Title: Re: split string by delimiters
Post by: BigBobby on Mar 22, 2016, 12:08 pm
The confusing usage of String and string that you are complaining about is NOT an Arduino issue - it is a C/C++ issue.
You may be serious but I can't see how your interventions have been any assistance to the OP.

...R
Haha...I guess this is the forum static that was mentioned before?

Not only isn't it a C/C++ issue, but I provided a link to the standard to prove it.  Did you not read it, or did you not understand it?  If it's the latter, I can explain it to you but how the hell can you have 24,515 posts and not know this stuff?

And my first post is quite easily the most helpful thing for the OP in this thread.

Seriously...read a book.  This isn't the first time I've seen you blathering on about something where you had no idea what you were talking about.
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 22, 2016, 02:46 pm
Quote
my first post is quite easily the most helpful thing for the OP in this thread.
In your first post you said
Quote
You're mixing up "Strings" with "String Objects"
I find it somewhat amusing that the link you provided to explain Strings (uppercase) leads to a page headed strings (lowercase)
Title: Re: split string by delimiters
Post by: BigBobby on Mar 22, 2016, 03:15 pm
In your first post you saidI find it somewhat amusing that the link you provided to explain Strings (uppercase) leads to a page headed strings (lowercase)
Ffs...when I added the links the full URL was cumbersome as the displayed text so I snipped it to the last word.  Go type "Arduino string" into google.  The first link you get is "https://www.arduino.cc/en/Reference/String" and the second you get is "https://www.arduino.cc/en/Reference/StringObject."  The OP left here happy with my answer and a general awareness that String objects are inefficient.

And double ffs...you must realize that the Arduino has a respect problem in real engineering environments.  While there are some people on these forums that seem to know what they're doing, your persistance with the trivial "string" vs "String" thing (and being unaware it isn't a C++ thing) contributes to that lack of respect.
Title: Re: split string by delimiters
Post by: UKHeliBob on Mar 22, 2016, 03:59 pm
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.
Title: Re: split string by delimiters
Post by: BigBobby on Mar 22, 2016, 04:25 pm
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.
Title: Re: split string by delimiters
Post by: christop on Mar 22, 2016, 04:56 pm
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".
Title: Re: split string by delimiters
Post by: EasyGoing1 on Jul 10, 2017, 12:59 am
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.
Title: Re: split string by delimiters
Post by: Robin2 on Jul 10, 2017, 10:32 am
It's too bad Arduino doesn't use Java.
Heaven protect us.

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

...R
Title: Re: split string by delimiters
Post by: UKHeliBob on Jul 10, 2017, 11:24 am
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)  :)
Title: Re: split string by delimiters
Post by: Robin2 on Jul 10, 2017, 01:06 pm
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
Title: Re: split string by delimiters
Post by: UKHeliBob on Jul 10, 2017, 01:43 pm
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 !
Title: Re: split string by delimiters
Post by: Robin2 on Jul 10, 2017, 02:37 pm
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
Title: Re: split string by delimiters
Post by: jandresmartinez on Jul 04, 2018, 01:56 am
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
Title: Re: split string by delimiters
Post by: Shrimant_Patel on May 21, 2019, 10:29 pm
Finally I have a decent and simple String splitter , which splits a string by a given delimiter:

Thanks to "Peter Polidoro (https://platformio.org/lib/show/5825/Vector)" 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 (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
Title: Re: split string by delimiters
Post by: christop on May 21, 2019, 11:03 pm
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:

Try to re-implement the function with this declaration:

Code: [Select]

void split(Vector<String> &MsgAry, const String &MsgStr, const String &delim);
Title: Re: split string by delimiters
Post by: Shrimant_Patel on May 22, 2019, 01:06 am
@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);
}
}

Title: Re: split string by delimiters
Post by: Robin2 on May 22, 2019, 08:59 am
@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 (http://www.cplusplus.com/reference/cstring/) - char arrays terminated with '\0' (NULL).

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

...R
Title: Re: split string by delimiters
Post by: lastchancename on May 22, 2019, 12:14 pm
...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.
Title: Re: split string by delimiters
Post by: drmpf on Jun 16, 2020, 05:34 am
There is now a SafeString library available from the Arduino Library manager which includes a number of tokenizer methods and a simple effective example of parsing user input for keywords without blocking the rest of the sketch  from running

SafeStrings do not cause heap fragementation and never cause the sketch to reboot and have detail debugging available.


Code: [Select]
void loop() {
  input.read(Serial)
  // read from Serial, returns true if at least one character was added to SafeString input

  if (input.nextToken(token, delimiters)) { // process at most one token per loop does not return tokens longer than input.capacity()

    if (token == startCmdStr) {
      running = true;  Serial.print(F("start at ")); Serial.println(loopCounter);

    } else if (token == stopCmdStr) {
      running = false; Serial.print(F("stop at ")); Serial.println(loopCounter);

    } else if (token == resetCmdStr) {
      loopCounter = 0; Serial.print(F("reset Counter:")); Serial.println(loopCounter);

    }// else  // not a valid cmd ignore
  }

  // rest of code here is executed while the user typing in commands
  if (running) {
    loopCounter++;
    if ((loopCounter % 100000) == 0) {
      Serial.print(F("Counter:")); Serial.println(loopCounter);
    }
  }
}
Title: Re: split string by delimiters
Post by: EasyGoing1 on Jun 19, 2020, 04:30 pm
As you might have gathered I wasn't entirely serious about programming an Arduino in MUMPS.
I learned a language called FROG ... way back in high school ... I think DOS was on version 2 or 3 back then ... 1986-ish