for loop in float to char conversion.

Hello I did a simple code to convert float into char, and then the char again into float.
But when I’m adding a for loop to print all single Bytes inside the char array, all the code will not work anymore.

This below is the code.

//Tx//COM3
float f = 23.52;
float f2 = 10.42;
float f1;
float f3;

float f1_from_outstr = 0.00;


void setup() {
  Serial.begin(9600);
}



void loop() {
f1 = f + random(1,8);
char outstr[6] = "";
dtostrf(f1, 6, 2, outstr);

Serial.print("outstr: "); Serial.print(outstr);
Serial.print(" -->sizeof(outstr): "); Serial.println(sizeof(outstr));
delay(1000);


  
  //for(int i = 0; i < sizeof(outstr)+1; i++) {
    //Serial.print("outstr[i]: "); Serial.print(outstr[i]);
    //Serial.print(" --> in BIN: "); Serial.println(outstr[i],BIN);
    //delay(200);
   //}

char copiedChar [sizeof(outstr)] = "";
strcpy(copiedChar,outstr);
Serial.print("copiedChar: "); Serial.println(copiedChar);
delay(1000);
f1_from_outstr = atof(copiedChar);
f3 = f1_from_outstr - f2;



Serial.print("f3: "); Serial.println(f3);
Serial.println("");
delay(2000);

}

Why is this happening?
Any suggestion in how to improve the code are appreciated. Thank You

So what do you see in the console??

why would you attempt to go beyond the bounds of your array?

 //for(int i = 0; i < [color=red]sizeof(outstr)+1[/color]; i++) {
... Serial.print([color=red]outstr[ i ][/color]);

just to be on the safe side, allocate 20 bytes to outstr at least you won’t be playing with fire there.

why would you attempt to go beyond the bounds of your array?
//for(int i = 0; i < sizeof(outstr)+1; i++) {
… Serial.print(outstr[ i ]);

I thought that maybe if I didn’t put the +1 it won’t print the last Byte of the array, anyway should I change it to i = sizeof(outstr) ?

So what do you see in the console??

if I include the the for loop, basically it will not go out of the loop, and it prints all type of ascii characters.

the strange thing is that if you remove all the part of the code after the for loop, all will work fine also with the small size of the outstr char array.

The last part of the code and the for loop are in conflict, I don’t know why.

Maybe you want to check the documentation for the dtostrf function.

anyway should I change it to i = sizeof(outstr) ?

No, to “i < sizeof(outstr)”

i've checked this example dtostrf().
The function dtostrf works well if I omit the part after the loop, so I think it' s not a problem of dtostrf. What I should I look for, or change in dtostrf? Thanks

The second argument, and the size of the destination buffer

I've changed the second argument WIDTH(is the number of character to use in the output)from 6 to 5 and now it works. But this was pure luck I would like to understand why. Here's my try:

  1. I have a float with two decimals after the point, so in this case I have 5 Bytes.

2)If I set WIDTH = 6 there's no space for an end character such as '\0' or '\n', so if I change WIDTH to 5 and BUFFER(in my case outstr) to 6, I have 1 Byte more than WIDTH. If I not set this, it will happen something strange i can't explain in arduino memory.

3)I can't explain to my self in other ways.

Should this be correct?

No, it wasn’t luck, it was allowing space for the termination zero at the end of the string.

Ok thanks!

TheMemberFormerlyKnownAsAWOL:
The second argument, and the size of the destination buffer

Not sure this is it, the doc described it as

The minimum field width of the output string (including the possible '.' and the possible sign for negative values) is given in width

So this seems more geared towards fitting data in a known space with left or right alignment, but if you have more data to print it might just overflow, esp as the doc states as well

The caller is responsible for providing sufficient storage in s.

Would be easy to test but I’m Not near an Arduino...

Coming back to this, I have a question. When I print the binary of a single Byte that Arduino sends to the Hardware serial port, I noticed that the binary are preceded by two ones → 11.

While the point is equal to: 101110 that is correct.
The 2 would be equal to: 110010
3 = 110011
4 = 110100… and so on.

Is this because they are numbers with a char format?

I’m adding an image of the output I’m receiving

Don’t understand the question.
Please post code and the TEXT of what you receive, not a picture.

TheMemberFormerlyKnownAsAWOL:
The second argument, and the size of the destination buffer

So I did write a simple test and the second argument has nothing to do with constraining what gets written into the buffer but more how things get aligned / padded.

So You really need to size your buffer for the maximum width possible which is a mix of the number representation with the dot and sign at the expected precision and then the left or right padding if there is space.

Here is the code I used

// testing dtostrf https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

char tmpBuffer[30];
double d = -123.456789; // 11 symbols
const int8_t minWidth = 3;
const int8_t maxWidth = 21;
const int8_t precision = 7;

void setup() {
  Serial.begin(115200);
  Serial.println(F("----- WIDTH POSITIVE -----"));
  for (int8_t w = minWidth; w < maxWidth; w++) {
    dtostrf(d, w, precision, tmpBuffer);
    Serial.print(F("Width: "));
    Serial.print(w);
    Serial.print(F("\t["));
    Serial.print(tmpBuffer);
    Serial.print(F("]\tLength = "));
    Serial.println(strlen(tmpBuffer));
  }

  Serial.println(F("\n----- WIDTH NEGATIVE -----"));
  for (int8_t w = minWidth; w < maxWidth; w++) {
    dtostrf(d, -w, precision, tmpBuffer);
    Serial.print(F("Width: "));
    Serial.print(-w);
    Serial.print(F("\t["));
    Serial.print(tmpBuffer);
    Serial.print(F("]\tLength = "));
    Serial.println(strlen(tmpBuffer));
  }
}

void loop() {}

this is what the output in the serial monitor @115200 looks like: (I add square brackets around the buffer to see the impact of padding)

[color=purple]
----- WIDTH POSITIVE -----
Width: 3	[-123.4567900]	Length = 12
Width: 4	[-123.4567900]	Length = 12
Width: 5	[-123.4567900]	Length = 12
Width: 6	[-123.4567900]	Length = 12
Width: 7	[-123.4567900]	Length = 12
Width: 8	[-123.4567900]	Length = 12
Width: 9	[-123.4567900]	Length = 12
Width: 10	[-123.4567900]	Length = 12
Width: 11	[-123.4567900]	Length = 12
Width: 12	[-123.4567900]	Length = 12
Width: 13	[ -123.4567900]	Length = 13
Width: 14	[  -123.4567900]	Length = 14
Width: 15	[   -123.4567900]	Length = 15
Width: 16	[    -123.4567900]	Length = 16
Width: 17	[     -123.4567900]	Length = 17
Width: 18	[      -123.4567900]	Length = 18
Width: 19	[       -123.4567900]	Length = 19
Width: 20	[        -123.4567900]	Length = 20

----- WIDTH NEGATIVE -----
Width: -3	[-123.4567900]	Length = 12
Width: -4	[-123.4567900]	Length = 12
Width: -5	[-123.4567900]	Length = 12
Width: -6	[-123.4567900]	Length = 12
Width: -7	[-123.4567900]	Length = 12
Width: -8	[-123.4567900]	Length = 12
Width: -9	[-123.4567900]	Length = 12
Width: -10	[-123.4567900]	Length = 12
Width: -11	[-123.4567900]	Length = 12
Width: -12	[-123.4567900]	Length = 12
Width: -13	[-123.4567900 ]	Length = 13
Width: -14	[-123.4567900  ]	Length = 14
Width: -15	[-123.4567900   ]	Length = 15
Width: -16	[-123.4567900    ]	Length = 16
Width: -17	[-123.4567900     ]	Length = 17
Width: -18	[-123.4567900      ]	Length = 18
Width: -19	[-123.4567900       ]	Length = 19
Width: -20	[-123.4567900        ]	Length = 20
[/color]

riemanndiy:
Coming back to this, I have a question. When I print the binary of a single Byte that Arduino sends to the Hardware serial port, I noticed that the binary are preceded by two ones --> 11.

While the point is equal to: 101110 that is correct.
The 2 would be equal to: 110010
3 = 110011
4 = 110100.... and so on.

Is this because they are numbers with a char format?

I'm adding an image of the output I'm receiving

You are seeing the binary representation of the ASCII code for the characters.