[Code] Sprintf alternative that actually works with floats and doubles

Hey, so I have been trying to get some json data off my photon, and found that lots of people have issues when it comes to using sprintf.

Help with “sprintf” formatting for doubles in preparation for JSON
Issues with converting float to string with sprintf
[Solved] Problem using sprintf on spark

The topics above were all great and helpful, but no real solution exists if you’re trying to return data as such on a photon:

{"Humidity":49.10, "Celsius":23.60, "Feels Like":25.25}

Why? Because all you get on the other side when you do:

sprintf(publishString,"{\"Humidity\": %2.2f, \"Celsius\": %2.2f, \"Feels Like\": %2.2f}",h,t,hi);

or

sprintf(publishString,"{\"Humidity\": %f, \"Celsius\": %f, \"Feels Like\": %f}",h,t,hi);

is the following:

{"Humidity":49.10, "Celsius":23.60, "Feels Like":25.25}

This is true as of SPARK FIRMWARE V0.3.4 (OCT 21). So likely this post will be deleted at some point when this is fixed.

Luckily, this is C++, and even though I am not an avid C++ developer, I was able to figure this out, so here goes how I solved this issue myself.

// make sure this is outside your loop
char publishString[64];

// And then inside your loop
strcpy (publishString,"{\"Humidity\":");
strcat (publishString,String(h, 2));
strcat (publishString,", \"Celsius\":");
strcat (publishString,String(t, 2));
strcat (publishString,", \"Feels Like\":");
strcat (publishString,String(hi, 2));
strcat (publishString,"}");

This is just string concatenation (instead of interpolation), but works a treat. References for strcat and strcpy are linked.

Let me know if you know of any different solutions

1 Like

I think i said this in another thread, if you just want a work around for sprintf while you are waiting for it to get fixed you can do this

sprintf(publishString,"{“Humidity”: %d.%.2d, “Celsius”: %d.%.2d, “Feels Like”: %d.%.2d}",h/100,h%100,t/100,t%100,hi%100,hi/100);
where h,t and hi are integers that are the original doubles (or floats) multiplied by 100.
Probably not ideal but as a temporary workaround it keeps the code very similar to what it will be once the sprintf implementation that includes floats is re-implemented.

Here is how I did it with the native methods. I will leave the commented out sprintf so you can see it in context. Pretty close.

char *getTemp(int tempIndex) {
    static char retbuf[64];
    sensor.requestTemperatures();
    temperature=sensor.getTempC(deviceIndexArray[tempIndex]);
    //sprintf(retbuf, "{\"value\":%.4f}", temperature*1.8 + 32); 
    String s = "{\"value\": ";
    s.concat(String(temperature*1.8 + 32));
    s.concat("}");
    s.toCharArray(retbuf, 64);
    return retbuf;
    
}
1 Like

Thanks team. the combination of s.concat and @mplacona’s string(float, decimal places) saved me from going crazy due to yet another Photon bug.

Seriously. unboxed it two nights ago, and spent 5 hours getting it to just work, though I know I’ll be missing prior PWM functionality for a lil’ while.

THANK YOU!

I have been struggling to find a fast and clean workaround for the sprintf() function not playing well with floats; a known issue around the forums. This trick is nice in that we dont use the String function at all.

I’m running this in a loop that cycles several hundred times a day. If anyone knows of a heap corruption issue with this technique, I’d like to know.
Thanks

I seem to be missing the point of this thread.
What's the problem?

sprintf() is working fine for ages now IMHO.

I can't spot the difference :confused:

The output is the same in both instances. The difference is the surprising number of threads describing issues having to do with Strings eating up the heap after repeated iterations. I’m not an expert and know nothing more than what I read. My original inquiry was just to find a way for Strings to handle floats…

sprintf() is the way to stay clear from String but that’s not the topic of this thread.
This thread was valid very early during Particle (Spark) teething troubles, but that’s long gone.