Topics to Cover

Shortcut: Initializing variables in the declaration

Up 'til now, we've usually made delcaring a variable and initializing that variable (i.e. giving the variable it's initial value in the program) separate steps. However, in C++ you may give a variable it's initial value at the same time you declare it by simply putting "= value" or (value) after the variable's name in the declaration.

For example, the following code declares variables x and y and gives an inital value of 1.0 and 200 to them respectively.


double x = 1.0, y(200);
 

Including the Necessary Library

To work with files in C++, we need to include the fstream library:

#include <fstream>
This library provides two important types:

Writing To a file

Opening an Output File

To open a file for writing, declare an ofstream variable and pass the filename as a string:

ofstream fout("out.txt");           

Writing to a file

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

int main()
{
  // Again, fout is a variable, and ostream is a type
  ofstream fout("out.txt");
  
  int i;
  i = 1;
  while(i <= 10)
  {
    fout << i << endl;    // fout: write i into the file
    i = i + 1;
  }

  return 0;
}

Note: Do not confuse cout and fout.

  • cout prints to screen.
  • fout writes into the file.

Reading From a File

Opening an Input File

To open a file for reading, declare an ifstream variable and pass the filename as a string:

ifstream fin("temp.txt");           

Reading data

Reading from a file is very similar to reading input with cin.

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

int main()
{
  ifstream fin("temp.txt");           

  int n;
  // ********* READING ***************
  fin >> n;     
  // *********************************

  cout << "The first number is " << n << endl;
  return 0;
}
Note: The code
fin >> n
extracts an integer from the file temp.txt into variable n.

Other Useful Things

Closing input file streams

We know how to create an ifstream object that is open for reading to a file. How are input file streams closed? When you close a file, and a new ifstream variable is created to read from the same file, it starts over at the beginning.

Letting the User Provide a Filename

Often, we don't know in advance which file to open. Instead, we let the user specify the filename at runtime:

string name;  
cin >> name;  // user types filename 
ifstream fin(name); // open that file 

Working with Two Files at Once

Can you read two files? Yes! Simply create two variables of ifstream type at the same time!

ifstream fin1("in1.txt");
ifstream fin2("in2.txt");

int a1, a2;
fin1 >> a1;
fin2 >> a2;
cout << "file1:" << a1 << endl;
cout << "file2:" << a2 << endl;

Important: Checking Failures

File open failure

If the file cannot be opened (for example, if it does not exist), the stream will enter a failure state. You can check this by converting the stream into a bool.
ifstream fin("temp.txt");

// if fin enters a failure state
if (!fin) 
{
  cout << "File not found!" << endl;
  return 1; // exit the program!!	
}
Conversion of ifstream object into a bool

The boolean value represents the state of fin. In particular,

  • true, when fin is in a good state.
  • false, when it's in a failure state.

Note: The same idea applies to cin and cout too!

Using return 1

Reading failure

Likewise, you can check whether the reading operation has failed by later checking the state of fin.

string fname;
cin >> fname;

ifstream fin(fname);

int k;
fin >> k;

if( fin )
{
  // fin is still in good state
  cout << "k was " << k << endl;
}
else
{
  // fin has gone bad
  cout << "reading failed!" << endl;
}
Try:
  • test1.txt which contains: 2 3 7
  • test2.txt which contains: hello world
  • test3.txt which contains nothing

Summing all the numbers in the file

Now, let's write code that sums all the numbers in file temp

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

int main()
{
  // Create istream object that reads from file temp
  ifstream fin("temp.txt");   // note: fin has ifstream type
  if (!fin)
  {
    cout << "File not found!" << endl;
    return 1;				// exit the program!!	
  }   

  // Loop and add as long as more int's can be read
  int j, k;
  k=0;

  while(fin >> j)                 
  {
    k = k + j;
  }

  // Print out the sum k
  cout << k << endl; 
  return 0;
}
How while(fin >> j) works
  • Step 1: With (fin >> j), the program reads an integer into variable j.
  • Step 2: (fin>> j) evaluates to fin.
  • Step 3: Since fin is located in the while condition, fin is converted into a boolean value (i.e., the state of fin).
    • If the reading fails, the condition is false.
    • If it succeeds, it is true.

When a file ends: The code will keep reading an integer, and it will eventually read all the integers in the file. Then, reading will fail and the loop will stop.

Mandatory Practice Problem

Simple data bucketing. Write a program that works as follows:
  • Ask the user for a filename containing integers.
  • Store the even numbers in the file in file "even.txt" and the odd numbers in "odd.txt".
Solution: here.
Download data.txt.

Sample run:

$ ./a.out
Filename? data.txt
$ cat data.txt
1 3 2 4 10 8 7 5
$ cat even.txt
2 4 10 8
$ cat odd.txt
1 3 7 5

Other Practice Problems

  1. A simple data-conversion problem. You'd be amazed how often you need to write programs that do nothing more than convert data from one format to another. Write a program that reads in a file (name given by user) that contains points in ordered pair notation, and writes the same points to a file (name also given by user) in gnuplot notation, i.e. one point per line, each point given by x-coordinate tab ('\t') y-coordinate. For a nice small file to test with, we have testin.txt. For a nice big challenge file, we have in.txt.
    a solution.