views:

1516

answers:

15

So I generally use cout and cerr to write text to the console. However sometimes I find it easier to use the good old printf statement. I use it when I need to format the output.

So one example of where I would use this is:

// Lets assume that I'm printing coordinates... 
printf("(%d,%d)\n", x, y);

// To do the same thing as above using cout....
cout << "(" << x << "," << y << ")" << endl;

I know I can format output using cout but I already know how to use the printf. So is there any reason I shouldn't use the C printf statement?

+1  A: 

I've read often on the net that printf is faster (but with no type safety) than the c++ standard stream.

So you should use the standard stream most of the time because the type safety will help make correct code. But if you're in a performance critical application (like a log system in an AAA game for example) you'll need to get most of the performance so using printf might help on this side.

Just don't forget that premature optimization if the root of all evils and that correct code is the priority over faster code.

Klaim
Type safety and format-like functionality are available via boost::format, or, since no one has mentioned it here yet: [FastFormat](http://www.fastformat.org/)
Don Wakefield
+4  A: 

No reason at all. I think it's just some strange ideology that drives people towards using only C++ libraries even though good old C libs are still valid. I'm a C++ guy and I use C functions a lot too. Never had any problems with them.

mingos
c libraries are very good quality, and easy to use. i agree that people shouldn't feel pressured to use c++ libraries.
Matt Joiner
+23  A: 

My students, who learn cin and cout first, then learn printf later, overwhelmingly prefer printf (or more usually fprintf). I myself have found the printf model sufficiently readable that I have ported it to other programming languages. So has Olivier Danvy, who has even made it type-safe.

Provided you have a compiler that is capable of type-checking calls to printf, I see no reason not to use fprintf and friends in C++.

Disclaimer: I am a terrible C++ programmer.

Norman Ramsey
I use Java's `String.format` a lot. In C++, I use Boost.Format a lot, which is iostreams-friendly but also somewhat `printf`-compatible.
Chris Jester-Young
*printf's lack of type safety is mitigated but not eliminated by compilers that check those calls, since using variables as format strings is a perfectly valid use case. e.g: i18n. This function can blow up in so many ways, it's not even funny. I just don't use it any more. We have access to perfectly good formatters such as boost::format or Qt::arg.
rpg
@rpg: I think the tradeoff is between readability and type safety. I think it's reasonable for different applications to make different tradeoffs. Once you're into i18n, readability is already halfway out the window anyway, and I agree type safety trumps printf in that situation. Interestingly, the way `boost::format` works is somewhat similar to the way Olivier Danvy's ML code works.
Norman Ramsey
@Norman Ramsey: I see the `type safety problem` with `printf()` mentioned several times. *What exactly is the type safety problem with printf()?*
Lazer
@eSKay: According to the C standard, the types of arguments to `printf` are not checked. But many compilers, including gcc, check them in the common case that the first argument is a string literal.
Norman Ramsey
@Norman Ramsey: I am not sure what kind of problem can arise if the types are not checked. Can you please quote an example? I use `printf()` in C all the time. Never faced a problem.
Lazer
@eSKay: It's very rare to have an issue in practice. But try `char *fmt = "%s %s"; printf(fmt, "hello");` or `char *fmt = "%s"; printf(fmt, main);`.
Norman Ramsey
+3  A: 

I use printf because I hate the ugly <<cout<< syntax.

Igor Zevaka
what better reason is there? :P
Matt Joiner
+3  A: 

I often "drop back" to using printf(), but more often snprintf() for easier formatted output. When programming in C++ I use this wrapper I wrote a while back, called like this (to use your example as above): cout << format("(%d,%d)\n", x, y);

Here's the header (stdiomm.h):

#pragma once

#include <cstdarg>
#include <string>

template <typename T>
std::basic_string<T> format(T const *format, ...);

template <typename T>
std::basic_string<T> vformat(T const *format, va_list args);

And the source (stdiomm.cpp):

#include "stdiomm.h"
#include <boost/scoped_array.hpp>
#include <cstdio>

template <>
std::wstring vformat(wchar_t const *format, va_list arguments)
{
#if defined(_WIN32)
    int required(_vscwprintf(format, arguments));
    assert(required >= 0);
    boost::scoped_array<wchar_t> buffer(new wchar_t[required + 1]);
    int written(vswprintf(buffer.get(), required + 1, format, arguments));
    assert(written == required);
    return std::wstring(buffer.get(), written);
#else
#   error "No implementation yet"
#endif
}

template <>
std::string vformat(char const *format, va_list arguments)
{
#if defined(_WIN32)
    int required(_vscprintf(format, arguments));
    assert(required >= 0);
    boost::scoped_array<char> buffer(new char[required + 1]);
    int written(vsnprintf(buffer.get(), required + 1, format, arguments));
    assert(written == required);
    return std::string(buffer.get(), written);
#else
    char *buffer;
    int printed = vasprintf(&buffer, format, arguments);
    assert(printed != -1);
    std::string retval(buffer, printed);
    free(buffer);
    return retval;      
#endif
}

template <typename T>
std::basic_string<T> format(T const *format, ...)
{
    va_list ap;
    va_start(ap, format);
    std::basic_string<T> retval(vformat(format, ap));
    va_end(ap);
    return retval;
}

template std::wstring format(wchar_t const *format, ...);
template std::string format(char const *format, ...);

Update

After reading some of the other answers, I might have to make a switch to boost::format() myself!

Matt Joiner
The best of both worlds!
Bob Dylan
doesn't boost already have somehting like this?
Martin Beckett
+27  A: 

If you ever hope to i18n your program, stay away from iostreams. The problem is that it can be impossible to properly localize your strings if the sentence is composed of multiple fragments as is done with iostream.

Besides the issue of message fragments, you also have an issue of ordering. Consider a report that prints a student's name and their grade point average:

std::cout << name << " has a GPA of " << gpa << std::endl;

When you translate that to another language, the other language's grammar may need you to show the GPA before the name. AFAIK, iostreams has not way to reorder the interpolated values.

If you want the best of both worlds (type safety and being able to i18n), use Boost.Format.

R Samuel Klatchko
The ability to specify formatting parameters by position in boost::format() is great for localization.
Ferruccio
@Ferruccio - That can also be done by `printf()`.
Chris Lutz
But `boost::format` gives you such niceties as type safety. `printf` just blows up.
jalf
+2  A: 

Streams are the canonical way. Try making this code work with printf:

template <typename T>
void output(const T& pX)
{
    std::cout << pX << std::endl;
}

Good luck.

What I mean is, you can make operators to allow your types to be outputted to ostream's, and without hassle use it just like any other type. printf doesn't fit the the generality of C++, or more specifically templates.

There's more than usability. There's also consistency. In all my projects, I have cout (and cerr and clog) tee'd to also output to a file. If you use printf, you skip all of that. Additionally, consistency itself is a good thing; mixing cout and printf, while perfectly valid, is ugly.

If you have an object, and you want to make it output-able, the cleanest way to do this is overload operator<< for that class. How are you going to use printf then? You're going to end up with code jumbled with cout's and printf's.

If you really want formatting, use Boost.Format while maintaining the stream interface. Consistency and formatting.

GMan
Yeah I doubt this will work with a `printf` seeing as how templates didn't exist when `printf` was invented.
Bob Dylan
That's the point. This is C++ code we're talking about, isn't it? Am I being down voted for having a true point? Can the down voters implement my function with `printf`?
GMan
Your not being downvoted because you have a true point, your being downvoted because your point is irrelevant. We know `printf` can't do this, it's not designed to. It's like saying, "Oh I bet you can't make a class in C". That point would be true as well because the language isn't designed to.
Bob Dylan
It's hardly irrelevant. You're asking if you should use `printf`. For consistency, **no**. Streams will always work, `printf` will not always work. Code that isn't consistent is ugly. What if I have `cout` tee'd to also print to a log file? (And yes, all my projects do this!) Now you're just bypassing all that. There's more to think about than you saving keystrokes.
GMan
GMan, I see where you are coming from, but I think the point may be better expressed as 'there is some value in using a consistent output operation'. The OP says he uses both cout and printf, so ultimately the question is whether he should be using just one - as you demonstrate, probably cout - or if it's okay to mix them up. I would say that it's okay, and hope that anyone who can program with cout isn't going to be befuddled by printf(), but I can see how other people might disagree.
Tim Crone
Consider my usage above. And in programming anyway, consistency is *always* a good thing.
GMan
So you have to write an overloaded << operator for T, rather than a print(T) function.
Martin Beckett
Rather than a `print(T, S)` function, actually. S is the output stream. No need for that with `operator<<`; it works on any ostream interface.
GMan
"mixing `cout` and `printf`, while perfectly valid, is ugly" - the only ugly is the `x << y << z` madness!
bobobobo
__To printf__ an object, there's no problem with defining a member function `object.print( FILE* f )`. You can pass `stdout`, `stderr`, or an already open `FILE*` object to this function.
bobobobo
+15  A: 

Use boost::format. You get type safety, std::string support, printf like interface, ability to use cout, and lots of other good stuff. You won't go back.

janm
+4  A: 

Use printf. Do not use C++ streams. printf gives you much better control (such as float precision etc.). The code is also usually shorter and more readable.

Google C++ style guide agrees.

Do not use streams, except where required by a logging interface. Use printf-like routines instead.

There are various pros and cons to using streams, but in this case, as in many other cases, consistency trumps the debate. Do not use streams in your code.

Sherwood Hu
+1 for the link. It's no 10 Commandments, but they sure have their heads on straight.
ojrac
In my opinion while the Google C++ Style Guide is very good in many respects, the consistency trump they refer to is that of their own code. Remember that Google has been around for 10 years, and they value code consistency (a very good thing). The reason they aren't using printf is because people used it in previous incarnations of their code and they want to remain consistent. If this weren't the case I'm confident that they would be using streams instead.
Geoff
+5  A: 

On the whole I agree (hate the << syntax especially if you need complex formatting)

But I should point out the safety aspects.

printf("%x",2.0f)
printf("%x %x",2)
printf("%x",2,2)

Probably won't be noticed by the compiler but could crash your app.

Martin Beckett
`$ gcc -Wall -Werror printf.c` `cc1: warnings being treated as errors``printf.c: In function ‘main’:``printf.c:4: warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type ‘double’``printf.c:5: warning: too few arguments for format``printf.c:6: warning: too many arguments for format` Always compile with `-Wall -Werror`, and you shouldn't have this problem; if some warnings are spurious, you can disable those selectively.
Brian Campbell
Agreed here. It might seem annoying, but it's always a good idea to compile your code with as many restrictions from the compiler as possible. Enable all warnings, treat all warnings as if they were errors and, if possible, use electric fence + gdb as often as possible. But that's a general coding tip ;)
mingos
Interestingly xCode IDE detects these things you've mentioned here (in its intellisense.)
bobobobo
+3  A: 

Use whatever fits your needs and preferences. If you're comfortable with printf then by all means use it. If you're happier with iostreams stick to 'em. Mix and match as best fits your requirements. This is software, after all - there's better ways and worse ways, but seldom is there only ONE way.

Share and enjoy.

Bob Jarvis
+2  A: 

I do not like printf. Its lack of type-safety makes it dangerous to use, plus the need to remember format specifiers is a pain. The templated operators that smartly do the right thing are much better. So I always use the C++ streams in C++.

Granted, many people prefer printf, for other reasons, enumerated elsewhere.

Paul Nathan
A: 

I almost always use printf for temporary debugging statements. For more permanent code, I prefer the 'c' streams as they are The C++ Way. Although boost::format looks promising and might replace my stream usage (especially for complexly formatted output), probably nothing will replace printf for me for a long time.

aib
A: 

streams are preferred in cpp as they adhere to the object oriented paradigm of cpp, beside being type safe.

printf , on the other hand is more of a functional approach.

only reason for not using printf in cpp code that i can think of is not being object oriented.

its more of a personal choice.

ishan
A: 

cout stinks.

bobobobo