Computing Concepts with C++ Essentials
Laboratory Notebook
Chapter 10 - Files

Cay S. Horstmann
Geof Pawlicki

Your name:
Your email address:
Your student ID number:

Once this form has been customized for your institution, you can use this button to send your lab work. Be sure to read the instructions before starting your work.

Lab Objectives

To gain experience with

P1. Reading Text Files

You already know how to read data from a file and write data to a file, by using the system variables cin and cout together with command-line redirection (myprog <input.txt >output.txt).

However, this approach is limited. You need to learn to use files directly in your program in the following situations:

In these situations, you need files. C++ supports three file types, fstream, ifstream and ofstream. The latter two are used to open files for input or output only. Since fstream can be used for both reading and writing, we will not cover those other file classes in this course.

To open a file, first define an object of type fstream and then call the open member function.

fstream my_data;"output.txt", ios::out);   

Next, you should check that the file was opened successfully:

if (
   cout << "Unable to open output.txt";

Then you can read and write with the same commands that you used with cin and cout, such as << >> get_line get_int etc.

Write a program which compares the contents of two files. Have your program display the line number and text of the first pair of lines that differ.

First, prompt the user for the names of the two files. Then open each file. Remember to check for failure. Keep reading a line from each of them. Increment a line number counter. If both inputs fail, print a message indicating that both files are identical. If one of the inputs fails and the other does not, print a message indicating which file is shorter, then exit. If the two input lines are different, print the line number counter and both input lines, then exit. If the two input lines are identical, keep on reading.

P2. Reading Input Data in a Graphics Program

Consider a graphics program that prompts the user to define shapes by selecting menu options and clicking on a window. When the user is done, the user's work should be stored in a file so that the user can retrieve it later. Graphics can be stored in a variety of formats. Choosing the best format for a particular purpose involves factors such as speed, portability to different platforms and programs, and the storage space and transmission requirements. In this lab exercise, we will use a simple text file containing lines of the form:

Circle 1 3 5.0
Circle -4 3 5.0

That is, a circle is specified by the x- and y-coordinates of it's center, followed by it's radius.

When the program starts, all saved data are read in automatically from the file saved.dat. When the user adds more circles, then the new circles are appended to that file.

void read_shapes(fstream& shape_file)
/* PURPOSE:  Read shapes from a file and display them
   RECEIVES: shape_file - the file containing the shape descriptions
{  /* your work here */

void add_circle(fstream& shape_file, Circle c)
/* PURPOSE:  Add a circle shape to a file
   RECEIVES: shape_file - the file containing the shape descriptions
             c - the circle to add
{  /* your work here */  

int main()
{  fstream shapes("saved.dat", ios::in + ios::out);
   while (true)
   {  if (uppercase(cwin.get_string("More circles? (Y/N)")) == "N") 
      {  return EXIT_SUCCESS;
      Point center = cwin.get_mouse("Center: ");
      float radius = cwin.get_float("Radius: ");
	     Circle c(center, radius);
      cwin << c;

Note: The next time the user starts, the newly added circles are automatically displayed.

Consider the read_shapes and add_circle functions. Both have fstream as a reference parameter. Of course, add_circle adds new data to the file. But read_shapes doesn't change the contents of the file on disk. Why is it nevertheless necessary to pass the fstream object by reference?

Now implement the circle drawing program. Extra credit if you enhance it to handle both circles and lines!

P3. Command Line Arguments

Extend your file comparison program in two ways. First, make it possible to specify the file names on the command line. Only ask the user for the file names when they are not specified. And support a command line flag to control the number of differences identified. That is:

differ -a file1.txt file2.txt       
   displays all differences
differ -n  file1.txt file2.txt
   displays the first n differences
   For example
differ -20   
   displays the first 20 differences and prompts the user for the file names

P4. Random Access

If a file stores records of fixed length, it is easy to locate any one of them. If the records are also in a sorted order, for example employee records sorted by name, it is also possible to implement a fast search strategy called binary search. Rather than having to step through every record, you can eliminate half of the records remaining at each stage of the search because they are either too big or too small.

Consider searching for the name "Mushroom" in the following listing.

  Acorn, John         34000
  Barley, Lawrence    37500 
  Corn, Charlie       29000
  Flax, Winston       43700
  Grape, Priscilla    35800
  Kiwi, Rachel        28700
->Lime, Lucy          45400
  Melon, Walker       33000
  Nasturtium, Ken     57000
  Olive, Ollie        29500
  Pickle, Jim         32000
  Radish, Ruby        32500
  Squash, Slim        44700
  Turnip, Misha       27500

First, note that there are 14 records. Start in the middle, at record 7, "Lime". Compare it with the search term, "Mushroom". Since "Mushroom" > "Lime", there is no need to look for it in the lines containing "Acorn" through "Lime".

  Melon, Walker       33000
  Nasturtium, Ken     57000
  Olive, Ollie        29500
->Pickle, Jim         32000
  Radish, Ruby        32500
  Squash, Slim        44700
  Turnip, Misha       27500

Go to the middle again. This time the middle among records 8 through 14 is record 11,"Pickle". Similarly, since "Mushroom" < "Pickle", "Pickle" through "Turnip" can be eliminated from further consideration.

That leaves only records 8 through 10. The middle record is 9.

  Melon, Walker       33000
->Nasturtium, Ken     57000
  Olive, Ollie        29500

That record is larger than "Mushroom", so we are left with records 8 through 8, i.e. a single record.

->  Melon, Walker       33000

Since this is not a match, we see that the name Mushroom is not in the database!

Here is the pseudocode to locate the value e, using binary search.

from = 0; 
to = index of last record;  

while (from <= to)
{  int mid = (from + to) / 2;
   if (value at mid equals e) return mid;
   else if (value at mid comes before e)
      from = mid + 1;
      to = mid - 1;
// e not found

Enhance database.cpp from the textbook to prompt for a user input lastname, then search for it using a binary search strategy. (Of course, you must use a data file that is sorted).

Don't forget to send your answers when you're finished.