Activity 5-3 - Reading to The End of File
                       Member Functions get and put
                       Member Function eof



In Program P52.cpp, you read all the integers from a file and did the required computations.  In that program, you used:

    while( in_s >> x) // Step (4)-Read all numbers one-by-one to the end of the file
    {
         ....

    }

to do the reading.  Let's see if we can use a similar technique to read a text file and display its contents.  In order to do this, let's first create the following input file.

Exercise 5.4
Create a file called act54.txt and type the following text exactly as it appears below into that file. You may cut and paste the following 10 lines into that file.

We have learned that "\n" means go to a new line
when it is used with the cout statement.
In C++, '\n' and "\n" look very similar.
In fact, in a cout statement, they both act the same.

However, they do not mean the same in all situations.
'\n' is a value of type char and can be stored in a variable
of type char, for example:  int c = '\n';
On the other hand, "\n" is a string,
that happens to be made up of one character.

The following program uses a similar technique as in program P52.cpp to read the entire contents of the act54.txt file and to display its entire contents exactly as they appear above.

// P54.cpp - This program reads the entire contents of an input file and will
// display it with the same format.
#include<iostream>
#include<fstream>  // Step (1)
#include<cstdlib>
using namespace std;

void get_input_stream(ifstream& in_s);

int main( )
{
    char c;
    ifstream in_s;  // Step (2)-B - declaration of the stream of type input

    get_input_stream(in_s);

    cout << "Here are the entire contents of the input file \n";

    while( in_s >> c) // Step (4)-Read all numbers one-by-one to the end of the file.
    {
         cout <<  c;
    }

   cout << "\n I am done with writing the contents of the file \n";

    in_s.close( );  // Step (5)-Close the connection (close the file)

   return 0;
}

void get_input_stream(ifstream& in_s)
{
 char input_file[15]; // Step (2)-A
    cout << "Please input the input file name \n"; // Step (3)-A Get the file name
    cin >> input_file;

    in_s.open(input_file); // Step (3)-B - Connect to the input file and test
    if(in_s.fail( ))
    {
       cout << "Input file opening failed. \n";
       exit(1);  // if we couldn't open the file to read from we exit
    }
}

Exercise 5.5
Cut and paste or carefully copy the P54.cpp program into a file called ex55.cpp.  Compile the program to make sure it compile without any error.  Then run the program and use the act54.txt file as the input file.

Does this program produce the same exact output as shown above?

What do you think the problem is?

The get and put Member Functions

We will help you find the answer very soon.  The problem is that cin does not read the white spaces, i.e., it skips blank spaces, tabs (\t), and new lines (\n).  Thus, the entire text will appear in one piece without the separating spaces and new lines.  In order to read and write the entire text with correct spacing, we will use a member function with the input stream.  The get(c) function, where c is a character, allows us to read all characters from the file one character at a time.  So to fix the above program we could simply us this function instead of the cin.  We used:

   while( in_s >> c) // Step (4)-Read all numbers one-by-one to the end of the file
   {
       ....
   }

to read the contents of the file.  Now we can replace the in_s >> c with in_s.get(c).

Exercise 5.6
Modify the ex55.cpp program by replacing in_s >> c with in_s.get(c) in the while loop.  Compile, then run the program for the act53.txt input.  Call your new program ex56.cpp.

Does your program produce the correct output this time?

The member function put(c) will do the opposite of what the  member function get(c) does.  It writes to the output stream one character at a time.   To practice with this function, in program ex56.cpp, you can replace the:
         cout <<  c;

with
         cout.put(c);

That does the same thing.

The eof Member Function
There is yet another way to read a file (any file) to the end.  The member function eof( ) can be used with a stream of input type to determine the End-Of-File.  This function returns true when the end of the input file is reached.  Thus, it can be used in a while loop to control the looping process.  In general, you need to read one character before you check to see if the end of the file is reached.  Here is a way to use the eof( ).  Please note that we haven't shown the complete program.

// Other lines of program
ifstream in_s;
char next_char;
// Other lines of programs

in_s.get(next_char);

while( ! in_s.eof( ) )
{
     cout << next_char;       // you could use cout.put(next_char) too
     in_s.get(next_char);
}

Exercise 5.7
Modify the program ex55.cpp by using the eof( ) to read to the end of file act53.txt and to display its entire contents.  Make sure to check that the displayed contents are exactly the same and in the same format.