I’d be really grateful if somebody could give me some guidance on this.
I’m still new to Arduinos and I am trying to tidy up some sketches by using functions, or more specifically functions that return values. This is new to me.
In the sketch attached I pass a float to a function called NumToChar() hoping to get a character string returned.
In the function I Serial.print the character string before returning it just to make sure that the function is doing what it is supposed to, but when the variable is returned it is empty.
I’ve included another simple function for area just to make sure that I am returning variables.
Can anybody tell me why the Serial.println(NumToChar(3.142)); prints nothing?
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
Serial.println(NumToChar(3.142));
Serial.print("Area =");
Serial.println(areaCalc(4, 5));
delay(3000);
}
/////////////////////////////////////////////////////////////
char* NumToChar(float number)
{
String numberAsString = String(number, 3) + ","; // convert float to String
int str_len = numberAsString.length() + 1; // find string length
char numberAsChar[str_len]; //declare char of correct length
numberAsString.toCharArray(numberAsChar, str_len); // convert String to char string
Serial.print(numberAsChar);
return numberAsChar;
}
/////////////////////////////////////////////////////////////
int areaCalc(int length, int width) {
int area = (length * width);
return area;
}
what microcontroller are you using?
if a low power micro such as a Uno, Mega, etc avoid using String class as they can fragment memory, cause problems and possible crash the program#
This variable numberAsChar is deleted as soon as the function returns
Either make this variable static, or use a global variable, or add another parameter to the function, which will be a char array where the result of the function can be stored
For safety, you can add another parameter to the function, which will be the size of that char array, and make sure your function doesn't write more than that into the char array
The function that I am using to write data to an SD card uses char strings. I could probably change that function but that would lead me to further problems.
At the moment I am finding that every obstacle that I overcome requires me to overcome other obstacles, all of which require me to overcome other obstacles ad infinitum.
It's 30 years since I was a graduate engineer but I'm feeling more like a graduate every day. I don't feel any younger though.
That's a very good observation and a good question by implication.
char* NumToChar(float number)
{
The function definition promises to return a pointer to char, that's what the * means in this context.
Inside the function, you create an array of characters. In C/C++, arrays can be handed around just by using a pointer. The name of the array can be thought of as is in fact a pointer to char.
char numberAsChar[str_len]; //declare char of correct length
So the function happily returns said pointer, viz:
return numberAsChar;
but unfortunately, the array that the pointer is pointing to ceases to exist at around exactly the same time, when the function exits.
The solution offered above
means that the variable remains in existence, and retains its contents, across calls to the function.
One small detail is that since a static array must have its size determined ahead of time, you cannot make the array size differ from call to call, so it would have to be a fixed size, and one would need to ensure that it was large enough for all things that were put into it.
Just go with other solutions and trust that someday this will make sense.
I liken the situation to this. Imagine you are hiring a private investigator because you need a picture of a mystery guy so you can identify him.
The int function is like a PI that promises to get you a picture of the guy. And he does bring you back a picture of the guy.
The char* function returns a pointer. That's like a PI that says he will get you the address of the house where the guy lives so you can go get your own picture. And he does. And it is the correct address. The problem is that the guy has moved out before you got there to take his picture.
It would be unusual but not inconceivable, like strtok() which now has its better modern version strtok_r(), the code for which makes interesting reading.
What I meant was that today it is conceivable. Once upon a time it was all just one thread on an AVR. But some of these new boards are kind of impressive. A lot of old arguments don't hold anymore.
No, I got that. I came up from playing with things that made the UNO feel like I'd never run out of anything… most of what I do is like cutting butter with a blowtorch using the now "low end" micros.
I feel bad for ppl coming the other way and wondering where all the things they're used to are to be found.
I wish I could quote one recent newcomer who said something like "normally I'd just thread this out".
Even in a single-thread, single-core environment, functions that are called by both ISR and non-ISR code need to be reentrant-safe.
Recursive algorithms, admittedly, aren't seen much in Arduino Land. But they exist. For instance, in the "SD_Test.ino" example in the ESP32 core, the listDir() function is recursive.