How to convert a float to a string

Hi, I'm trying to write data from a Grove 6-axis accelerometer and gyroscope and enter it into a file. This is how I plan to write it

sensorData.println(ax + "," + ay + "," + az + "," + gx + "," + gy + "," + gz);

I'm assuming that the data needs to be a string to join it like this, so I was wondering how I would convert it from a float so it can be joined and written to the file.

Also I think this is how you join strings, but I might be confusing languages, so correct me if I messed anything up

Although correct, it's the dangerous way Concatenation with + will create temporary String objects. There is also no need as you just as well can use

sensorData.print(ax);
sensorData.print(",");
...
...
1 Like

When we execute the following command, the 12.57 exactly appears on the ASCII-type Serial Monitor. Here, the print() method converts 12.57 into their corresponding ASCII codes: 0x31, 0x32, 0x2E, 0x35, 0x37.

Serial.print(12.57, 2); 

look this over.
can be simplified

output

  0: 1.20
  1: 3.40
  2: 5.60
  3: 7.80
  4: 9.00
  5: 2.20
1.20, 3.40, 5.60, 7.80, 9.00, 2.20

const int N = 6;
float f   [N] = { 1.2, 3.4, 5.6, 7.8, 9.0, 2.2 };
char  str [N][10];
char  s   [90];

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

    for (int n = 0; n < N; n++)  {
        dtostrf (f [n], 1, 2, &str [n][0]);
        sprintf (s, " %2d: %s", n, &str [n][0]);
        Serial.println (s);
    }


    strcpy (s, &str [0][0]);
    for (int n = 1; n < N; n++) {
        strcat (s, ", ");
        strcat (s, &str [n][0]);
    }
    Serial.println (s);
}

void loop () { }

thanks! would this also work if I were to use file.print?

it generates a c-string, so anywhere a string can be passed, even to the file and to the serial monitor for debugging

this version is tighter

Output

1.20,1.20,3.40,5.60,7.80,9.00,2.20
const int N = 6;
float f   [N] = { 1.2, 3.4, 5.6, 7.8, 9.0, 2.2 };
char  s   [90];

// -----------------------------------------------------------------------------
char *
genStr (
    float *f,
    int    nVal )
{
    char t [10];

    dtostrf (f [0], 1, 2, s);
    for (int n = 0; n < nVal; n++)  {
        dtostrf (f [n], 1, 2, t);
        strcat (s, ",");
        strcat (s, t);
    }
    return s;
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);
    Serial.println (genStr (f, N));
}

void loop () { }

Not quite. If you actually have a String object, then you can use + to concatenate the usual suspects via the StringSumHelper subclass

friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);

through the magic of implicit conversion

StringSumHelper(const String &s) : String(s) {}
StringSumHelper(const char *p) : String(p) {}
StringSumHelper(char c) : String(c) {}
StringSumHelper(unsigned char num) : String(num) {}
StringSumHelper(int num) : String(num) {}
StringSumHelper(unsigned int num) : String(num) {}
StringSumHelper(long num) : String(num) {}
StringSumHelper(unsigned long num) : String(num) {}
StringSumHelper(float num) : String(num) {}
StringSumHelper(double num) : String(num) {}

So given

float f = 0.0625;
const char *p = "c-string";
String s = "object";
int i = 4;

You actually can't

auto x = f + p;  // error: invalid operands of types 'float' and 'const char*' to binary 'operator+'

add a float to a pointer. But if you start with a String, you can concat the float to it (hard-coded to use two decimal places), resulting in another String; and then repeat with the c-string (or any of those others)

auto y = s + f + p;
auto z = i + p;
Serial.println(y);  // object0.06c-string
Serial.println(z);  // ring

The last case is where you can get in trouble easily. You can add an integer to a pointer -- i.e. "pointer math" -- but C/C++ will not do any bounds checking, and that might not be what you intended anyway.

If you're just going to print the results once, then I agree that using print to do each part directly is slightly wordier to type, but better otherwise. It also has the benefit of being able to choose the number of decimal places.

If you want to reuse the resulting string, you may be able to minimize memory issues by reserving the desired space and calling concat directly, or by using +=, which does that for you

s.reserve(20);
s += f;
s += p;
s += i;
Serial.println(s);           // object0.06c-string4
Serial.println(s.length());  // 19

Very easy to write and read. BTW, the float-to-String conversion uses dtostrf anyway

unsigned char String::concat(float num)
{
	char buf[20];
	char* string = dtostrf(num, 4, 2, buf);
	return concat(string, strlen(string));
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.