[LC++]IO in C++

Carlo Wood carlo at alinoe.com
Fri Nov 2 01:07:48 UTC 2001


On Thu, Nov 01, 2001 at 02:42:47PM +1030, Mark Phillips wrote:
> Hi,
> 
> Suppose I have an integer and I wish to convert it to a 
> string.  I can do:
> 
> int myInt=259;
> char myCstr[20];
> sprintf(myCstr, "%d", myInt);

Or

int myInt=259;
ostringstream oss;
oss << myInt;

(use oss.str())

> Or suppose I have a string and I wish to convert it to an
> int.  I can do:
> 
> int myInt;
> string myString="259";
> istringstream iss(myString);
> iss>>myInt;
> 
> But both of these seem a bit inelegant.  Are there better
> ways of doing this kind of thing.

What is inelegant about it?

> The other thing is, I have heard it said that cout is bad for
> doing output formatting, and that printf should be used, even
> in C++.  Do people agree?

Absolutely not.  You should use solely cout/cerr and never
printf.  People who say you should use printf are only looking
at the syntax/layout and like printf better because it looks
better (which is only because they are used to it).

If you write a *simple* program that only does very simple
output, then there is no big disadvantage in using printf.
However - when you write a Object Oriented program then you
will need to output objects rather than only builtin-types.
Then you will appreciate the advantage of using ostreams.

Another advantage of using ostreams appart from that they are
type-safe and extendable is they result in faster code: by
using the overload mechanism of C++, you use compile time
to decide which function to call instead of doing that at
runtime.  A printf("The ammount is: %d\n", a);  needs to
_decode_ the format string at runtime and then call a function
that can convert an integer to a string.  While the code

std::cout << "The ammount is: " << a << '\n';

calls the three different needed functions _directly_.

> What alternatives are there for dealing with IO in C++?  There
> seems to be no sensible and flexible framework.  Am I wrong?

I think you are wrong.  The most powerful reason to use
ostreams is that you treat them just like that: abstract
output streams.  You can pass them around.

Consider this code:

template<class T>
  class Foo {
    T M_t;
  public:
    Foo(T const& t) : M_t(t) {
      Dout(dc::notice,
          "You are calling "
	  << type_info_of<Foo<T> >().demangled_name()
	  << '(' << t << ");");
    }
  };

where I use the debug output macro "Dout" of libcwd
(http://libcw.sourceforge.net/debugging/)

libcwd allows you to set an ostream somewhere
(with  Debug(libcw_do.set_ostream(&std::cout)); )

So the above code could be writing to cout, or cerr, or
a file (or both), or to syslog - or to a pipe that is
send buffered over a socket to a remote site - or to
another program that is filtering it before logging
it and displaying it partly in a window on another 
monitor.  Moreover, this same code could be writing
directly to the ostream or to a temporal stringstream
because it needed buffering (depending on the history
of previous debug output (`continued' debug output)).

-- 
Carlo Wood <carlo at alinoe.com>



More information about the tuxCPProgramming mailing list