FAQs in section [15]:
[15.1] Why should I use <iostream> instead of the
traditional <cstdio>? 
[Recently renamed "subclassable" to "inheritable" and revamped to use new-style headers (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Increase type safety, reduce errors, improve performance, allow extensibility,
and provide inheritability.
printf() is arguably not broken, and scanf() is perhaps livable despite
being error prone, however both are limited with respect to what C++ I/O can
do. C++ I/O (using << and >>) is, relative to C (using printf() and
scanf()):
- Better type safety: With <iostream>, the type of object
being I/O'd is known statically by the compiler. In contrast, <cstdio> uses
"%" fields to figure out the types dynamically.
- Less error prone: With <iostream>, there are no
redundant "%" tokens that have to be consistent with the actual objects
being I/O'd. Removing redundancy removes a class of errors.
- Extensible: The C++ <iostream> mechanism allows new
user-defined types to be I/O'd without breaking existing code. Imagine the
chaos if everyone was simultaneously adding new incompatible "%" fields
to printf() and scanf()?!).
- Inheritable: The C++ <iostream> mechanism is built from
real classes such as std::ostream and std::istream. Unlike <cstdio>'s
FILE*, these are real classes and hence inheritable. This means you
can have other user-defined things that look and act like streams, yet that do
whatever strange and wonderful things you want. You automatically get to use
the zillions of lines of I/O code written by users you don't even know, and
they don't need to know about your "extended stream" class.
[ Top | Bottom | Previous section | Next section ]
[15.2] Why does my program go into an infinite loop when
someone enters an invalid input character? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
For example, suppose you have the following code that reads integers from
std::cin:
#include <iostream>
int main()
{
std::cout << "Enter numbers separated by whitespace (use -1 to quit): ";
int i = 0;
while (i != -1) {
std::cin >> i; // BAD FORM See comments below
std::cout << "You entered " << i << '\n';
}
}
The problem with this code is that it lacks any checking to see if someone
entered an invalid input character. In particular, if someone enters
something that doesn't look like an integer (such as an 'x'), the stream std::cin
goes into a "failed state," and all subsequent input attempts return
immediately without doing anything. In other words, the program enters an
infinite loop; if 42 was the last number that was successfully read,
the program will print the message You entered 42 over and over.
An easy way to check for invalid input is to move the input request from the
body of the while loop into the control-expression of the while loop.
E.g.,
#include <iostream>
int main()
{
std::cout << "Enter a number, or -1 to quit: ";
int i = 0;
while (std::cin >> i) { // GOOD FORM
if (i == -1) break;
std::cout << "You entered " << i << '\n';
}
}
This will cause the while loop to exit either when you hit end-of-file, or when
you enter a bad integer, or when you enter -1.
(Naturally you can eliminate the break by changing the while loop
expression from while (std::cin >> i) to
while ((std::cin >> i) && (i != -1)), but that's not
really the point of this FAQ since this FAQ has to do with iostreams rather
than generic structured programming guidelines.)
[ Top | Bottom | Previous section | Next section ]
[15.3] How does that funky while (std::cin >> foo) syntax
work? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
See the previous FAQ for an example of the
"funky while (std::cin >> foo) syntax."
The expression (std::cin >> foo) calls the appropriate operator>>
(for example, it calls the operator>> that takes an std::istream on
the left and, if foo is of type int, an int& on the right). The
std::istream operator>> functions return their left argument by
convention, which in this case means it will return std::cin. Next the compiler
notices that the returned std::istream is in a boolean context, so it
converts that std::istream into a boolean.
To convert an std::istream into a boolean, the compiler calls a member
function called std::istream::operator void*(). This returns a
void* pointer, which is in turn converted to a boolean (NULL
becomes false, any other pointer becomes true). So in this
case the compiler generates a call to std::cin.operator void*(), just as if
you had casted it explicitly such as (void*) std::cin.
The operator void*() cast operator returns some non-NULL
pointer if the stream is in a good state, or NULL if it's in a failed
state. For example, if you read one too many times (e.g., if you're already at
end-of-file), or if the actual info on the input stream isn't valid for the
type of foo (e.g., if foo is an int and the data is an 'x'
character), the stream will go into a failed state and the cast operator will
return NULL.
The reason operator>> doesn't simply return a bool (or void*) indicating
whether it succeeded or failed is to support the "cascading" syntax:
std::cin >> foo >> bar;
The operator>> is left-associative, which means the above is parsed as:
(std::cin >> foo) >> bar;
In other words, if we replace operator>> with a normal function name such as
readFrom(), this becomes the expression:
readFrom( readFrom(std::cin, foo), bar);
As always, we begin evaluating at the innermost expression. Because of the
left-associativity of operator>>, this happens to be the left-most
expression, std::cin >> foo. This expression returns std::cin (more precisely,
it returns a reference to its left-hand argument) to the next expression. The
next expression also returns (a reference to) std::cin, but this second reference
is ignored since it's the outermost expression in this "expression statement."
[ Top | Bottom | Previous section | Next section ]
[15.4] Why does my input seem to process past the end of file? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Because the eof state may not get set until after a read is attempted past the
end of file. That is, reading the last byte from a file might not set the eof
state. E.g., suppose the input stream is mapped to a keyboard in that case
it's not even theoretically possible for the C++ library to predict whether or
not the character that the user just typed will be the last character.
For example, the following code might have an off-by-one error with the count
i:
int i = 0;
while (! std::cin.eof()) { // WRONG! (not reliable)
std::cin >> x;
++i;
// Work with x ...
}
What you really need is:
int i = 0;
while (std::cin >> x) { // RIGHT! (reliable)
++i;
// Work with x ...
}
[ Top | Bottom | Previous section | Next section ]
[15.5] Why is my program ignoring my input request
after the first iteration? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Because the numerical extractor leaves non-digits behind in the input buffer.
If your code looks like this:
char name[1000];
int age;
for (;;) {
std::cout << "Name: ";
std::cin >> name;
std::cout << "Age: ";
std::cin >> age;
}
What you really want is:
for (;;) {
std::cout << "Name: ";
std::cin >> name;
std::cout << "Age: ";
std::cin >> age;
std::cin.ignore(INT_MAX, '\n');
}
Of course you might want to change the for (;;) statement to while (std::cin), but don't confuse that with skipping the non-numeric
characters at the end of the loop via the line: std::cin.ignore(...);.
[ Top | Bottom | Previous section | Next section ]
[15.6] How can I provide printing for my class Fred? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Use operator overloading to provide a
friend left-shift operator, operator<<.
#include <iostream>
class Fred {
public:
friend std::ostream& operator<< (std::ostream& o, const Fred& fred);
// ...
private:
int i_; // Just for illustration
};
std::ostream& operator<< (std::ostream& o, const Fred& fred)
{
return o << fred.i_;
}
int main()
{
Fred f;
std::cout << "My Fred object: " << f << "\n";
}
We use a non-member function (a friend in this case)
since the Fred object is the right-hand operand of the << operator.
If the Fred object was supposed to be on the left hand side of the <<
(that is, myFred << std::cout rather than std::cout << myFred), we could
have used a member function named operator<<.
Note that operator<< returns the stream. This is so the output operations
can be cascaded.
[ Top | Bottom | Previous section | Next section ]
[15.7] But shouldn't I always use a printOn()
method rather than a friend function? 
[Recently created (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
No.
The usual reason people want to always use a printOn() method rather
than a friend function is because they wrongly believe that friends violate
encapsulation and/or that friends are evil. These beliefs are naive and
wrong: when used properly, friends can actually
enhance encapsulation.
This is not to say that the printOn() method approach is never
useful. For example, it is useful when providing
printing for an entire hierarchy of classes. But if you use a
printOn() method, it should normally be protected, not public.
For completeness, here is "the printOn() method approach." The idea is to
have a member function (often called printOn() that does the actual
printing, then have operator<< call that printOn() method. When it
is done wrongly, the printOn() method is public so
operator<< doesn't have to be a friend it can be a simple
top-level function that is neither a friend nor a member of the class.
Here's some sample code:
#include <iostream>
class Fred {
public:
void printOn(std::ostream& o) const;
// ...
};
// operator<< can be declared as a non-friend [NOT recommended!]
std::ostream& operator<< (std::ostream& o, const Fred& fred);
// The actual printing is done inside the printOn() method [NOT recommended!]
void Fred::printOn(std::ostream& o) const
{
// ...
}
// operator<< calls printOn() [NOT recommended!]
std::ostream& operator<< (std::ostream& o, const Fred& fred)
{
fred.printOn(o);
return o;
}
People wrongly assume that this reduces maintenance cost "since it avoids
having a friend function." This is a wrong assumption because:
- The member-called-by-top-level-function approach has
zero benefit in terms of maintenance cost. Let's say it takes
N lines of code to do the actual printing. In the case of a friend
function, those N lines of code will have direct access to the class's
private/protected parts, which means whenever someone changes the class's
private/protected parts, those N lines of code will need to be
scanned and possibly modified, which increases the maintenance cost. However
using the printOn() method doesn't change this at all: we still have
N lines of code that have direct access to the class's
private/protected parts. Thus moving the code from a friend function
into a member function does not reduce the maintenance cost at
all. Zero reduction. No benefit in maintenance cost. (If anything it's
a bit worse with the printOn() method since you now have more lines
of code to maintain since you have an extra function that you didn't have
before.)
- The member-called-by-top-level-function approach makes the
class harder to use, particularly by programmers who are not also class
designers. The approach exposes a public method that programmers are
not supposed to call. When a programmer reads the public methods of the
class, they'll see two ways to do the same thing. The documentation would
need to say something like, "This does exactly the same as that, but don't use
this; instead use that." And the average programmer will say, "Huh? Why make
the method public if I'm not supposed to use it?" In reality the only
reason the printOn() method is not public is to avoid granting friendship
status to operator<<, and that is a notion that is somewhere between subtle
and incomprehensible to a programmer who simply wants to use the
class.
Net: the member-called-by-top-level-function approach has a cost but no
benefit. Therefore it is, in general, a bad idea.
Note: if the printOn() method is protected or private, the second
objection doesn't apply. There are cases when that approach is reasonable,
such as when providing printing for an entire
hierarchy of classes. Note also that when the printOn() method is
non-public, operator<< needs to be a friend.
[ Top | Bottom | Previous section | Next section ]
[15.8] How can I provide input for my class Fred? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Use operator overloading to provide a
friend right-shift operator, operator>>. This is
similar to the output operator, except the
parameter doesn't have a const: "Fred&"
rather than "const Fred&".
#include <iostream>
class Fred {
public:
friend std::istream& operator>> (std::istream& i, Fred& fred);
// ...
private:
int i_; // Just for illustration
};
std::istream& operator>> (std::istream& i, Fred& fred)
{
return i >> fred.i_;
}
int main()
{
Fred f;
std::cout << "Enter a Fred object: ";
std::cin >> f;
// ...
}
Note that operator>> returns the stream. This is so the input operations can
be cascaded and/or used in a while loop or if
statement.
[ Top | Bottom | Previous section | Next section ]
[15.9] How can I provide printing for an entire hierarchy of
classes? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Provide a friend operator<<
that calls a protected virtual function:
class Base {
public:
friend std::ostream& operator<< (std::ostream& o, const Base& b);
// ...
protected:
virtual void printOn(std::ostream& o) const;
};
inline std::ostream& operator<< (std::ostream& o, const Base& b)
{
b.printOn(o);
return o;
}
class Derived : public Base {
protected:
virtual void printOn(std::ostream& o) const;
};
The end result is that operator<< acts as if it was dynamically
bound, even though it's a friend function. This is
called the Virtual Friend Function Idiom.
Note that derived classes override printOn(std::ostream&) const. In
particular, they do not provide their own operator<<.
Naturally if Base is an ABC,
Base::printOn(std::ostream&) const can be declared
pure virtual using the "= 0" syntax.
[ Top | Bottom | Previous section | Next section ]
[15.10] How can I "reopen" std::cin and std::cout in binary
mode under DOS and/or OS/2? 
[Recently changed so it uses new-style headers and the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
This is implementation dependent. Check with your compiler's documentation.
For example, suppose you want to do binary I/O using std::cin and std::cout. Suppose
further that your operating system (such as DOS or OS/2) insists on translating
"\r\n" into "\n" on input from std::cin, and "\n" to
"\r\n" on output to std::cout or std::cerr.
Unfortunately there is no standard way to cause std::cin, std::cout, and/or std::cerr to
be opened in binary mode. Closing the streams and attempting to reopen them in
binary mode might have unexpected or undesirable results.
On systems where it makes a difference, the implementation might provide a way
to make them binary streams, but you would have to check the manuals to find
out.
[ Top | Bottom | Previous section | Next section ]
[15.11] Why can't I open a file in a different directory
such as "..\test.dat"? 
[Recently changed so it uses new-style headers and uses the std:: syntax (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
Because "\t" is a tab character.
You should use forward slashes in your filenames, even on an operating system
that uses backslashes such as DOS, Windows, OS/2, etc. For example:
#include <iostream>
#include <fstream>
int main()
{
#if 1
std::ifstream file("../test.dat"); // RIGHT!
#else
std::ifstream file("..\test.dat"); // WRONG!
#endif
// ...
}
Remember, the backslash ("\") is used in string literals to create
special characters: "\n" is a newline, "\b" is a backspace, and
"\t" is a tab, "\a" is an "alert", "\v" is a
vertical-tab, etc. Therefore the file name
"\version\next\alpha\beta\test.dat" is interpreted as a bunch of very
funny characters; use "/version/next/alpha/beta/test.dat" instead, even
on systems that use a "\" as the directory separator such as DOS,
Windows, OS/2, etc. This is because the library routines on these operating
systems handle "/" and "\" interchangeably.
[ Top | Bottom | Previous section | Next section ]
[15.12] How do I convert a value (a number, for example) to
a std::string? 
[Recently created thanks to Rob Stewart (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
There are two easy ways to do this: you can use the <stdio> facilities or
the <iostream> library. In general, you should
prefer the <iostream> library.
The <iostream> library allows you to convert pretty much anything to a
std::string using the following syntax (the example converts a double, but
you could substitute pretty much anything that prints using the <<
operator):
#include <iostream>
#include <sstream>
#include <string>
std::string convertToString(double x)
{
std::ostringstream o;
if (o << x)
return o.str();
// some sort of error handling goes here...
return "conversion error";
}
The std::ostringstream object o offers formatting facilities just like
those for std::cout. You can use manipulators and format flags to control
the formatting of the result, just as you can for other std::cout.
In this example, we insert x into o via the overloaded insertion
operator, <<. This invokes the iostream formatting facilities to convert
x into a std::string. The if test makes
sure the conversion works correctly it should always succeed for built-in
types, but the if test is good style.
The expression os.str() returns the std::string that contains
whatever has been inserted into stream o, in this case the string value of
x.
[ Top | Bottom | Previous section | Next section ]
[15.13] How do I convert a std::string to a number? 
[Recently created thanks to Rob Stewart (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]
There are two easy ways to do this: you can use the <stdio> facilities or
the <iostream> library. In general, you should
prefer the <iostream> library.
The <iostream> library allows you to convert a std::string to pretty much
anything using the following syntax (the example converts a double, but you
could substitute pretty much anything that can be read using the >>
operator):
#include <iostream>
#include <sstream>
#include <string>
double convertFromString(const std::string& s)
{
std::istringstream i(s);
double x;
if (i >> x)
return x;
// some sort of error handling goes here...
return 0.0;
}
The std::istringstream object i offers formatting facilities just like
those for std::cin. You can use manipulators and format flags to control
the formatting of the result, just as you can for other std::cin.
In this example, we initialize the std::istringstream i passing the
std::string s (for example, s might be the string "123.456"),
then we extract i into x via the overloaded extraction operator,
>>. This invokes the iostream formatting facilities to convert as much of
the string as possible/appropriate based on the type of x.
The if test makes sure the conversion works
correctly. For example, if the string contains characters that are
inappropriate for the type of x, the if test will fail.
[ Top | Bottom | Previous section | Next section ]
E-mail the author
[ C++ FAQ Lite
| Table of contents
| Subject index
| About the author
| ©
| Download your own copy ]
Revised Jul 10, 2000
|