http://cpp.gantep.edu.tr
C++ resources. Faculty of Engineering, University of Gaziantep
 MAIN  -  Tutorials  -  Howtos  -  nmPrimer  -  Misc  -  Links  -  Contacts
C++ Tutorial (Basic)
[index][<][1][2][3][4][5][6][7][8][9][.]

9. Formatted I/O and File Processing

Last modified: Tue, 07 Dec 2010 14:31:19 +0200

Complete: ##################-- (90%)

9.1 Introduction
9.2 Overview of Streams in C++
9.3 Formatted Input/Output
9.4 Input/Output with Files
9.5 Examples
9.6 Exercises

9.1 Introduction

Until now, we have used cout to write data to the screen and cin to read data from the keyboard without specifying any format. This section deals with formatted input/output (formatted I/O); this allows the programmer to specify how numbers/characters are displayed or read. In this section we will also look at how to read from and write to files (file I/O).

In this section, we will learn

  • an overview of streams
  • how to manage a formatted I/O using the <iomanip> library
  • how to write to and read from files using streams

9.2 Overview of Streams in C++

In C++, as part of the language, no statements are defined for writing to a screen (or to a file) and for reading data into a program. However, C++ includes some libraries to facilitate I/O. These libraries contain some classes called stream (which is an abstraction that represents a device on which input and output operations are performed).

The iostream classes view the flow of data from your program to the screen or a file. The class cout is a stream of output stream ostream. The reason cout is called a stream is that output sent to it flows like a stream of bytes. If things are sent to cout, they fall in line, one after to the other are dropped into the stream. Then they are displayed on the screen in that order. (The name cout, pronounced see-out, stands for console output).

Input is analogous to output. The class cin is a stream of input stream istream. In this case, we have data flowing in from the input stream. (The name cin, pronounced see-in, stands for console input).

One principal goal of streams is to encapsulate the problems of getting the data to and from the external storage (e.g. a hard-drive) or the screen. Once a stream is created, your program works with the stream and the stream hides the details. Hence, a stream can basically be represented as a source or destination of characters of indefinite length. Figure 9.1 illustrates this fundamental idea.
See also: http://www.cplusplus.com/reference/.


Fig 9.1: Encapsulation through streams

The standard C++ library provides the following classes to perform I/O operations:

  • iostream: Stream class to facilitate basic I/O. It contains istream and ostream.
  • ofstream: Stream class to output to files
  • ifstream: Stream class to input from files
  •  fstream: Stream class to both read and write from/to files.

9.3 Formatted Input/Output

Generating cleanly formatted output is a common programming requirement. Formatting improves your user interface and makes it easier to read any debugging messages that you might output to the screen. In C++, the I/O formatting can be performed by either manipulators or using the methods of I/O classes and format-state flags (a detailed overview can be found here). We will use manipulators in these notes.

A manipulator is a function that can alter the characteristics of the output (and input) stream. For cout, we have seen the endl manipulator which ends a line (and calls the flush function of the ostream).

Using cout to Format Output
The following manipulators, defined in the header file <iomanip>, are the most commonly used for formatting output.

  • setw(n) : sets the minimum width of the next output. The length of the width is n.
  • setfill(c) : fills leading spaces in a number with a given character c.

  • setprecision(n) : sets the maximum number of digits (given by n) that are displayed for a number.
  • fixed : allows inserting floating-point values in fixed format
  • scientific : allows inserting floating-point values in scientific format

  • left : left-justify
  • right : right-justify

  • dec : insert or extract integer values in decimal format
  • oct : insert or extract values in octal (base 8) format
  • hex : insert or extract integer values in hexadecimal (base 16) format
For example, the following program section
  int   i = 1299;
  float f = 314.15926;
  cout << "numbers:" << setw(10) << i << f << "four" << endl;
will output
         1         2         3
12345678901234567890123456789012345
numbers:      1299314.159four
The first two lines are not part of the output, they are just for gauging the output. After outputting "numbers:", setw(10) creates a 10-column empty field and then the number 1299 is placed in this field right-justified. This is followed by "314.159four". Note that 314.15926 is output as "314.159" because of the default format of the compiler.

For the following assignment of variables

  int    i = 1453;
  float  f = 314.15926;
  string s = "University of Gaziantep";
example program sections and the corresponding outputs are given below:

Program section Output (first lines are not shown)
 cout << setw(30) << s << endl;          // default
 cout << setw(30) << left << s << endl;  // left-justified
 cout << setw(30) << right << s << endl; // right-justified
12345678901234567890123456789012345
       University of Gaziantep
University of Gaziantep
       University of Gaziantep
 cout << setw(10) << setfill('0') << i << endl;
12345678901234567890123456789012345
0000001453
 cout << setw(10) << i << endl;
 cout << setw(10) << left << i << endl;
 cout << setw(10) << right << i << endl;
12345678901234567890123456789012345
      1453
1453
      1453
 cout << setw(10) << dec << i << endl; // decimal (default)
 cout << setw(10) << oct << i << endl; // octal (base 8)
 cout << setw(10) << hex << i << endl; // hexadecimal (base 16)
12345678901234567890123456789012345
      1453
      2655
       5ad
 cout << setw(15) << fixed << setprecision(4) << f << endl;
 cout << setw(15) << fixed << setprecision(2) << f << endl;
12345678901234567890123456789012345
       314.1593
         314.16
 cout << setw(15) << scientific << setprecision(3) << f << endl; 
12345678901234567890123456789012345
      3.142e+02

Here an example programming application is given below. The program outputs the sine and cosine values of angles from 0o to 180o in steps of 10o.

09prg01.cpp: A formatted trigonometric table
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
// A formatted trigonometric table
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
  cout << setprecision(5) << fixed;

  for(int deg=0; deg<=180; deg+=10)
  {
    double x = M_PI*deg/180.;
    cout << setw(3)  << deg
         << setw(10) << sin(x)
         << setw(10) << cos(x) << endl;
  }

 return 0;
}
  0   0.00000   1.00000
 10   0.17365   0.98481
 20   0.34202   0.93969
 30   0.50000   0.86603
 40   0.64279   0.76604
 50   0.76604   0.64279
 60   0.86603   0.50000
 70   0.93969   0.34202
 80   0.98481   0.17365
 90   1.00000   0.00000
100   0.98481  -0.17365
110   0.93969  -0.34202
120   0.86603  -0.50000
130   0.76604  -0.64279
140   0.64279  -0.76604
150   0.50000  -0.86603
160   0.34202  -0.93969
170   0.17365  -0.98481
180   0.00000  -1.00000

Using cin to Format Input
cin, being responsible for input, is a class defined in <iostream>. The extraction operator (>>) is used to put data into your program's variables. For example, the following operation

  int var;
  cin >> var;
writes data from the buffer of cin to your local variable, var.

cin has some member functions to manipulate input data. The famous one is get() that is used to get a single character, including a white space, or a string for input. For example, the following program section

  char a, b, c;
  cout << "Enter three letters: ";
  cin.get(a).get(b).get(c);
  cout << a << " " <<  b << " " << c;
will output
  Enter three letters: one
  o n e
Here is the another usage
  char str1[256], str2[256];

  cout << "Enter string one: ";
  cin.get(str1, 256);
  cout << "string one: " << str1 << endl;

  cout << "Enter string two: ";
  cin >> str2;
  cout << "string two: " << str2 << endl;
an example I/O is
  Enter string one: Now is the time
  string one: Now is the time
  Enter string two: Now is the time
  string two: Now
In the second input str2 is assigned a string from a space-delimited input so only the first word is stored.

Note that the getline() function can be used to input a whole line into a string:

  string s;
  cout << "Input your message: ";
  getline(cin, s);

9.4 Input/Output with Files

Reading from and writing to files is performed using data streams. The ifstream class is used for reading (inputting) data from a file, and the ofstream class is used for writing (outputting) data to a file. These two class require the fstream to be included in the program. There are several methods associated with ifstream and ofstream. The most useful are given in the following table.

Method (function) Description
open(filename, mode) filename is the name (and path) of the file to open.
mode is an optional parameter and can have the following flags:
ios::in - open for input operations (default for ifstream)
ios::out - open for output operations (default for ofstream)
ios::binary - open in binary mode (default is text mode)
ios::ate - set the initial position at the end of the file (default is the beginning of the file)
ios::app - append the content to the current content of the file
ios::trunc - delete the previous content and replaced the new one
is_open() Returns true if a file is successfully opened.
eof() Returns true if a file open (for reading) has reached the end.
close() Closes the file.

File Output

As an example, the following line opens the file student.txt for an output operation.

  ofstream myFile;
  myFile.open("student.txt", ios::out);
As ios::out is the default behaviour for ofstream, this is equivalent to:
  ofstream myFile;
  myFile.open("student.txt");
A combination of flags can also be used.
  ofstream f1, f2;
  f1.open("student1.txt", ios::out | ios::app); // output or  append
  f2.open("student2.txt", ios::out & ios::app); // output and append
Data input/output from a file can be performed in the same way as for cin/cout. Here we will give some examples.

The following program writes two lines of strings to the file example.txt.

09prg02.cpp: Writing data to a text file
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
// Writing data to a text file
#include <iostream>
#include <fstream>
using namespace std;

int main ()
{
  ofstream myFile("example.txt");

  // check if the file is open
  if (myFile.is_open())
  {
    myFile << "This is first line.\n";
    myFile << "This is second line.\n";
    myFile.close();
  }
  else
    cout << "Unable to open file example.txt";

  return 0;
}
[in the file example.txt]
This is first line.
This is second line.

cout manipulators can also work with file I/O. The program given below, writes sine and cosine values of the angles given in Program 9.1 to the file trigo.data instead of the screen.

09prg03.cpp: Writing trigonometric data to a text file
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
// Writing trigonometric data to a text file
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;

int main ()
{
  const float PI=3.1415926;

  string filename = "trigo.data";
  ofstream myFile(filename.c_str());

  if (myFile.is_open())
  {
      cout << "Writing data to the file: " << filename << endl;
      myFile << setprecision(5) << fixed;

      for(int deg=0; deg<=180; deg+=10)
      {
         float x = PI*deg/180.;
         myFile << setw(3)  << deg
                << setw(10) << sin(x)
                << setw(10) << cos(x) << endl;
      }
      myFile.close();
  }
  else
    cout << "Unable to open file " << filename;

  return 0;
}
[on the screen]
Writing data to the file: trigo.data

[in the file trigo.data]
  0   0.00000   1.00000
 10   0.17365   0.98481
 20   0.34202   0.93969
 30   0.50000   0.86603
 40   0.64279   0.76604
 50   0.76604   0.64279
 60   0.86603   0.50000
 70   0.93969   0.34202
 80   0.98481   0.17365
 90   1.00000   0.00000
100   0.98481  -0.17365
110   0.93969  -0.34202
120   0.86603  -0.50000
130   0.76604  -0.64279
140   0.64279  -0.76604
150   0.50000  -0.86603
160   0.34202  -0.93969
170   0.17365  -0.98481
180   0.00000  -1.00000

Note that at line 13 the c_str() method must be appended to the string filename.

File Input

The following example program provides a basic method for inputting data from a file mydata.txt.

09prg04.cpp: Reading data from a file
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
// Reading data from a file
#include <iostream>
#include <fstream>
using namespace std;

int main () {

  ifstream fin("mydata.txt");
  double x, sum=0.0;

  for (int i=0; i<10; i++) {
    fin >> x;
    sum = sum + x;
  }

  fin.close();

  cout << "The sum of all values in mydata.txt is " << sum << endl;

}
The sum of all values in mydata.txt is 59.2

Note that the program assumes that there are exactly ten values in the file. If there are more or less values in the file then the sum will not be correct (probably without warning!).

We can expand on the above basic statements adding more useful features. For example, it is important to check that the file has been opened successfully, this can be done with the is_open() function. Also the eof() function can be used to check if the end of the file has been reach.

Consider a file kelvin.tmp that contains 100 lines of temperature values. The following program reads data from the file and outputs the mean temperature to the screen.
Note that the file name is stored in a string, and the is_open() function is used to check if the file was opened succesfully.

09prg05.cpp: Reading data from a file with a check for is_open()
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
// Reading data from a file with a check for is_open()
#include <iostream>
#include <fstream>
using namespace std;

int main ()
{
  string filename = "kelvin.tmp";
  ifstream kelvin(filename.c_str());
  double k;

  if (kelvin.is_open())
  {
      double s;
      int i;

      cout << "Reading data from file: " << filename << endl;
      for(s = 0.0, i=0; i<100; i++, s += k )
         kelvin >> k;
      kelvin.close();

      double mean = s/100.0;

      cout << "mean of the data = " << mean << endl;
  }
  else
    cout << "Unable to open file " << filename;

  return 0;
}
Reading data from file: kelvin.tmp
mean of the data = 412.652

Below 09prg05.cpp is modified such that it reads temperatures in Kelvin (K) from the file kelvin.tmp, converts them to degrees celsius (C) according to K = C + 273.15 and writes degrees celsius values to an another file degrees.tmp. However, in this case we assume that we do not know how many lines of data the file kelvin.tmp contains.

09prg06.cpp: Reading an unknown number of lines of data from a file
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 51:
 52:
// Reading an unknown number of lines of data from a file
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

int main ()
{
  string source = "kelvin.tmp";   // source file
  string target = "degrees.tmp";  // target file

  ifstream kelvin(source.c_str());
  ofstream degrees(target.c_str());

  // Check if files can be opened
  if ( ! kelvin.is_open() ) {
    cout << "Unable to open file " << source << endl;
    return 1; // stop the execuation of the program
  }
  if ( ! degrees.is_open() ) {
    cout << "Unable to open file " << target << endl;
    return 1;
  }

  double s = 0.0, mean, k, c;
  int n = 0;

  cout << "Reading data from file: " << source << endl;
  cout << "Writing data to file: "   << target << endl;

  // Start an infinte loop
  while(1)
  {
      kelvin >> k;                // Read a line from source file
      if( kelvin.eof() ) break;   // Do you reach end of file?
      c = k + 273.15;             // Convert
      degrees << setw(8) << fixed // Write to the target file
              << setprecision(2)
              << c << endl;
      s += k;                     // Sum the temperatures
      n++;                        // Count number of lines
  }                               // Goto next line in the file

  kelvin.close();                 // Close the files
  degrees.close();

  mean = s/n;
  cout << "number of data   = " << n << endl;
  cout << "mean of the data = " << mean << endl;

  return 0;
}
Reading data from file: kelvin.tmp
Writing data to file: degrees.tmp
number of data   = 100
mean of the data = 412.652

Notes:
- lines 16 and 20: the symbol "!" is the logical NOT operator.
- lines 18 and 22: an integer 1 is returned to the operating system indicating that an error occured.
- line 34 attempts to read data, then line 35 breaks out of the read loop if the EOF condition is true.

9.5 Examples

[NEEDS EXAMPLES]

9.6 Exercises

  1. What is a stream?
  2. Why is cout called a stream?
  3. What is a manipulator?
  4. What does the ios::ate argument do?
  5. What does the method eof() do?

  6. Modify 09prg05.cpp such that it also outputs the minimum and maximium values of the temperatures recorded in the file kelvin.tmp.

  7. Write a program that outputs to a file called numbers.dat the integer numbers 1 to 100 and their square-roots. The output should be formatted as illustrated below.
    1234567890
      1  1.000
      2  1.414
      3  1.732
      .      .
      .      .
      .      .
    100 10.000
    

  8. The file gravity.dat contains the following measured values for the acceleration due to gravity. Write a program to input the data into an array and output the mean value to the screen.
    9.81
    9.79
    9.83
    9.79
    9.90
    9.82
    9.84
    9.78
    9.85
    

  9. The file student.dat contains the names and corresponding exam scores of 20 students in a class (the data is given below). Write a program which reads the data from the file and calculates and outputs a) the mean score of the class excluding zeros and b) the name and score of the students getting the maximum and minimum score.
    UGUR      67
    KADIR     72
    SEMIH	  00
    GOZDE     73
    FIRAT     30
    EDA       51
    FULYA     41
    GULISTAN  67
    EMRE      30
    AHMET     76
    ISMAIL    67
    MELIKE    71
    TANER     59
    SEHER     79
    ALI       90
    EMIN	  88
    HAVVA     76
    FERDA     00
    MUKRIME   54
    TUGBA	  61
    

  10. What is the output of the following program?
    #include <iostream>
    #include <cmath>
    #include <iomanip>
    using namespace std;
    
    int main()
    {
      int i = 1;
      while(i<=10)
        cout << setw(4) << i++ << fixed
             << setw(6) << setprecision(2) << log(i)
             << setw(6) << setprecision(2) << log10(i) << endl;
      return 0;
    }
    

  11. What is the output of the following program?
    // Program to show that the maximum power delivered to the 
    // load resistance R occurs when the load resistance
    // matches the internal resistance r (namely R = r)
    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    int main()
    {
      double R=0.0, r = 1.0e+3, Rmax = 5.0e+3;
    
      cout << scientific << setprecision(1);
    
      do{
        double power = 100.0* R/(R+r)/(R+r);
        cout << setw(9) << r << setw(9) << R
             << setw(9) << power << endl;
        R += 500;
    
      }while(R <= Rmax);
    
      return 0;
    }
    
[index][<][1][2][3][4][5][6][7][8][9][.]
please send us you comments/questions/corrections