5

Why do we use printf() & scanf() functions in c++?

unwind
  • 391,730
  • 64
  • 469
  • 606
ankit
  • 877
  • 3
  • 9
  • 14

9 Answers9

16

I think some programmers find them easier or more accessible than the stream-based ones that are more common in C++.

Also, when doing complicated string formatting, the C way of using a formatting string can be perceived as being more concise and readable. I'm not arguing that it is, I'm just saying that in some cases some people might think it is, and thus chose to use printf().

unwind
  • 391,730
  • 64
  • 469
  • 606
14

I've read various debates about the virtues and vices of <stdio.h> versus <iostream>. But to me, this issue is settled beyond a reasonable doubt. Except for trivial testing purposes, never, ever use stdio.h in C++.

If that sounds too extreme to you, consider that stdio.h is the cause of major security holes in C programs. Passing an "unsanitized" format string to an Xprintf function is just about as dangerous as executing an unsanitized SQL query from an untrusted client.

Suppose someone passes you the following string:

"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"

...and your program naively passes this string to printf.

What do you think is going to happen? In that example, you'll probably be lucky and your program will just crash. But a skilled hacker can use the %n format specifier to write to an arbitrary memory address, such as the return address on the stack, enabling him/her to execute injected shellcode.

C++ IOstreams, however, do not have any of these problems, because the format arguments are not interpreted at runtime, but are evaluated at compile-time. So despite the extra verbosity of C++ iostreams, you should always prefer them over printf in production code.

Charles Salvia
  • 52,325
  • 13
  • 128
  • 140
  • 6
    Disagree with "always". There are plenty of cases where the verbosity of iostreams buys you nothing, and merely obfuscates your code. You've given one example where this isn't the case, it doesn't mean that it must apply to all cases! – Oliver Charlesworth Nov 02 '10 at 11:17
  • 2
    +1 for security concerns and example – Viktor Sehr Nov 02 '10 at 11:22
  • 6
    I think that passing unsanitized user input to ANY function is dangerous, and that's a different thing than using any and all functions. – Michael Foukarakis Nov 02 '10 at 11:42
  • 1
    Your point about security is both good and sad. Sad because of the sucky way the internet/web was built, riddled with holes for scoundrels. – Mike Dunlavey Nov 02 '10 at 12:20
  • In 99.9999% of real-world cases the format string is a compile-time constant, and in popular compilers like g++ the arguments are type-checked in that case. In terms of risk it's closer to eating dinner than crossing the road. – Porculus Nov 02 '10 at 23:13
  • 1
    @Porculus: so 99.9999% of real-world cases don't need localization? ;) – jalf Nov 02 '10 at 23:16
  • yes, i agree. c++ iostreams, while being unreadable messes when doing complex formatting, have the advantage that an ignorant developer who knows nothing about what he's is doing is less likely to cause a core dump. – Erik Aronesty Nov 21 '14 at 16:00
7

Because it is a better way to format strings than streams, in my opinion. I can using C-like formatting functions to do string formatting with things like precision in floating point variables well and with much less code.

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43
Svisstack
  • 16,203
  • 6
  • 66
  • 100
  • 1
    Why? (As it stands, your answers is pretty worthless. If you don't explain *how* it is better, how does it help the OP?) – jalf Nov 02 '10 at 12:06
6

I'm not sure what the question is here.

By default, one should probably use <iostream> functionality (std::cin, etc.).

There is an argument, however, that using printf for formatted output instead of std::cout leads to less-verbose code (because you control it all through a single format string, rather than chains of stream modifiers. Of course, printf is much less type-safe, and not object-oriented in any way (in contrast to iostreams, where one can overload operator<< and operator>> on user-defined types to encapsulate many aspects of formatted output).

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 4
    "OO" is not the same as "good", though you can of course write good OO code. +1 for good points otherwise. –  Nov 02 '10 at 11:14
  • @Roger: I guess I didn't really mean OO. I was referring to the ability to overload `operator<<` on user-defined types. Will clarify my answer... – Oliver Charlesworth Nov 02 '10 at 11:18
4

It's fast and concise. We use it for our logging statements quite happily.

(We also supports ostream-style, but usually printf wins the day there...)

Macke
  • 24,812
  • 7
  • 82
  • 118
4

I don't use printf. I usually use cout, and then I cry myself to sleep afterwards.

Seriously, both options suck. printf has a nice syntax, but throws away type safety, extensibility and safety. And cout is lousy for i18n, and it's verbose and painful to use.

boost::format is a pretty decent compromise between the two. If you have the option, use that instead.

jalf
  • 243,077
  • 51
  • 345
  • 550
2

One important reason is speed. But the most important reason is just a habit. The main advantage of streams is that they are inheritable, so they go with OO paradigm much better.

Klark
  • 8,162
  • 3
  • 37
  • 61
  • Though I disagree with the premise that printf is faster, worth noting that ["Of the 136 pages we tested on the site over the past 90 days, 17 page(s) resulted in malicious software being downloaded and installed without user consent."](http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=http://programming-designs.com/2009/02/c-speed-test-part-2-printf-vs-cout/&client=googlechrome&hl=en-US). –  Nov 02 '10 at 11:25
  • And is that a [comment bug?](http://meta.stackexchange.com/questions/69215/urls-in-urls-parsed-incorrectly-in-comments) http://safebrowsing.clients.google.com/safebrowsing/diagnostic?site=http://programming-designs.com/2009/02/c-speed-test-part-2-printf-vs-cout/&client=googlechrome&hl=en-US –  Nov 02 '10 at 11:31
  • Hm, I don't know why it is reported as attack site. In opera it opens normally, but I see that warning in the FF. Ok, I'll remove the link. – Klark Nov 02 '10 at 11:37
  • 1
    C streams are not faster than C++ IO streams. This is just a common misconception based on the fact that by default, C++ syncs its streams with the C streams (and *this* in turn is slow) but it can be disabled by setting `ios_base::sync_with_stdio`. – Konrad Rudolph Nov 02 '10 at 11:47
  • 1
    @Konrad: in my (limited) testing, C streams have turned out to be faster with or without that option. That might have been an anomaly though, and I've never bothered to test it thoroughly. Got a link to some proper benchmarks of this? – jalf Nov 02 '10 at 11:54
  • With GCC 4.3.2, my limited testing shows that iostreams are actually faster. But I haven't tested this extensively on other platforms. Certainly, I/O streams have a lot of overhead (sentry objects, checking internal state, etc.), but in theory this should be offset by the fact that unlike `printf`, an `iostream` object doesn't need to actually *parse* a format string at runtime - it simply calls precompiled code to output each argument. – Charles Salvia Nov 02 '10 at 12:15
  • @jalf Nothing authoritative but there are two benchmarks here: http://stackoverflow.com/questions/896654/ and one here: http://stackoverflow.com/questions/2872543/printf-vs-cout-in-c which find that they are (almost) equally fast. The [FastFormat](http://www.fastformat.org/performance.html) benchmark finds other results, however (comparing `snprintf` with `stringstream`). – Konrad Rudolph Nov 02 '10 at 12:25
0

The C++ way of handling IO is using IO-streams.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • 4
    These functions are also C++. –  Nov 02 '10 at 11:08
  • 1
    @Roger: As far as I understand it they are only in there to provide backwards compatibility, so they should not be used in C++ code. If that is wrong please correct me. – Björn Pollex Nov 02 '10 at 11:09
  • @Space: That's not true. It is true that is deprecated, but that's only because of the namespace issue; it's why is provided. –  Nov 02 '10 at 11:13
  • @Roger: Then why are people keep on saying (at least that is my perception) that we should not use these function in C++? (not being rhetoric here, I really don't understand). – Björn Pollex Nov 02 '10 at 11:14
  • 1
    @Space: Misunderstanding and popular repetition. Each has advantages; use the right tool for the job at hand. –  Nov 02 '10 at 11:17
  • 1
    @Roger: I don’t think C++ provided a largely redundant library (`iostream`) just for giggles. Officially, C++ doesn’t deprecate *any* old C headers but they are only included in C++ to preserve backwards compatibility. You should **not** use `printf` and consorts. If not for any other reason, then simply because they aren’t extensible and cannot be used meaningfully with custom objects. Use the C++ IO streams or, if you don’t like their interface (who does?), use Boost.Format. – Konrad Rudolph Nov 02 '10 at 11:43
  • @Konrad: All the C headers, including , are officially deprecated in the standard, but included for backwards compatibility. How can a new header, , be *created* for backwards compatibility — such a claim just doesn't make sense. –  Nov 02 '10 at 11:45
  • @Roger: well, they sure didn't reinvent `printf` just because it's an awesome function. They included it because C had it, and nothing else. So in a sense, it is just backwards compatibility. But more in the "C had it, it was popular, some people are going to hate us if we don't have it to" kind of sense than the strict "we should be able to compile C code unmodified" sense. – jalf Nov 02 '10 at 11:57
  • 1
    @Roger: I think it makes sense. It’s a much more affordable upgrade path to change one include, and add a `using namespace` directive, instead of rewriting every usage of a library to conform to a different interface. I’m not arguing whether they are officially deprecated (they’re not), I’m arguing whether their usage should be endorsed (it shouldn’t, and if it were, this would leave C++ with two completely incompatible IO libraries on equal footing; which is ludicrous, given the otherwise very lean standard library). – Konrad Rudolph Nov 02 '10 at 11:57
  • 1
    @Konrad: You mean ludicrous like strstream and stringstream? or valarray? or vector? Of the many problems with the current stdlib, having two IO libraries is rather minor. The real reason we have iostreams now is we didn't have variadic templates at the time. –  Nov 02 '10 at 12:14
  • @Roger: I mean ludicrous like `iostream` and `stdio`. `strstream` is deprecated and `vector` may be a premature optimization but still makes a lot of since in many cases (and other languages handle it the same, they just don’t have the problem of iterators). Designing two IO libraries is not something that I accept being called “minor”. – Konrad Rudolph Nov 02 '10 at 12:29
0

You should use iostreams, because printf/scanf are non-extendable. You can't add a new format specifier to printf or scanf. You can, however, extract any type T that has a suitable operator from an iostream. In addition, the fact that the types are known at compile-time is a legion of safety far ahead of what printf and scanf can offer.

Puppy
  • 144,682
  • 38
  • 256
  • 465