Hello,
i have obviously easy to solve problem but cant find out the solution. My sketch looks like this:
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?
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).
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:
#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:
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.
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
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 :)
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
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.
//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
}
}
}
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.
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.
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
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)
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:
#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?"
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.
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!
and another way
/*
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 */
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
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.
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.
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
There are 37.5 angels on the head of my pin.
Are they actually on the pin or are they floating ?
Are they actually on the pin or are they floating ?
Maybe I need PULLUPs ? (or PULLDOWNs ?)
...R
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...
<...>
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
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.
<...>
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.)
// 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
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
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.
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
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.
my first post is quite easily the most helpful thing for the OP in this thread.
In your first post you said
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)
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.
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.
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.
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".
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:
String[] items = serialString.split(";");
and WALLA! Instant array populated with each piece of the string between delimiters.
It's too bad Arduino doesn't use Java.
Heaven protect us.
It's bad enough that it uses C/C++
...R
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) :)
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
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 !
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
Another way
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:
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
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)
#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
#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:
void split(Vector<String> &MsgAry, const String &MsgStr, const String &delim);
@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?
#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);
}
}
@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
...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.
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.
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);
}
}
}
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