How do you convert a float to string (SOLVED)

I am having a very tough time converting float to string.

I am getting some data from GPS. The coordinates are in float.

I want something like

String gpsString;

//Imma gonna call this function in the loop
void checkGPS() {
     //Assuming we already have the coordinates
    float flat, flong.

    //I want to do something like this
    gpsString ="";  //make sure the string is empty if its not
    gpsString += flat;
    gpsString += " ";
    gpsString += flong.
    Serial.println(gpsString);
}

I have tried a couple of things like without success. Perhaps I did it wrongly, but I could

sprintf(gpsString, "Lat: %f", flat);
dtostrf(flat, 8, 6, &gpsString[1]);

Kindly assist with some clear examples.

Thank you in advance.

1 Like

float f = 123.456; // example
string mystring;

mystring = String(f);

Here we go again with Strings and strings.

A String is not a string.

A String is an object supported by the String library. Using them is likely to fragment memory usage which with the limited resources available on the Arduino can cause problems.

A string is an array of chars terminated by a null. Using them does not fragment memory because they are not continually created and destroyed.

To add to the fun the OP has tried to use a String with the sprintf() function
sprintf(gpsString, "Lat: %f", flat);That won't work because the sprintf() function expects a char array as its target.

To add to the fun the Arduino implementation of sprintf() does not support the floating point format (%f)

So, what to do ?
I suppose the first question is why do you want to convert the float in the first place ?

2 Likes

I have to agree with ULHeliBob; avoid the String class like the plague. There are probably a bazillion ways to solve your problem, and one might be:

void setup() {
  int i;
  float val;
  char buff[10];
  
  Serial.begin(115200);
  val = 0.0;
  for (i = 0; i < 10; i++) {
    snprintf (buff, sizeof(buff), "%f", val);
    Serial.println(val);
    val += 5.0;
  }
}

void loop() {}

Note you can change the format specifier (i.e., the "%f") if you need different decimal values.

Note you can change the format specifier (i.e., the "%f") if you need different decimal values.

Except that the %f format specifier is not supported on the Arduino. The dtostrf() function uses a different approach with similar results.

1 Like

econjack:
I have to agree with ULHeliBob; avoid the String class like the plague. There are probably a bazillion ways to solve your problem, and one might be:

void setup() {

int i;
  float val;
  char buff[10];
 
  Serial.begin(115200);
  val = 0.0;
  for (i = 0; i < 10; i++) {
    snprintf (buff, sizeof(buff), "%f", val);
    Serial.println(val);
    val += 5.0;
  }
}

void loop() {}




Note you can change the format specifier (i.e., the "%f") if you need different decimal values.

Hi do I print that?

I tried "Serial.println(buff)", it prints a '?'.

Then, I also tried looping it to print out each character stored,

void setup() {
  int i;
  float val;
  char buff[10];
  
  Serial.begin(115200);
  val = 0.0;
  for (i = 0; i < 10; i++) {
    snprintf (buff, sizeof(buff), "%f", val);
    Serial.print("val: ");
    Serial.println(val);
    val += 5.0;
  }
  
  Serial.println("Contents of Buffer: ");
  for (int a=0; a<10; a++) {
    Serial.println(buff[a]);
  }
  
}

void loop() {
}

The output is as below:

val: 0.00
val: 5.00
val: 10.00
val: 15.00
val: 20.00
val: 25.00
val: 30.00
val: 35.00
val: 40.00
val: 45.00
Contents of Buffer: 
?

For what PaulS says you can't do this line:

snprintf (buff, sizeof(buff), "%f", val);

I'll do something like:

void setup() {
  int i;
  float val;
  int val_int;
  int val_fra;
  char buff[10];
  #define DEC_PLACES 1000
  Serial.begin(115200);
  val = 0.0;
  for (i = 0; i < 10; i++) {
    val_int = (int) val;   // compute the integer part of the float 
    val_fra = (int) ((val - (float)val_int) * 1000);   // compute 3 decimal places (and convert it to int)
    snprintf (buff, sizeof(buff), "%d.%d", val_int, val_fra); //
    Serial.println(val);
    val += 5.0;
  }
}

Ahhaaaa!!! Eureka!!

I worked my butt off and tried to read and understand dtostrf at avr-libc: <stdlib.h>: General utilities

Modified the codes so its like this. I should modify a couple of things later, but I think I got it right this time right?

#include <stdlib.h>

void setup() {
  int i;
  float val;
  char buff[10];
  String valueString = "";
  Serial.begin(115200);
  val = 0.0;
  for (i = 0; i < 10; i++) {
    dtostrf(val, 4, 6, buff);  //4 is mininum width, 6 is precision
    Serial.print("val: ");
    Serial.println(val);
    val += 5.0;
    valueString += buff;
    valueString += ", ";
  }
  Serial.println(valueString);
}

void loop() {
}

So the output is like this:

val: 0.00
val: 5.00
val: 10.00
val: 15.00
val: 20.00
val: 25.00
val: 30.00
val: 35.00
val: 40.00
val: 45.00
0.000000, 5.000000, 10.000000, 15.000000, 20.000000, 25.000000, 30.000000, 35.000000, 40.000000, 45.000000,
2 Likes

Good work!

Can you change the subject of the post to solved.

Regards.

I have changed the subject to solved.

Oh one more question, if I were to call that in a loop, I would need to clear the buffer. How do I clear the buffer??

I'm not a guy of C++ so I don't use "String", but I've read here in the forum that is not good use this way to have a strings.

In the way you had write the code, clear the "buffer" with name valueString is done like you already did:

  String valueString = "";

If you want to do this in other place than the definition of the variable, it's simply :

  valueString = "";

The "buffer" with name buf it's cleared every time you do:

dtostrf(val, 4, 6, buff);

If you want to correct your code and do all strings the same way, you can declare the string like:

  char valueString[100];

concatenate the string, like:

strcat(valueString, buff);
strcat(valueString, ", ");

and clear the string like:

strcpy(valueString, "");

Note that the 100 in the line "char valueString[100];", must be a number long enough to hold the entire string.

1 Like

visualxl:
Ahhaaaa!!! Eureka!!

I worked my butt off and tried to read and understand dtostrf at avr-libc: <stdlib.h>: General utilities

Modified the codes so its like this. I should modify a couple of things later, but I think I got it right this time right?

#include <stdlib.h>

void setup() {
 int i;
 float val;
 char buff[10];
 String valueString = "";
 Serial.begin(115200);
 val = 0.0;
 for (i = 0; i < 10; i++) {
   dtostrf(val, 4, 6, buff);  //4 is mininum width, 6 is precision
   Serial.print("val: ");
   Serial.println(val);
   val += 5.0;
   valueString += buff;
   valueString += ", ";
 }
 Serial.println(valueString);
}

void loop() {
}





So the output is like this:



val: 0.00
val: 5.00
val: 10.00
val: 15.00
val: 20.00
val: 25.00
val: 30.00
val: 35.00
val: 40.00
val: 45.00
0.000000, 5.000000, 10.000000, 15.000000, 20.000000, 25.000000, 30.000000, 35.000000, 40.000000, 45.000000,

Do you have the complete coding to convert the gps data? ive been trying to figure out how to do this. Im sending the coordinates through LoRa but it seems impossible for me to do it using floats, but its easy enough to send strings data through LoRa. It would be great if you could help me out.

You say this is solved but I wouldn't be surprised to see you back here with your program randomly crashing because you ignored the advice to avoid the String class (capital S) in favour of a C-style string.

    dtostrf(val, 4, 6, buff);  //4 is mininum width, 6 is precision

How do you reasonably expect to print at least one digit before the decimal point, a decimal point, and 6 digits after the decimal place, in a field of width 4?

Yes, I know that it is 4 or more, but your values just look dumb.

1 Like

PaulS:

    dtostrf(val, 4, 6, buff);  //4 is mininum width, 6 is precision

How do you reasonably expect to print at least one digit before the decimal point, a decimal point, and 6 digits after the decimal place, in a field of width 4?

Yes, I know that it is 4 or more, but your values just look dumb.

My code just worked perfectly. Thank you guys