printf to the serial port?

In what I've read, printf outputs to stdout. Wouldn't it's output just as easily go to Serial.print()?

It prints: Joe -1

void setup() {
    char buf[20];
    Serial.begin(9600);
    sprintf(buf,"%20s","Joe");
    Serial.println(buf);
    Serial.println(printf("%20s","Dave"));
}

void loop() {
}

Both sprintf() and printf() return the number of characters converted, not a pointer to data. Since printf() code does not do conversions, it returns -1 on error. So your code displays "Joe" and -1. Changing the printf() call to sprintf() changes the value to 4; still not what you want.

Your (corrected) code generates 3368 bytes of code, while the alternative which avoids sprintf() uses only 1886 bytes. True, sprintf() is a powerful function, but one rarely uses all of that power so simply string functions can save a lot of memory.

void setup() {
    char buf[20];
    Serial.begin(9600);
    strcpy(buf, "Joe");                // Alternative to sprintf()
    //sprintf(buf,"%20s","Joe");
    Serial.println(buf);
    //sprintf(buf,"%20s","Dave");
    strcpy(buf, "Dave");               // Same here...
    Serial.println(buf);
}

void loop() {
}

I was trying to accomplish padding and your example doesn't do that. However I see where I misunderstood the way printf works. Thank you.

“since printf() code does not do conversions, it returns -1 on error.”

That is not true. printf returns an error because its stream is not open.

I use (disregarding the memory penalty):

/*
 Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */
 
/**
 * @file printf.h
 *
 * Setup necessary to direct stdout to the Arduino Serial library, which
 * enables 'printf'
 */

#ifndef __PRINTF_H__
#define __PRINTF_H__

#ifdef ARDUINO

int serial_putc( char c, FILE * ) 
{
  Serial.write( c );

  return c;
} 

void printf_begin(void)
{
  fdevopen( &serial_putc, 0 );
}

#else
#error This example is only for use on Arduino.
#endif // ARDUINO

#endif // __PRINTF_H__

After including that each printf goes to the serial stream.
(You have to call printf_begin() in setup.)

You can pad the result if you want either directly or by writing a pad() function. For example:

void setup() {
    char buf[20];
    Serial.begin(9600);
    strcpy(buf, "Joe");
    pad(buf, sizeof(buf) - strlen(buf) + 1);   // Save room for null
    Serial.println(buf);
    
    strcpy(buf, "Dave");
    pad(buf, sizeof(buf) - strlen(buf) + 1);
    Serial.println(buf);
}

void pad(char *s, int spaces)
{
  char temp[40];            // Set to max expected size

  memset(temp, ' ', spaces);
  temp[spaces] = '\0';
  strcat(temp, s);
  strcpy(s, temp);
}


void loop() {
}

@Whandall:

That is not true. printf returns an error because its stream is not open.

Perhaps not phrased correctly. Still, my guess is that trying to write to an unopened stream is an error. Either way, it's not going to work the way the OP thought it would.

Nice! Why does it fail when I make buf[20] a global though?

char buf[20];

void setup() {

    Serial.begin(9600);
    strcpy(buf, "Joe");
    pad(buf, sizeof(buf) - strlen(buf) + 1);   // Save room for null
    Serial.println(buf);
    
    strcpy(buf, "Dave");
    pad(buf, sizeof(buf) - strlen(buf) + 1);
    Serial.println(buf);
}

void pad(char *s, int spaces)
{
  char temp[40];            // Set to max expected size

  memset(temp, ' ', spaces);
  temp[spaces] = '\0';
  strcat(temp, s);
  strcpy(s, temp);
}


void loop() {
}

econjack: @Whandall: Perhaps not phrased correctly. Still, my guess is that trying to write to an unopened stream is an error. Either way, it's not going to work the way the OP thought it would.

Thats why I showed a way how to use printf on the serial :-)

@freakdaddy

Why does it fail when I make buf[20] a global though?

I'm away from my system, but what happens if you put:

delay(100);

after Serial.begin()?

It's weird... It works then but the output is...

                  Joe
                 Davh

Note Davh instead of Dave.

Why does it need the delay.

Is there a spelling error in your code? I have no explanation for that since it worked fine on my machine.

Creating the Serial object takes a small time slice, so the delay() gives it time to establish the object before you try to use it. You might try cutting the delay() constant down to see how small you can get it.

I think

pad(buf, sizeof(buf) - strlen(buf) + 1);

should be...

pad(buf, sizeof(buf) - strlen(buf) - 1);

and buf[20] needs to be buf[21]

If I want to print "Joe" with 17 preceding spaces so my end result is 20 chars I would need a 21 char array right?

So the calculation sizeof(buf) - strlen(buf) + 1 or 20 - 3 + 1 = 18; 18 spaces plus "Joe" = 21; 21 will overflow the array.

Am I thinking about this wrong?

My bad. It should be:

    pad(buf, sizeof(buf) - (strlen(buf) + 1) );   // Save room for null

which, for "Joe", becomes:

pad(buf, 20- (3 + 1)); // Save room for null pad(buf, 20- 4); // Save room for null pad(buf, 16); // Save room for null

which is the padding if you want to stay within your 20 char limit.

Ok... Thank a lot! I appreciate it!!

econjack: @freakdaddyI'm away from my system, but what happens if you put:

delay(100);

after Serial.begin()?

That delay is completely unnecessary, except on one or two specific Arduino boards (Uno? Leonardo?).

Regards, Ray L.

@Ray: A delay should only be necessary for the Leonardo board. I think it should work on all others without a delay. Since he was having a problem and I didn't know the board he was using, that was the only thing I could think of, which is why I asked him to report what happens if he added the delay.

Once econjack fixed a small error the code worked without the delay. Strange that delay fixed it since I know that is for Leonardo but it did. This was on a Mega 2560.

I wonder if my "incorrect" first example was stomping on something important, since it would write past the end of the string. That is, my error meant writing to element 21 when the array only had 20 elements.

It messes with Serial. On a Micro it stopped working completely, no output at all. Corrected version works perfectly.