I am using an Arduino Function that returns a String object.
I need to send that string to another function, which accepts a char Array.
I tried simply sending the String object, in the hope that some implicit conversion will happen,
but none did..
So I wrote this small helper function:
char* ConvertStringToCharArray(String S)
{
int ArrayLength =S.length()+1; //The +1 is for the 0x00h Terminator
char CharArray[ArrayLength];
S.toCharArray(CharArray,ArrayLength);
return(CharArray);
}
It works, but I wonder...
is this really needed?
No shorter way already exists for such a basic thing, rather than writing this myself?
CharArray goes out of scope as soon as you leave the function. So the returned pointer will point to somewhere in memory where the data was in the past.
The rest of your code might use that memory and corrupt the original data.
I am using an Arduino Function that returns a String object.
Does it have to return a String ?
Incidentally, your function returns a pointer to an array that does not exist once the function ends. If you are determined to use Strings then why not just use the toCharArray() function in your code rather than calling a function that calls it ?
sterretje:
CharArray goes out of scope as soon as you leave the function. So the returned pointer will point to somewhere in memory where the data was in the past.
The rest of your code might use that memory and corrupt the original data.
Indeed that's what happened..
I received a partial string, with some garbage after it..
So what is the best way to return a string from a Function?
Only the String object, and never a char*/char[]?
UKHeliBob:
Does it have to return a String ?
Well, the Arduino function that I use, that returns a String object, is Serial.readStringUntil(),
and it only returns a String.. That's how it was defined..
UKHeliBob:
If you are determined to use Strings then why not just use the toCharArray() function in your code rather than calling a function that calls it ?
Because using .toCharArray() requires several lines of code every time, and not just one,
so to make my code simpler and clearer, and to prevent this code duplication, the idea was to wrap it in a function, and thus not having to write several lines each time I need convert String->char*..
If I am calling a function that only returns a String object,
and then I have to call a function that only accepts a char*,
there's no better and more streamlined way to take the returned value from the first function, and send it to the second?
I must do the conversion myself?
(this might sound small for you, when it's happening just once, but if you have a long code, messing with strings, and the functions sometimes return String, and sometimes accept char*, this really adds a lot of lines of code....)
and you could of course do the .readStringUntil() within the FillCstring function and include a maximum size to the cstr (or TheString.length()+1) , actually you really should, but now you can declare the charArray locally and fill it. And not have the memory possibly fragmented.
If I need to create a function that gets a Byte array (the function just reads from it, it doesn't write to it)
Must the function have 2 parameters? function(byte* ByteArray, ArrayLength)
Can't it have 1 parameter function(byte* ByteArray)
and inside the function, sizeof(ByteArray) will help to get the Length?
If not,
when can sizeof(SomeArray) help us, and when can't it?
sizeof() in the function will return the size of the pointer, not of the array.
It depends what is in that byte array. If it's non-text, you have to specify the length. If it's text, you can use strlen(). But in that case it's better to use a char array.
sterretje:
2)
malloc() returns a pointer so you will encounter the same problem.
Not quite. malloc() does allocate the specified amount of memory (if it can) and returns a pointer to it. However, that memory remains in existence and valid to use even after the function that called malloc() returns. So, as long as you save the pointer's value, you can use the memory.
However, I don't recommend @card5 use this technique. You can quickly get in trouble with it if you don't know what you're doing. Repeatedly calling a function that calls malloc() will quickly lead to grief unless the memory is properly de-allocated when no longer needed. Even then, the order of the allocation / de-allocation sequence will probably be important on a limited-memory platform.