There seems to be a lot of cases where newbies are still being warned about relying to much on Arduino String due to potential memory fragmentation.
Early on I also received the same warnings and I decided to do something about it re providing the convenience of String without the risks of memory fragmentation.
Therefore I humbly offer my CString class for newbies to use as they see fit.
Simply include the CString.h and CString.cpp in the same folder as your sketch (.ino file) and do #include "CString.h" in your .ino file.
You use my CString class as follows....
CBuff is just a wrapper class for a regular c style string 'char *str[100]'
Except that the CBuff constructor initialises the entire c style string with null terminators, similar to what the Arduino String class does.
And you can use CBuff objects in place of a regular c syle string if you wish - it has a few other convenient functios like 'empty()'
The idea behind this class was inspired by the PString library, the Arduino String class and the Microsoft Foundation Class CString class.
I have added a number of other convenient functions over the last couple of years.
// Delcare a c string buffer
CBuff<100> buff;
// Initialise a CString object with the buffer
CString str(buff)
It was necessary to set up the CString class in this way so that you can pass references to CString objects through functions freely.
If class CString itself was itself a template class then the above would not be possible.
The function names should be mostly self explanatory.
Please enjoy.
CString.cpp (28.3 KB)
CString.h (10.1 KB)
Could you post them in code tags please. I would like to see them but don't want to download the files.
arduino_new:
Could you post them in code tags please. I would like to see them but don't want to download the files.
No can do I am afraid.
The post exceeds the maximum allowed size.
You will have to download them.
Delta_G:
Can you give us some example code?
void CHTTPManager::updateEmailSettings(const char *strToEmail, const char *strMailServer, const char *strUsername, const char *strPassword, CString &strMsg)
{
CBuff<16> SmallBuff;
CString strFilename(SmallBuff);
if ((strlen(strToEmail) > 0) && (strlen(strMailServer) > 0) && (strlen(strUsername) > 0) && (strlen(strPassword) > 0))
{
strFilename = str_TXT_EMAIL;
if (SD.exists(strFilename))
{
CTextFile file;
if (file.open(strFilename, REWRITE))
{
file.writeLine(strToEmail);
file.writeLine(strMailServer);
file.writeLine(strUsername);
file.writeLine(strPassword);
file.close();
strMsg.empty();
}
else
{
strMsg = F("ERROR: Could not write to '");
strMsg += strFilename;
strMsg += F("'!");
}
}
else
{
strMsg = F("ERROR: Could find '");
strMsg += strFilename;
strMsg += F("'!");
}
}
arduino_new:
Okay, here goes:
- Your library generates a lot more executable code comparing to the standard String.
That is because it contains the combined function of Arduino String, MFC CString and a number of my own functions.
arduino_new:
2) What is the point of allowing to copy(); concat(); ... if your array cannot be resized?
You have to make sure that you allow a big enough buffer contain all the concatenated strings. The only way if you want to avoid the memory fragmentation due to dynamic memory allocation.
The various concatenate functions do generate a run time error in serial monitor if a call to them will result in buffer overrun.
arduino_new:
3) Your init() does a shallow copy of the pointer.
Not sure I understand what you mean by 'shallow'
boylesg:
Not sure I understand what you mean by 'shallow'
Google is inactive in your region?
If not, you could try to use it, "shallow copy c++" shows (me) 246000 hits.
Whandall:
Google is inactive in your region?
If not, you could try to use it, "shallow copy c++" shows (me) 246000 hits.
Oh I know what you mean. You mean I am copying the pointer value but not the contents of what it is pointing to.
But that is by design.
The init(...) is simply filling the CString object with an actual buffer with which to do all the later string manipulation.
I just put this code in the init(....) function so I did not have to repeat all the same code in each CString constructor.
boylesg:
Oh I know what you mean. You mean I am copying the pointer value but not the contents of what it is pointing to.
But that is by design.
That opens a whole bag of problems, like dangling pointers and maybe duplicate free() calls.
I would call that a bad design.
Whandall:
That opens a whole bag of problems, like dangling pointers and maybe duplicate free() calls.
I would call that a bad design.
The whole point of this class system is that it DOES NOT use dynamic memory allocation.
So there are NO issues with dangling pointers nor duplicate free() calls.
The char* buffers (CBuff) are created on the stack and are de-allocated when the function terminates.
Or at least the CBuff objects SHOULD be created on the stack and NOT through a call the new(..) or alloac(...).
One thing you can't do with my CString class, and that you can with the Arduino String class, is the following:
String str1("ABC"), str2;
str3 = str1 + "DEF";
The only way you can do same operation with my class is as follows:
CBuff<16> buff;
CString str(buff);
str = "ABC";
str += "DEF";
This is because it is really difficult to cater for all string sizes without using dynamic memory.
Either you only allow concatenation of really short strings in order conserve the amount of SRAM that must be taken up by temp buffers.
Or you allow for concatenation of large strings but the necessary temp buffers must be large and use up lot of SRAM.
In the end it was proved easier and more efficient to just do without the operator +(....) functions.