I've written a simple program whereby input from the Serial monitor is printed back out again, via a function.
I've implemented this by passing a SafeStringReader object as an argument to another function (See code sample 1). Is that an 'okay' thing to do? I know it is for SafeString, wasn't sure about SafeStringReader. Or would it be better to leave SafeStringReader inside the function it is already in, and pass an extra argument to getSerialInput()? See code sample 2. My preference would be sample 1, because that consumes less memory I would think, only one large SafeString is in existence at any given time instead of two.
N.b. both sketches compile and run perfectly fine.
Code sample 1.
#include "SafeStringReader.h"
void setup() {
Serial.begin(9600);
SafeString::setOutput(Serial); // enable error messages and SafeString.debug() output to be sent to Serial
}
void loop() {
printAnySerialInput();
}
void printAnySerialInput(){
createSafeStringReader(sfReader, 322, "\n");
getSerialInput(sfReader);
Serial.print("input: "); Serial.println(sfReader);
}
void getSerialInput(SafeStringReader& sfReader){
sfReader.connect(Serial);
sfReader.echoOff();
while(1){
if (sfReader.read()) {
break;
}
}
}
Code sample 2.
#include "SafeStringReader.h"
void setup() {
Serial.begin(9600);
SafeString::setOutput(Serial); // enable error messages and SafeString.debug() output to be sent to Serial
}
void loop() {
printAnySerialInput();
}
void printAnySerialInput(){
createSafeString(tstStr, 255);
getSerialInput(tstStr);
Serial.print("input: "); Serial.println(tstStr);
}
void getSerialInput(SafeString& strOut){
createSafeStringReader(sfReader, 322, "\n");
sfReader.connect(Serial);
sfReader.echoOff();
while(1){
if (sfReader.read()) {
strOut = sfReader;
break;
}
}
}
I think that you will find very little support for their use because they are non standard and were implemented as a way of papering over the imperfections of using Strings in the Arduino environment. As such they are not well understood and not used by the majority of the Arduino using population and certainly not by many users of this forum
Why not use C style strings (ie zero terminated arrays of chars) instead ? They have been a feature of C almost since its inception and, as a result are well understood, have had all known bugs fixed and are used by serious Arduino programmers across the World. If you use them you will get solid, well informed help here but the majority of experienced members here will know little or nothing about SafeStrings
What problem are you trying to solve by using SafeStrings rather thab C style strings ?
I came across this webpage which recommends against using C-string methods (which I guess everyone does, sooner or later when they get started with C-string?)
Not any single particular problem. I have an application where I need to deal with quite a bit of strings/text, and I have been using Arduino Strings because that's the only thing I know. I ran into a problem which probably originates in my use of Arduino Strings. Then I came across the SafeString website which outlines the issues with both Arduino Strings and C-strings, and I thought: why not change things up a bit, if SafeString offers so many advantages?
Yeh I understand that is a barrier. How would you recommend to deal with the criticism outlined in the above website about C-strings?
The answer is that you need to program defensively which should be your objective anyway. You will be using standard C++ functionality to achieve that and should you have problems then a competent C++ programmer will be able to provide help and support. However, if you use an obscure and little used library such as SafeString you will struggle to get help
The SafeString library tries to solve 2 sets of problems. One is the bad reputation for fragmenting and wasting memory that Strings have when used in the limited memory of the average Arduino. The other is the misuse of arrays and of course it only addresses that for the case where an array is used to hold a string, not the general use of arrays, which I assume you use and are careful with
Why not ask the author of the library for his advice on your question ? He is a member here (@drmpf) but has not logged on for about a year, which I believe says a lot about how much the library is used
Summary : by all means use SafeStrings but don't expect too much help on their use here
I am well aware of the possible problems associated with the use of C style strings but I wondered whether @daanvV was trying to solve a particular problem, but he/she has not given a definitive answer
I see from a quick search that you have participated in many topics on the subject of SafeStrings to the point where you would seem to be an enthusiastic advocate of using them
Is that the case and do you use them as a matter of course instead of Strings or strings ?
Hi @daanvV ,
Feel free to contact me about SafeString either via a @drmpf here or via my website.
To answer your question, neither of those examples are desirable as they both create a SafeStringReader every loop.
The recommended approach is to create a global SafeStringReader and connect it in setup() to the Serial you want to read from.
See the examples included with the library.
Ignoring the SafeString aspect, Code sample 2 provides better encapsulation.
It lets you replace the getSerialInput implementation with some other code (reading from http / spi etc) without affecting the rest of the program.
Yes it is the case. Me personal I prefer SafeStrings over Strings and c-strings.
SafeStrings offer almost the same comfort as Strings.
Concenating the content of different variable-types is as easy as
Interesting, so why is that a problem? Does it require a lot of resources?
My gut instinct would be for making SafeStringReader local because that frees up memory when it's not used (when faced with a limited RAM MCU).
E.g. in the following scenario
// Setup etc. same as above sketch...
void loop() {
printAnySerialInput();
someOtherBigFunction();
somethingElseBigAndBulky();
}
void someOtherBigFunction(){
float big_array[1000];
// etc.
}
void somethingElseBigAndBulky(){
double another_big_array[1500];
}
// Other functions same as above sketch...
Sure but discarding the SafeStringReader also discards its internal state.
You are using
while(1)
to lock yourself in getSerialInput (and keep the reader's state) until it finds the next line, which makes the getSerialInput a blocking call.
That negates the non-blocking feature of SafeStringReader.
But if it makes sense to do that then not a problem.