Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Common usage

As the Date extractor illustrated, you must be on guard for erroneous input. If the input produces an unexpected value, the process is skewed, and it s difficult to recover. In addition, formatted input defaults to white space delimiters. Consider what happens when we collect the code fragments from earlier in this chapter into a single program:

//: C04:Iosexamp.cpp {RunByHand}
// Iostream examples.
#include <iostream>
using namespace std;
 
int main() {
int i;
cin >> i;
 
float f;
cin >> f;
 
char c;
cin >> c;
 
char buf[100];
cin >> buf;
 
cout << "i = " << i << endl;
cout << "f = " << f << endl;
cout << "c = " << c << endl;
cout << "buf = " << buf << endl;
 
cout << flush;
cout << hex << "0x" << i << endl;
} ///:~
 

and give it the following input:

12 1.4 c this is a test
 

We expect the same output as if we gave it

12
1.4
c
this is a test
 

but the output is, somewhat unexpectedly

i = 12
f = 1.4
c = c
buf = this
0xc
 

Notice that buf got only the first word because the input routine looked for a space to delimit the input, which it saw after this. In addition, if the continuous input string is longer than the storage allocated for buf, we overrun the buffer.

In practice, you ll usually want to get input from interactive programs a line at a time as a sequence of characters, scan them, and then perform conversions once they re safely in a buffer. This way you don t need to worry about the input routine choking on unexpected data.

Another consideration is the whole concept of a command-line interface. This made sense in the past when the console was little more than a glass typewriter, but the world is rapidly changing to one where the graphical user interface (GUI) dominates. What is the meaning of console I/O in such a world? It makes much more sense to ignore cin altogether, other than for simple examples or tests, and take the following approaches:

1.      If your program requires input, read that input from a file you ll soon see that it s remarkably easy to use files with iostreams. Iostreams for files still works fine with a GUI.

2.      Read the input without attempting to convert it, as we just suggested. When the input is some place where it can t foul things up during conversion, you can safely scan it.

3.      Output is different. If you re using a GUI, cout doesn t necessarily work, and you must send it to a file (which is identical to sending it to cout) or use the GUI facilities for data display. Otherwise it often makes sense to send it to cout. In both cases, the output formatting functions of iostreams are highly useful.

Another common practice saves compile time on large projects. Consider, for example, how you would declare the Date stream operators introduced earlier in the chapter in a header file. You only need to include the prototypes for the functions, so it s not really necessary to include the entire <iostream> header in Date.h. The standard practice is to only declare classes, something like this:

class ostream;
 

This is an age-old technique for separating interface from implementation and is often called a forward declaration (and ostream at this point would be considered an incomplete type, since the class definition has not yet been seen by the compiler).

This will not work as is, however, for two reasons:

1.  The stream classes are defined in the std namespace.

2.  They are templates.

The proper declaration would be:

namespace std {
template<class charT, class traits = char_traits<charT> >
class basic_ostream;
typedef basic_ostream<char> ostream;
}
 

(As you can see, like the string class, the streams classes use the character traits classes mentioned in Chapter 3). Since it would be terribly tedious to type all that for every stream class you want to reference, the standard provides a header that does it for you: <iosfwd>. The Date header would then look something like this:

// Date.h
#include <iosfwd>
 
class Date {
friend std::ostream& operator<<(std::ostream&,
const Date&);
friend std::istream& operator>>(std::istream&, Date&);
// Etc.
 
Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire