printf vs cout/scanf vs cin

Could someone explain why cout and cin are considered more practical when programming in comparison to printf and scanf? I've heard of something such as overloading can be done easily with cout and cin, could somebody help with this?
Thanks
A few reasons why cout/cin are better:

-) typesafe
1
2
3
double foo = 5;
cout << foo;  // OK
printf("%d",foo);  // BAD, %d doesn't work for 'double' 


-) can be easily overloaded with simpler syntax
1
2
3
4
5
6
7
8
9
10
11
ofstream file("whatever.txt");
stringstream ss;

MyClass foo;
cout << foo; // works if you write a << operator for MyClass
file << foo;  // also works with same << operator
ss << foo;  // ditto

// doing the same in printf is more difficult, because there are 3 separate functions
//   printf, sprintf, and fprintf, each which has a different output.  I don't think there's a
// way to do all of them in one function like you can with ostream above 



A few reasons why printf are better:

-) shorter syntax (for those familiar with it):

1
2
3
4
printf("%08X", myvar);

//vs
cout << hex << setw(8) << setfill('0') << upper << myvar;


-) can be thread-safe.
printf/scanf family of function only works with the few data types they were designed for (essentially, the scalar types shared with C). The C++ I/O streams work with many more standard types, such as bitsets, RNGs, complex numbers, etc, and may also work with user-defined class types, if you provide the necessary overloads.
Last edited on
As ditsch said basically - printf / scanf can be a lot shorter, istreams / ostreams are more adaptable and overall more convenient otherwise.
> shorter syntax (for those familiar with it):

Almost as short:
1
2
3
4
5
6
7
8
#include <iostream>
#include <boost/format.hpp>

int main()
{
    std::cout << boost::format( "%08X %+12.5f %c" ) % 123 % 1.23 % '\n' ;
    // prints: 0000007B     +1.23000
}
-) can be thread-safe.

unless sync_with_stdio(false) was issued, cin and cout (and the rest of standard iostream objects) are thread-safe.
Last edited on
That requires boost though. Which is all fine and dandy if you're writing progs for yourself (or for a team that uses Boost), but sucks if you're working for a research team that kinda knows how to program, but put quick results over anything even if that leads into the godmother of all messes.
Cubbi wrote:
unless sync_with_stdio(false) was issued, cin and cout (and the rest of standard iostream objects) are thread-safe.


In the sense that they can be used from multiple threads: Yes.
In the sense that they can be used from multiple threads simultaneously without providing your own locking mechanism: No.

Due to the nature of how the << and >> operators work, printing and formatting things are done serially, not atomically.

Say you have 2 threads:

1
2
3
4
5
6
7
8
9
void thread1()
{
  cout << std::hex << 0xa << endl;
}

void thread2()
{
  cout << std::dec << 15 << endl;
}


If this code is run simultaneously, it could produce a myriad of different output. Possibiles are:

a
15
1015

f
a


etc


It is impossible for any implementation to print things in the order you'd expect when in a multithreaded environment, due to the nature of how the << operator works, and how the output stream effectively has to act like a state machine.

In contrast, it is entirely possible for an implementation for any single printf statement to print the entire block as specified, even when multithreading.
Last edited on
Of course, if you ever try to do any error checking on printf the potential thread safety benefits are lost.
@Telion: Can you elaborate on that? What do you mean by "error checking on printf"?


Also I just want to clarify -- I'm not trying to say printf is better. I just think both have their pros and cons.

I really like what iostream tried to do, but it just fails so hard in so many ways. The decision to overload >> and << the way they did was just a monstrosity. And don't even get me started on the difficulty/impossibility to derive from ostream.
Last edited on
> I just think both have their pros and cons.

They are not comparable to each other (unless input/output operations are not extensible to handle user defined types in the same way as primitive types). Their design goals are very different. In addition to an int there could be a user defined big_integer - should input/output of a big_integer be done in the same way as input/output of an int?


> And don't even get me started on the difficulty/impossibility to derive from ostream.

Deriving from ostream is almost always a terribly convoluted design idea anyway. Streams are much easier to customize by using composition rather than inheritance.

The key design concept is the separation of formatting from buffering and physical device input/output - the former is handled by facets and manipulators, the latter by classes derived from std::streambuf. Customize stream behaviour by customizing streambuf, and if needed adding user-defined facets and manipulators.
Also, when looking to do atomic stream operations, you should do all your formatting with a stringstream and then output directly to your target stream's buffer. Obnoxious, I know.
JLBorges wrote:
The key design concept is the separation of formatting from buffering and physical device input/output - the former is handled by facets and manipulators, the latter by classes derived from std::streambuf. Customize stream behaviour by customizing streambuf


It's also a design concept to make the stream buffer an implementation detail of the stream interface class, which means customized streambufs are, in practice, almost always accompanied by matching customized streams: the three standard streambufs come each with a different I/O stream type, boost::asio::basic_socket_streambuf comes with boost::ip::tcp::iostream, boost::iostreams::filtering_streambuf comes with boost::iostreams::filtering_stream, etc.

A counter-example is std::wbuffer_convert, which is a streambuf without a stream and it's annoying to have to go through the extra steps to do formatted I/O on it.

I don't quite understand what can be described as "difficult or impossible" about deriving from ostream, though.
Last edited on
JLBorges wrote:
Their design goals are very different. In addition to an int there could be a user defined big_integer - should input/output of a big_integer be done in the same way as input/output of an int?


I'm aware of that design goal, I agree that it's a good thing, and I'm glad that iostream accomplishes that much. But the way in which it accomplishes it is wretched, IMO.

The abuse of operator overloading, making the ostream have to operate like a state machine, and inconsistent memory of formatting flags is just a giant mess.

For example of the inconsistent memory thing...:

1
2
3
4
5
    int v = 10;

    cout << hex << setfill('0') << setw(3) << uppercase;
    cout << v << endl;
    cout << v << endl;


The output here is
00A
A


Why is it that hex and uppercase are remembered, but setfill and setw are not? This is a really big gotcha that has bitten me several times.


JLBorges wrote:
Deriving from ostream is almost always a terribly convoluted design idea anyway. Streams are much easier to customize by using composition rather than inheritance.


If you use composition and not inheritance, then your class will not work with the millions of lines of existing code that already use ostream.

The abstract concept of an ostream is very simple. It outputs a stream of bytes to something. The interface to derive from it should be equally simple. You should only have to implement a handful of basic, clear functions.

Something like this would make much more sense:

1
2
3
4
5
6
7
8
class ostream : blah blah
{
protected:
  // implement these to derive from ostream
  virtual size_t output(const char* buffer, size_t size) = 0;
  virtual size_t tell() = 0;
  virtual size_t seek() = 0;
};


Even a novice could write their own ostream with that kind of interface. And it could still be just as functional as the current ostream implementation.


JLBorges wrote:
The key design concept is the separation of formatting from buffering and physical device input/output - the former is handled by facets and manipulators, the latter by classes derived from std::streambuf. Customize stream behaviour by customizing streambuf, and if needed adding user-defined facets and manipulators.


I have made several attempts to write my own streambuf class, even using copy-pasted examples. None of my attempts have been successful. Maybe it's because the examples I was using only worked with gcc and I was trying to compile them in VC++.

Whatever the reason, the examples were overly convoluted, confusing, and (for whatever reason) didn't work.

Maybe the blame for them not working in this case belongs to one of the compilers STL implementation for not being standards compliant. But that doesn't really change my main point which is that it is extremely difficult to do something that is conceptually simple, which, to me, just screams out "design flaw".


Of course, this is all better than printf, where the possibility of making your own FILE type or output device is entirely nonexistent.


Cubbi wrote:
I don't quite understand what can be described as "difficult or impossible" about deriving from ostream, though.


Have you tried it? Were you successful?

If yes, I would love to see your code.
Last edited on
> It's also a design concept to make the stream buffer an implementation detail of the stream interface class,
> which means customized streambufs are, in practice, almost always accompanied by matching customized streams.

Agreed. The customized stream class is almost always just a very thin facade, though; the streambuf (for instance std::filebuf) is the one that does the heavy lifting.


> If you use composition and not inheritance, then your class will not work with the millions of lines of existing code that already use ostream.

Why? The composed stream is still a std::ostream
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <fstream>

int main()
{
    std::filebuf buf ;
    buf.open( "output_file_name", std::ios::out ) ;
    std::ostream stm( &buf ) ; // stm is a std::ostream, which writes to a file
    // we could have used a custom streambuf instead if a filebuf just as well
    stm << "output to file" << std::endl ;
}



> Something like this would make much more sense

Something like that (overridable protected virtual functions) is precisely what std::streambuf has.


> If yes, I would love to see your code.

An admittedly trivialized example - but perhaps sufficient to show that there is no black magic / specific library implementation dependency about deriving from std::streambuf or std::ostream.
http://www.cplusplus.com/forum/general/64174/#msg347154

(AFAIK, what you say is true of customizing the std::codecvt facet).

I don't quite understand what can be described as "difficult or impossible" about deriving from ostream, though.

Have you tried it? Were you successful?


As JLBorges already said in this thread, the "deriving from ostream" part is trivial in most cases. It's streabuf and codecvt where the data processing logic goes (and seeing as you mention writing a streambuf, I see now that's what you meant to talk about)

But to answer, I use boost.iostreams in production, so I don't have anything actually useful like my own teestream to show (boost already has that), but I found a small custom ostream lying around in my testing dir: put together to bring fstream conversion functionality to a stringstream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <locale>
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>

template<class Facet>
struct d_facet : Facet
{
    template<class ...Args>
    d_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
    ~d_facet() {}
};

class wconv_ostream : public std::wostream
{
    std::stringbuf buf;

    typedef d_facet<std::codecvt_byname<wchar_t, char, std::mbstate_t>> cfacet_t;
    std::wbuffer_convert<cfacet_t> cbuf;
 public:
    wconv_ostream(const std::string& loc_name)
                  : std::wostream(&cbuf),
                    buf(ios_base::out),
                    cbuf(&buf, new cfacet_t(loc_name))
    {
    }
    std::string str() const { return buf.str(); }
};

int main()
{
     wconv_ostream utf8("en_US.utf8");
     utf8 << L"z\u00df\u6c34" << std::endl;

     wconv_ostream gb18030("zh_CN.gb18030");
     gb18030 << L"z\u00df\u6c34" << std::endl;

     std::cout << std::hex << std::showbase;
     std::cout << "UTF8:\n";
     for(unsigned char c: utf8.str())
         std::cout << std::setw(2) << +c << ' ';
     std::cout << '\n';

     std::cout << "GB18030:\n";
     for(unsigned char c: gb18030.str())
         std::cout << std::setw(2) << +c << ' ';
     std::cout << '\n';
}
UTF8:
0x7a 0xc3 0x9f 0xe6 0xb0 0xb4 0xa 
GB18030:
0x7a 0x81 0x30 0x89 0x38 0xcb 0xae 0xa 


It could use the rest of stringstream's public interface, but even then it would remain trivial.
Thanks.

I will have to look at these examples when I get some free time.
Topic archived. No new replies allowed.