[Univ of Cambridge] [Dept of Engineering]
[Concepts] [Classes] [Predefined streams] [Input] [Output] [References] [Background Information]

C++ Input/Output

Concepts

Users want a high degree of control over formatting, but also want high performance and ease of use. Before we see how C++ attempts to reconsile these needs, let's consider I/O in more detail in an attempt to justify C++'s solution. True to form, C++ represents each distinct concept with a class, and tries to 'factor out' components that are needed in more than one class. Usually users don't have to worry too much about this (skip to the Input section now if you want), but some awareness of this structure will help you understand the online documentation and help you decide which include files to use.

Classes

The class hierarchy (inheritance tree) is as follows
                   ios_base
                     ios
                      /\
                     /  \
                    /    \
               istream   ostream
              /    |  \ /  |    \
             /     |   |   |     \
            /     /    |    \     \
           /     /     |     \     \
          /     /      |      \     \
   istring ifstream iostream ofstream ostring
   stream             /\               stream
                     /  \
               fstream  stringstream
so if the user used a ifstream to get input from a file, the istream (input) features, state information (in ios_base) and format/buffer control (via ios) would be available.

Predefined streams

The following streams are predefined:

Input

Initialisation

To input data you first need to create a stream and associate it with a file or string so that the stream knows where to get the characters from. Unless you're using cin (the standard input stream - usually the keyboard) you'll need to use the open command, or a constructor. You can provide extra arguments, but usually you just need to provide a filename. As a simple example consider the following, which reads then displays 3 numbers from a file.
#include <iostream>
#include <fstream>
using namespace std;
 
int main()
{
 int i;
 ifstream fin;
 fin.open("test"); // test contains 3 ints
 for (int j=0;j<3;j++)
 {
    fin  >> i;
    cout << i  << endl;
 }
 fin.close();
}
This program lacks error-checking - if the file doesn't exist, or if it contains less than 3 integers then the program won't work well. Even if the file's ok, it's rather dangerous to ever read from it before checking first. For instance, in the program above if you put the fin.close(); line inside the loop (at the end), the stream will be closed after the first number is read, but the program will still happily print erroneous values out for the last two numbers and won't complain. You can check for success by calling the stream's good() function.

To read a line of text (including spaces) into a string, use getline()

#include <string>
#include <fstream>
#include <iostream>
using namespace std;

int main()
{
  string s;
  ifstream fin;
  fin.open("/etc/passwd");
  while(getline(fin,s))
    cout << s << endl;  
}

The file will be opened at its start. If you don't want to access the contents sequentially, you can use seekg() to set the file-position indicator, and tellg() to tell you the current position. The following program prints the first and last characters of the file given to it as an argument. Note the use of ios::beg (beg is defined in ios) to show that you're offsetting from the beginning of the file.

#include <string>
#include <fstream>
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
 string fileName;
 bool flag=false;
  
 if (argc==2)
    fileName=argv[1];
 else {
    cerr << "Provide a single filename next time" << endl;
    return 1;
 }

 ifstream fin;
 fin.open(fileName.c_str());

 while(fin.good() == false)
 {
    cout << "Unable to open file. Enter a new name: ";
    cin >> fileName;
    fin.open(fileName.c_str());
 }

 istream ist=(fin.rdbuf());  

 ist.seekg(0,ios::beg);
 streampos pos=ist.tellg();
 cout << "Initial Position=" << pos << endl;
 char c;
 ist.get(c);
 cout << "Char=" << c<< endl;
 ist.seekg(-1,ios::end);
 pos=ist.tellg();
 cout << "Final Position=" << pos << endl;
 ist.get(c);
 cout <<  "Char=" << c <<endl;
 return 0;
}

Routines

As well as being able to use ">>" as usual on an open file there are also various forms of the get command (to read raw data) as well as getline to read a line of text with spaces. Other member functions include And remember to call the close() member function when you've finished with a file. Further information for local users is on the basic_istream page.

Manipulators

When, during output, you use "<< endl" you are using a manipulator. There are a few input manipulators too

Output

Initialisation

To output data you first need to create a stream and associate it with a file or string so that the stream knows where to deliver the characters. You can use a constructor or the open member function to open a file for writing.

Routines

Once the stream is in operation you can use "<<" as usual. So
 ...
 ofstream fout;
 fout.open("MyFilename");

 fout << "test";
should work. Other member functions include

Formatting

This requires C++ knowing how to convert values of various types into characters. C++ can deal with the standard types automatically, but even with these the user may wish to format the output. Formatting is controlled by flags in ios_base. These can be set using the member functions below or by using manipulators The setf function can be called to set flags, and the following manipulators are available Here's a short example
#include <iostream>
#include <iomanip> // to use the setprecision manipulator
using namespace std;

int main()
{
  cout << 1331 <<endl;
  cout << "In hex " << hex<< 1331 <<endl;

  cout << 1331.123456 <<endl;
  cout.setf(ios::scientific,ios::floatfield);
  cout <<1331.123456 <<endl;
  cout << setprecision(3) << 1331.123456 <<endl;
  cout << dec << 1331 <<endl;
  cout.fill('X');
  cout.width(8);
  cout << 1331 <<endl;
  cout.setf(ios::left,ios::adjustfield);
  cout.width(8);
  cout << 1331 <<endl;
  return 0;
}
Local users can read more details on the ios_base and basic_ios pages.

Strings

Once you can do I/O to and from files, I/O to and from strings is very similar, except that you don't need an "open()" call. The following example writes (i.e. converts) an integer into a string.
#include <sstream>
#include <string>
#include <iostream>
using namespace std;

int main()
{
  stringstream s;
  string t;
  int x = 10;
  s << x;
  s >> t;
  cout << "t=" << t << endl; 
  return 0;
}

Booleans

You can print out bools as numerical values or as words. The following should print out "1" then "true" (translated into your chosen language).
cout <<  true << endl;
cout <<  boolalpha;
cout <<  true;

References

CUED users can read the pages for

Background Information

The code above works with HP-UX's aCC compiler (version A.03.31).

Note that cerr << "x"; runs cerr.operator<<("x");. By further redefining the "<<" operator you can control the output format of user-defined types.


[1A C++ Frequently Asked Questions] [C++ FAQ LITE Frequently Asked Questions] [C++] [Help]

Updated in June 2002
tpl@eng.cam.ac.uk