CPSC 427a: Object-Oriented Programming

Michael J. Fischer

Lecture 7
September 22, 2011

subsection in toc subsection in toc subsection in toc subsection in toc subsection in toc subsection in toc

IO Demos

Handling data errors and end of file Section 3.7 of the textbook contains a demo program that illustrates how to handle data errors and end of file using C++ I/O. It has three parts that illustrate

See 06-IOdemo.

How to write a test program

The 06-IOdemo was written in C-style using three global functions: use_get(), use_getline(), and use_nums().

I rewrote the demo

Here, each test is encapsulated within its own class.

The only responsibility of main() is to process the command line arguments and initiate the tests.

See 07-IOdemo-new.

Introduction to Classes

(Textbook, Chapter 4)

Classes, visibility, functions, inline We covered much of the material from sections 4.1 and 4.2 in lectures 2 and 3.

The textbook covers it in greater depth, so be sure to also read the book.

Bar Graph Demo

We look at the Bar Graph demo from Chapter 8 of the textbook.

Bar graph sample input and output

Input:

AWF  00  
MJF  98  
FDR  75  
RBW  69  
GBS  92  
PLK  37  
ABA  56  
PDB  71  
JBK  -1  
GLD  89  
PRD  68  
HST  79  
ABC  82  
AEF  89  
ALA  105 

Output:
Name of data file: bar.in  
File is open and ready to read.  
 
00..09:  AWF 0  
10..19:  
20..29:  
30..39:  PLK 37  
40..49:  
50..59:  ABA 56  
60..69:  PRD 68 RBW 69  
70..79:  HST 79 PDB 71 FDR 75  
80..89:  AEF 89 ABC 82 GLD 89  
90..99:  GBS 92 MJF 98  
Errors:  ALA 105 JBK -1 

Bar graph data structure

UML Diagram

class Graph {  
  private:  
    Row* bar[BARS]; // List of bars (aggregation)  
    void insert( char* name, int score );  
  public:  
    Graph ( istream& infile );  
    ~Graph();  
    ostream& print ( ostream& out );  
    // Static functions are called without a class instance  
    static void instructions() {  
      cout  << "Put input files in same directory "  
               "as the executable code.\n";  
    }  
};  
inline ostream& operator<<( ostream& out, Graph& G) {  
    return G.print( out );  
}

Notes: graph.hpp

Graph::Graph( istream& infile ) {  
  char initials[4];  
  int score;  
 
  // Create bars  
  for (int k=0; k<BARS; ++k) bar[k] = new Row(k);  
 
  // Fill bars from input stream  
  for (;;) {  
    infile >> ws;  // Skip leading whitespace before get.  
    infile.get(initials, 4, ’ ’);  // Safe read.  
    if (infile.eof()) break;  
    infile >> score;          // No need for ws before >> num.  
    insert (initials, score); // *** POTENTIAL INFINITE LOOP  
  }  
}

Notes: graph.cpp

This implements four functions.

Private class for use by Row.

Note friend declaration and private constructor.

class Cell  
{  
  friend class Row;  
  private:  
    Item* data;  // Pointer to one data Item (Aggregation)  
    Cell* next;  // Pointer to next cell in row (Association)  
 
    Cell (char* d, int s, Cell* nx) {  
      data = new Item(d, s);  
      next = nx;  
    }  
    ~Cell (){ delete data; cerr <<"  Deleting Cell " <<"\n"; }  
};

Public class represents one bar of the bar graph

 
class Row { // Interface class for one bar of the bar graph.  
  private:  
    char label[10];  // Row header label  
    Cell* head;      // Pointer to first cell of row  
  public:  
    Row ( int n );  
    ~Row ();  
    void insert ( char* name, int score );  // delegation  
    ostream& print ( ostream& os );  
};

Notes: row.hpp

A Row is a list of Item. It is implemented by a linked list of Cell.

Notes: row.cpp

Nested classes: rowNest.hpp

Alternative to Row.

Puts entire Cell class definition inside of class Row.

Now Cell is private in Row, but everything inside of class Cell is public.

This obviates the need for Cell to grant friendship toRow and also completely hides Cell—even the name is hidden.

Interface is same, so can substitute

   #include "rowNest.hpp"

for

   #include "row.hpp"

in graph.hpp and everything still works!