17

I've been looking through a lot of code made by others lately and happened to notice everyone uses "printf" style C functions a lot, but the C++ functions learned in school (cout, specifically) don't seem so popular.

Is this a valid observation, and is there a reason for this? Convention?

Thanks,

R

James McNellis
  • 348,265
  • 75
  • 913
  • 977
Russel
  • 3,609
  • 8
  • 33
  • 32

6 Answers6

24

Personally, I use printf over the iostream stuff (like cout) because I think it's clearer.

When you do formatting with iostream, you have to << all sorts of weirdness like setiosflags and setf. I can never remember which namespace all this stuff lives in, let alone what it all does. Even when I do, I'm disappointed with how verbose and unintuitive the code looks.

The formatting options with printf may seem illegible at first, but they're concise, clearly documented in a single manual page, and common to a wide range of languages.

Another advanage is that printf is stateless: Unlike with cout, I don't need to remember which member functions have been called on printf, or which byzantine concoction of flags has been <<'ed into it. This is a big plus for readability.

Diogenes Creosote
  • 1,922
  • 2
  • 17
  • 22
  • 11
    +1 for pointing out the state-vs-stateless distinction. it's really a nice thing when you don't have to worry whether your attempts to output data will step on one-another. – JustJeff Aug 29 '10 at 01:37
  • 6
    One thing to point out as well is that you can use printf-style flags with C++ strings using `boost::format` – bdonlan Aug 29 '10 at 01:38
6

I think taste is one possible reason. Personally I find this:

printf("%8d: %s\n", customer->id, customer->name);

more readable than this:

std::cout << customer->id << ": " << customer->name << std::endl;

There's also the issue with localization. printf makes it possible to change the formatting to suit other languages and UI cultures, which becomes a major chore with iostreams, unless you use something like the Boost Format library.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Mhmmd
  • 1,483
  • 9
  • 15
  • Weird answer. Support of locales is actually one point where iostreams are significantly better than printf *and* not really harder to use. – Martin Ba Dec 04 '13 at 22:33
4

There are several criticisms of the standard stream system -- most notably that it usually is not as performant as C's system, and that they don't allow reordering of the items to be formatted, which can make localization more difficult.

Personally, I use streams for most everything, because they allow me to have a function write to a console, a file, or a string, without having to modify the function.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 4
    You can use streams with printf-style format specifiers with `boost::format`, you know :) – bdonlan Aug 29 '10 at 01:39
  • 2
    Passing a `FILE*` as a parameter would be just as easy as passing a `ostream` parameter. Allowing `fprintf` to write to a console, or a file. – gwell Aug 29 '10 at 02:17
  • 2
    @gwell: Last I checked, I cannot make a FILE* write to a memory buffer. – Billy ONeal Aug 29 '10 at 02:23
  • 1
    @Billy ONeal, look again, these things exist! – Matt Joiner Aug 29 '10 at 03:52
  • The GNU library supports `fmemopen()`. It is not a standard, but it can exist. See http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_11.html#SEC166 – gwell Aug 29 '10 at 05:10
  • With streams you can for example write a derivate of `std::ostream` which automatically compresses the data, or an `std::istream` which acts as an SSL decrypter. This is simply more powerful than passing a `FILE*` – Tomaka17 Aug 29 '10 at 10:04
  • @Gwell: But that requires you to know the size of the output ahead of time. That's (generally speaking) unrealistic. – Billy ONeal Aug 29 '10 at 14:34
2

Where I work, we use printf-style formatting. This is because we used to make heavy use of the MFC CString class and its printf-style Format method. We've been phasing out MFC, but haven't changed our string-formatting approach.

As for which one is designed better, see Who architected / designed C++'s IOStreams, and would it still be considered well-designed by today's standards?

Community
  • 1
  • 1
dan04
  • 87,747
  • 23
  • 163
  • 198
0

The printf and scanf family functions have two major problems: type safety and memory safety. It's fairly easy to make a mismatch between the specification string and the variable length argument list that follows. Also, buffer overruns through scanf are a classic security vulnerability. In short, don't use them.

The C++ streams offer type and memory safety, and also formatting extensibility. They're much more powerful and generally easier to use than printf and scanf.

Also, as suggested by ShaderOp, Boost's format library provides the same safety, but makes the old C programmers feel more comfortable.

smithco
  • 679
  • 5
  • 17
  • 1
    C++ is low enough level that you can always shoot yourself in the foot, even with streams and "type safety" - for instance, `cout << *(int *)&foo;` On the flip side, any decent C compiler will issue warnings for `printf` format string type mismatches, so I don't think 'safety' is a valid argument for one over the other. On the other hand, C++ streams have at least 2 major disadvantages over `printf` (especially `printf` with XSI localization extensions): ease of translating messages for localization purposes, and statelessness (potentially a big issue with threads). – R.. GitHub STOP HELPING ICE Aug 29 '10 at 02:14
  • The compiler can only verify your format string if it knows what your format string is. But one of the advantages `printf` has over iostreams is that you can set up the format string at run time. So type safety certainly seems like a valid argument to me. – Dennis Zickefoose Aug 29 '10 at 02:21
  • 3
    @R any decent C++ compiler will catch the C-style cast and issue a warning as well – Sam Miller Aug 29 '10 at 02:37
  • 1
    @Dennis: Anyone constructing formatting strings at runtime (with the exception of loading an internationalized version) needs to be shot (for security flaws if nothing else). – Billy ONeal Aug 29 '10 at 02:42
  • @Billy: Loading an internationalized version is precisely what I was talking about. The compiler can't help you there. – Dennis Zickefoose Aug 29 '10 at 04:07
  • @Dennis: GCC can handle that with the format_arg attribute. This attribute means that the function (such as gettext()) modifies a format string in such a way that it takes the same parameters. Furthermore, the gettext tools can check if translated format strings still use the same parameters. – jilles Aug 29 '10 at 11:11
  • @Dennis: you'd better have some validation process to check that the internationalized version matches the original version :) – Matthieu M. Aug 29 '10 at 11:38
  • @jilles: So `printf` is typesafe if you use a specific non-standard library, with its associated pre-processing steps, and your compiler supports specific non-standard extensions? That's not a particularly compelling argument. Don't get me wrong, I prefer C IO to C++ IO for lots of things, and localization is one of them. – Dennis Zickefoose Aug 29 '10 at 14:23
0

I'm going to guess printf is more widely used because

  • it was in use for quite a few years before C++ compilers and streams showed up
  • C is used more than C++
  • lots of I/O was done for things like the Windows API, for which printf is a natural fit amongst Open/Read/Write/Close/etc
joe snyder
  • 3,629
  • 2
  • 21
  • 13