Other Functions

sprintf

sprintf, snprintf, printf, vsprintf, vsnprintf

One commonly used function in the standard C library is sprintf(), which is used to format a string with variables. This also includes variations like snprintf() and also functions that call snprintf() internally, like Log.info() and String::format().

This example shows several common formatting techiques along with the expected output.

#include "Particle.h"

SerialLogHandler logHandler;

int counter = 0;
const std::chrono::milliseconds testPeriod = 30s;
unsigned long lastTest = 0;

void runTest();

void setup() {
}

void loop() {
    if (millis() - lastTest >= testPeriod.count()) {
        lastTest = millis();

        runTest();
    }
}

void runTest() {
    Log.info("staring test millis=%lu", millis());
    // 0000068727 [app] INFO: staring test millis=68727

    // To print an int as decimal, use %d
    Log.info("counter=%d", ++counter);
    // 0000068728 [app] INFO: counter=1

    // To print an int as hexadecimal, use %x
    int value1 = 1234;
    Log.info("value1=%d value1=%x (hex)", value1, value1);
    // 0000068728 [app] INFO: value1=1234 value1=4d2 (hex)

    // To print a string, use %s
    const char *testStr1 = "testing 1, 2, 3";
    Log.info("value1=%d testStr=%s", value1, testStr1);
    // 0000068728 [app] INFO: value1=1234 testStr=testing 1, 2, 3

    // To print a long integer, use %ld, %lx, etc.
    long value2 = 123456789;
    Log.info("value2=%ld value2=%lx (hex)", value2, value2);
    // 0000068729 [app] INFO: value2=123456789 value2=75bcd15 (hex)

    // To print to a fixed number of places with leading zeros:
    Log.info("value2=%08lx (hex, 8 digits, with leading zeros)", value2);
    // 0000068729 [app] INFO: value2=075bcd15 (hex, 8 digits, with leading zeros)

    // To print an unsigned long integer (uint32_t), use %lu or %lx
    uint32_t value3 = 0xaabbccdd;
    Log.info("value3=%lu value3=%lx (hex)", value3, value3);
    // 0000068730 [app] INFO: value3=2864434397 value3=aabbccdd (hex)

    // To print a floating point number, use %f
    float value4 = 1234.5;
    Log.info("value4=%f", value4);
    // 0000068730 [app] INFO: value4=1234.500000

    // To print a double floating point, use %lf
    double value5 = 1234.333;
    Log.info("value5=%lf", value5);
    //  0000068731 [app] INFO: value5=1234.333000

    // To limit the number of decimal places:
    Log.info("value5=%.2lf (to two decimal places)", value5);
    // 0000068732 [app] INFO: value5=1234.33 (to two decimal places)

    // To print to a character buffer
    {
        char buf[32];
        snprintf(buf, sizeof(buf), "%.3lf", value5);

        Log.info("buf=%s (3 decimal places)", buf);
        // 0000068733 [app] INFO: buf=1234.333 (3 decimal places)

        Particle.publish("testing", buf);
    }

    // To print JSON to a buffer
    {
        char buf[256];

        snprintf(buf, sizeof(buf), "{\"value2\":%ld,\"value5\":%.2lf}", value2, value5);
        Log.info(buf);
        // 0000068734 [app] INFO: {"value2":123456789,"value5":1234.33}

        Particle.publish("testing", buf);
    }

    // Using String::format
    Particle.publish("testing", String::format("{\"value1\":%d,\"testStr1\":\"%s\"}", value1, testStr1).c_str());
}

One caveat is that sprintf-style formatting does not support 64-bit integers. It does not support %lld, %llu or Microsoft-style %I64d or %I64u.

As a workaround you can use the Print64 firmware library in the community libraries. The source and instructions can be found in Github.

Variation Supported Purpose
sprintf() Prints to a buffer, but snprintf is recommended to prevent overflowing the buffer.
snprintf() Prints to a buffer, recommended method.
vsprintf() Prints to a buffer, using va_list variable arguments.
vsnprintf() Prints to a buffer, using va_list variable arguments and buffer size.
printf()   Prints to standard output, use Log.info() instead.
vprintf()   Prints to standard output, using va_list variable arguments. Not supported.
fprintf()   Prints to a file system file. Not supported.
vfprintf()   Prints to a file system file, using va_list variable arguments. Not supported.