The wrong thig with option 3 is the buffer length, you should use snprintf instead.
The other problem is that first you build the string, then you print the output, the program traverses the string twice. Option 2 creates object from string, then applies + operator to create a new string, then prints it - it is comfortable with short strings, but least efficient (depends on the compiler optimalizations).
Option 1 is most effective, since it directly prints arguments to the output char by char (see Arduino Print class) and traverses the arguments only once.
You can use stdarg.h to create one-liner with Serial.prints:
#include <stdarg.h>
void Serialprintln(const char* input...) {
va_list args;
va_start(args, input);
for(const char* i=input; *i!=0; ++i) {
if(*i!='%') { Serial.print(*i); continue; }
switch(*(++i)) {
case '%': Serial.print('%'); break;
case 's': Serial.print(va_arg(args, char*)); break;
case 'd': Serial.print(va_arg(args, int), DEC); break;
case 'b': Serial.print(va_arg(args, int), BIN); break;
case 'o': Serial.print(va_arg(args, int), OCT); break;
case 'x': Serial.print(va_arg(args, int), HEX); break;
case 'f': Serial.print(va_arg(args, double), 2); break;
}
}
Serial.println();
va_end(args);
}
Then you can use it like sprintf (but efficiently):
void setup() {
int n = 42;
float f = 42.42;
const char* s = "answer";
Serial.begin(9600);
// The answer is 42 (101010 BIN, 2A HEX), in float 42.42
Serialprintln("The %s is %d (%b BIN, %x HEX), in float %f", s, n, n, n, f);
}
void loop() {
}