Yeah, well when C++ can create formatted output the simple way C can,
I'll concede but until then xxxprintf() functions are the way to really do formatting.
C++ in all its years of trying to stream i/o has yet to create decent formatting capablities
that are as easy to use as xxxprintf() functions.
(try to output a 4 digit numeric field that is zero filled, as an example)
AND.... todays gcc compilers have knowledge of printf and its formatting strings and check
the types of all the arguments passed to the functions against the expected types
based on the formatting string at compile time.
So you have the type checking of C++ builtin to the compiler with the added
benefit of variable arguments and easy to use formatting capability strings.
Kind of the best of all worlds.
It isn't like the old days where you could easily pass an incorrect format string
or invalid argument to a printf function.
Now you get a warning or even an error depending on your compile options.
So the C++ type checking argument of not using printf() no longer applies
(for most uses of the printf() functions).
===
One of the issues with AVRs and printf() type functions is the RAM usage.
Strings by default end up in the data section when using gcc
and all things in the "data" sections end up in RAM.
This means that all printf formatting strings will consume RAM.
The way to correct this is to move the strings into flash. But that means calling
non standard printf() functions and using a casting element each time you
declare a printf() formatting string. This is a total pain and most people
simply will not do it.
Here is a collection of functions and macros that I wrote that hides all this complexity
and moves the formatting strings off to FLASH automagically.
/*
* Define a REAL printf since Arduino doesn't have one
*
* SerialPrintf() will automatically put the format string in AVR program space
*
*/
#define SerialPrintf(fmt, ...) _SerialPrintf(PSTR(fmt), ##__VA_ARGS__)
extern "C" {
int serialputc(char c, FILE *fp)
{
if(c == '\n')
Serial.write('\r');
Serial.write(c);
}
}
void _SerialPrintf(const char *fmt, ...)
{
FILE stdiostr;
va_list ap;
fdev_setup_stream(&stdiostr, serialputc, NULL, _FDEV_SETUP_WRITE);
va_start(ap, fmt);
vfprintf_P(&stdiostr, fmt, ap);
va_end(ap);
}
To use it, simple call
SerialPrintf() just like you would use printf().
Thats it.
--- bill