JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Studio 12.3: C++ User's Guide     Oracle Solaris Studio 12.3 Information Library
search filter icon
search icon

Document Information

Preface

Part I C++ Compiler

1.  The C++ Compiler

2.  Using the C++ Compiler

3.  Using the C++ Compiler Options

Part II Writing C++ Programs

4.  Language Extensions

5.  Program Organization

6.  Creating and Using Templates

7.  Compiling Templates

8.  Exception Handling

9.  Improving Program Performance

10.  Building Multithreaded Programs

Part III Libraries

11.  Using Libraries

12.  Using the C++ Standard Library

13.  Using the Classic iostream Library

13.1 Predefined iostreams

13.2 Basic Structure of iostream Interaction

13.3 Using the Classic iostream Library

13.3.1 Output Using iostream

13.3.1.1 Defining Your Own Insertion Operator

13.3.1.2 Handling Output Errors

13.3.1.3 Flushing

13.3.1.4 Binary Output

13.3.2 Input Using iostream

13.3.3 Defining Your Own Extraction Operators

13.3.4 Using the char* Extractor

13.3.5 Reading Any Single Character

13.3.6 Binary Input

13.3.7 Peeking at Input

13.3.8 Extracting Whitespace

13.3.9 Handling Input Errors

13.3.10 Using iostreams With stdio

13.4 Creating iostreams

13.4.1 Dealing With Files Using Class fstream

13.4.1.1 Open Mode

13.4.1.2 Declaring an fstream Without Specifying a File

13.4.1.3 Opening and Closing Files

13.4.1.4 Opening a File Using a File Descriptor

13.4.1.5 Repositioning Within a File

13.5 Assignment of iostreams

13.6 Format Control

13.7 Manipulators

13.7.1 Using Plain Manipulators

13.7.2 Parameterized Manipulators

13.8 strstream: iostreams for Arrays

13.9 stdiobuf: iostreams for stdio Files

13.10 Working Withstreambuf Streams

13.10.1 streambuf Pointer Types

13.10.2 Using streambuf Objects

13.11 iostream Man Pages

13.12 iostream Terminology

14.  Building Libraries

Part IV Appendixes

A.  C++ Compiler Options

B.  Pragmas

Glossary

Index

13.3 Using the Classic iostream Library

To use routines from the classic iostream library, you must include the header files for the part of the library you need. The header files are described in the following table.

Table 13-1 iostream Routine Header Files

Header File
Description
iostream.h
Declares basic features of iostream library.
fstream.h
Declares iostreams and streambufs specialized to files. Includes iostream.h.
strstream.h
Declares iostreams and streambufs specialized to character arrays. Includes iostream.h.
iomanip.h
Declares manipulators: values you insert into or extract from iostreams to have different effects. Includes iostream.h.
stdiostream.h
(obsolete) Declares iostreams and streambufs specialized to use stdio FILEs.Includes iostream.h.
stream.h
(obsolete) Includes iostream.h, fstream.h, iomanip.h, and stdiostream.h. For compatibility with older style streams from C++ version 1.2.

You usually do not need all of these header files in your program. Include only the ones that contain the declarations you need. By default, libiostream contains the classic iostream library.

13.3.1 Output Using iostream

Output using iostream usually relies on the overloaded left-shift operator (<<) which, in the context of iostream, is called the insertion operator. To output a value to standard output, you insert the value in the predefined output stream cout. For example, given a value someValue, you send it to standard output with a statement like:

cout << someValue;

The insertion operator is overloaded for all built-in types, and the value represented by someValue is converted to its proper output representation. If, for example, someValue is a float value, the << operator converts the value to the proper sequence of digits with a decimal point. Where it inserts float values on the output stream, << is called the float inserter. In general, given a type X, << is called the X inserter. The format of output and how you can control it is discussed in the ios(3CC4) man page.

The iostream library does not support user-defined types. If you define types that you want to output in your own way, you must define an inserter (that is, overload the << operator) to handle them correctly.

The << operator can be applied repetitively. To insert two values on cout, you can use a statement like the one in the following example:

cout << someValue << anotherValue;

The output from the above example will show no space between the two values. So you may want to write the code this way:

cout << someValue << " " << anotherValue;

The << operator has the precedence of the left shift operator (its built-in meaning). As with other operators, you can always use parentheses to specify the order of action. When necessary, use parentheses to avoid problems of precedence. Of the following four statements, the first two are equivalent, but the last two are not.

cout << a+b;              // + has higher precedence than <<
cout << (a+b);
cout << (a&y);            // << has precedence higher than &
cout << a&y;            // probably an error: (cout << a) & y

13.3.1.1 Defining Your Own Insertion Operator

The following example defines a string class:

#include <stdlib.h>
#include <iostream.h>


class string {
private:
    char* data;
    size_t size;

public:
    // (functions not relevant here)

    friend ostream& operator<<(ostream&, const string&);
    friend istream& operator>>(istream&, string&);
};

The insertion and extraction operators must in this case be defined as friends because the data part of the string class is private.

ostream& operator<< (ostream& ostr, const string& output)
{    return ostr << output.data;}

The following example shows the definition of operator<< overloaded for use with strings.

cout << string1 << string2;

operator<< takes ostream& (that is, a reference to an ostream) as its first argument and returns the same ostream, making it possible to combine insertions in one statement.

13.3.1.2 Handling Output Errors

Generally, you don’t have to check for errors when you overload operator<< because the iostream library is arranged to propagate errors.

When an error occurs, the iostream where it occurred enters an error state. Bits in the iostream’s state are set according to the general category of the error. The inserters defined in iostream ignore attempts to insert data into any stream that is in an error state, so such attempts do not change the iostream’s state.

In general, the recommended way to handle errors is to periodically check the state of the output stream in some central place. If an error exists, you should handle it in some way. This chapter assumes that you define a function error, which takes a string and aborts the program. error is not a predefined function. See 13.3.9 Handling Input Errors for an example of an error function. You can examine the state of an iostream with the operator !,which returns a nonzero value if the iostream is in an error state. For example:

if (!cout) error("output error");

There is another way to test for errors. The ios class defines operator void *(), so it returns a NULL pointer when an error occurs. You can use a statement like the following example:

if (cout << x) return; // return if successful

You can also use the function good, a member of ios:

if (cout.good()) return; // return if successful

The error bits are declared in the enum:

enum io_state {goodbit=0, eofbit=1, failbit=2,
badbit=4, hardfail=0x80};

For details on the error functions, see the iostream man pages.

13.3.1.3 Flushing

As with most I/O libraries, iostream often accumulates output and sends it on in larger and generally more efficient chunks. If you want to flush the buffer, insert the special value flush. For example:

cout << "This needs to get out immediately." << flush;
 

flush is an example of a kind of object known as a manipulator, which is a value that can be inserted into an iostream to have some effect other than causing output of its value. These values are really functions that take an ostream& or istream& argument and return its argument after performing some actions on it (see 13.7 Manipulators).

13.3.1.4 Binary Output

To obtain output in the raw binary form of a value, use the member function write as shown in the following example. This example shows the output in the raw binary form of x.

cout.write((char*)&x, sizeof(x));

The previous example violates type discipline by converting &x to char*. Doing so is normally harmless but if the type of x is a class with pointers or virtual member functions, or one that requires nontrivial constructor actions, the value written by the above example cannot be read back in properly.

13.3.2 Input Using iostream

Input using iostream is similar to output. You use the extraction operator >> and can string together extractions the way you can with insertions. For example:

cin >> a >> b;

This statement gets two values from standard input. As with other overloaded operators, the extractors used depend on the types of a and b. Two different extractors are used if a and b have different types. The format of input and how you can control it is discussed in some detail in the ios(3CC4) man page. In general, leading whitespace characters (spaces, newlines, tabs, form-feeds, and so on) are ignored.

13.3.3 Defining Your Own Extraction Operators

When you want input for a new type, you overload the extraction operator for it, just as you overload the insertion operator for output.

Class string defines its extraction operator in the following code example:

Example 13-1 string Extraction Operator

istream& operator>> (istream& istr, string& input)
{
    const int maxline = 256;
    char holder[maxline];
    istr.get(holder, maxline, ”\n’);
    input = holder;
    return istr;
}

The get function reads characters from the input stream istr and stores them in holder until maxline-1 characters have been read, a new line is encountered, or EOF, whichever happens first. The data in holder is then null-terminated. Finally, the characters in holder are copied into the target string.

By convention, an extractor converts characters from its first argument (in this case, istream& istr), stores them in its second argument, which is always a reference, and returns its first argument. The second argument must be a reference because an extractor is meant to store the input value in its second argument.

13.3.4 Using the char* Extractor

Be careful when using this predefined extractor, which can cause problems. Use this extractor as follows:

char x[50];
cin >> x;

This extractor skips leading whitespace, extracts characters, and copies them to x until it reaches another whitespace character. It then completes the string with a terminating null (0) character.Use this extractor carefully because input can overflow the given array.

You must also be sure the pointer points to allocated storage. The following example shows a common error:

char * p; // not initialized
cin >> p;

Because the location where the input data will be stored is unclear, your program might abort.

13.3.5 Reading Any Single Character

In addition to using the char extractor, you can get a single character with either form of the get member function. For example:

char c;
cin.get(c); // leaves c unchanged if input fails

int b;
b = cin.get(); // sets b to EOF if input fails

Note - Unlike the other extractors, the char extractor does not skip leading whitespace.


The following example shows a way to skip only blanks, stopping on a tab, newline, or any other character:

int a;
do {
    a = cin.get();
   }
while(a ==’ ’);

13.3.6 Binary Input

If you need to read binary values (such as those written with the member function write), you can use the read member function. The following example shows how to input the raw binary form of x using the read member function, and is the inverse of the earlier example that uses write.

cin.read((char*)&x, sizeof(x));

13.3.7 Peeking at Input

You can use the peek member function to look at the next character in the stream without extracting it. For example:

if (cin.peek()!= c) return 0;

13.3.8 Extracting Whitespace

By default, the iostream extractors skip leading whitespace. The following example turns off whitespace skipping from cin, then turns it back on:

cin.unsetf(ios::skipws); // turn off whitespace skipping
...
cin.setf(ios::skipws); // turn it on again

You can use the iostream manipulator ws to remove leading whitespace from the iostream regardless of whether skipping is enabled. The following example shows how to remove the leading whitespace from iostream istr:

istr >> ws;

13.3.9 Handling Input Errors

By convention, an extractor whose first argument has a nonzero error state should not extract anything from the input stream and should not clear any error bits. An extractor that fails should set at least one error bit.

As with output errors, you should check the error state periodically and take some action, such as aborting, when you find a nonzero state. The ! operator tests the error state of an iostream. For example, the following code produces an input error if you type alphabetic characters for input:

#include <stdlib.h>
#include <iostream.h>
void error (const char* message) {
     cerr << message << "\n";
     exit(1);
}
int main() {
     cout << "Enter some characters: ";
     int bad;
     cin >> bad;
     if (!cin) error("aborted due to input error");
     cout << "If you see this, not an error." << "\n";
     return 0;
}

Class ios has member functions that you can use for error handling. See the man pages for details.

13.3.10 Using iostreams With stdio

You can use stdio with C++ programs, but problems can occur when you mix iostreams and stdio in the same standard stream within a program. For example, if you write to both stdout and cout, independent buffering occurs and produces unexpected results. The problem is worse if you input from both stdin and cin because independent buffering could render the input unusable.

To eliminate this problem with standard input, standard output, and standard error, use the following instruction before performing any input or output. It connects all the predefined iostreams with the corresponding predefined stdio FILEs.

ios::sync_with_stdio();

This type of a connection is not the default because a significant performance penalty occurs when the predefined streams are made unbuffered as part of the connection. You can use both stdio and iostreams in the same program applied to different files, that is, you can write to stdout using stdio routines and write to other files attached to iostreams. You can open stdio FILEs for input and also read from cin so long as you don’t also try to read from stdin.