3-line printf-style hack

There are times (usually debugging) when I really hate having to type lines and lines of stuff like this:

Serial.print("a = ");
Serial.print(a, DEC);
Serial.print(", b = $");
Serial.println(b, HEX);

...and I just wish I had a proper printf() type of function for writing to the serial port.

Well printf and friends are actually in the AVR libc library so here's a 3-line hack to give a printf-like function, which would ideally be incorporated into Serial already as Serial.printf().

#include <stdio.h>
char _str[32]; // 32 chars max! increase if required to avoid overflow
#define writeln(...) sprintf(_str, VA_ARGS); Serial.println(_str)

int a = 2, b = 3;

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

writeln("We're using writeln here\n");

writeln("a = %d, b = %d, a+b = %d", a, b, a+b);
}

void loop() {
for (int i = 0; i < 256; i++) {
writeln("i = %3d ($%02x)", i, i);
delay(200);
}
}

I've found this useful so I'm presenting it here purely as a convenient hack...

Disadvantages are that it would be easy to overflow the _str[] buffer, but I've kept it small to save space (it's easy enough to make it bigger). Also that the vfprintf() library uses quite a lot of memory, but for smaller sketches there may be times when it's worth the trade-off.

Flames to /dev/null, as we used to say.... :wink:

Docs for printf/sprintf/vfprintf are here: avr-libc: <stdio.h>: Standard IO facilities

Oh man, I am not sure that information will be a help or hindrance to those not already familiar with sprintf and the murky consequences of buffer overflow.

It's worth re-emphasizing that its really easy to overflow the buffer, the compiler gives absolutely no warning of this and the runtime consequences are difficult to predict. Its about the worst thing that can happen if you are trying to debug code that isn't working.

Unless one enjoys living dangeriously, or is in full command of how the sprintf arguments will be expanded, my advice is to spend a few extra seconds typing those compound Serial.print statements :wink:

Unless one enjoys living dangeriously,

I believe I used the work "hack" in bold. :wink:

So what's chances of a Serial.printf() then? Is there any good reason not to have it, apart from the size of the library?

The library is big, the syntax is obscure (especially compared to the core Arduino API), the syntax is different from the equivalent functionality in Processing, and it could be tough to implement properly in a memory-constrained environment (e.g. what do you we do if we don't have enough space for a buffer big enough to hold everything someone wants to print). Plus, the existing Serial API can do pretty much anything printf() can, it just takes a bit more text. I like the idea of making printf() easy for advanced users to hack into their code, but I'm wary of including it in the API.

Good show, just one small comment ....

You call it "writeln()" and use "Serial.println()", wouldn't it be more appropriate to call "Serial.print()" and put in the '\n' yourself ... if, where, and when you want it????

Buffer overflow considerations aside, I want it for formating stuff to LCD displays, where a 20-40 byte buffer is all I need and if I ain't payin attenshun to my line size I deserve whatever I get!!!!!

Thanks for a good idea ...

cheers ... BBR

You call it "writeln()" and use "Serial.println()", wouldn't it be more appropriate to call "Serial.print()" and put in the '\n' yourself ... if, where, and when you want it????

yeah good point.

I think with 'writeln' i was subliminally harking back to days of Pascal :wink:

There now seems to be a proble in Arduino 0011 invoking stdio.h ... see this thread http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213815025

cheers ... BBR

put this...

#undef int

before the #include <stdio.h>

it's a problem with v11, which redefines int for some reason which I forget.