CS 250 Computer Programming and Problem Solving - FALL 1998 

[ Home | Syllabus | Notes | Glossary | CS250 WEB Version Home Page ]


Templates Part 2


Book has a nice example of the use of templates


// DICT.H - Dictionary Class Template

#include <iostream.h>
#include "range.h" // header file for an exception class object

class DictionaryFull { // exception class for Dictionary full
public:
  friend ostream & operator <<(ostream & os,
         const DictionaryFull & F)
  {
    os << "Dictionary is full.";
    return os;
  }
};

class DuplicateKey {	// exception class for Duplicate Key insertion error
public:
  friend ostream & operator <<(ostream & os,
         const DuplicateKey & F)
  {
    os << "Attempt to add duplicate key.";
    return os;
  }
};


template<class TKey, class TVal>
class Dictionary {
public:
  Dictionary( unsigned maxEntries );
  ~Dictionary();

  int Add( const TKey & tk, const TVal & tv );
  // Add new key and value to dictionary.

  int Find( const TKey & tk );
  // If a key matching tk is found, set current to
  // the key's location and return 1. Otherwise,
  // return 0.

  int IsFull() const;
  // Return 1 if the dictionary is full, 0 otherwise.

  TVal Get() const;
  // Retrieve a copy of value at current key position.

  friend ostream & operator <<( ostream & os,
         const Dictionary<TKey, TVal> & D );

private:
  TKey * keys;      // array of dictionary keys hptrd_left.gif (955 bytes)
  TVal * values;    // array of dictionary values
  unsigned avail;   // index of next unused element
  unsigned size;    // size of the arrays
  unsigned current; // current index position
};

template<class TKey,class TVal>
Dictionary<TKey,TVal>::Dictionary( unsigned maxEntries )hptrd_left.gif (955 bytes)
{
  keys = new TKey[ maxEntries+1 ];
  values = new TVal[ maxEntries+1 ];
  avail = 0;
  size = maxEntries;
  current = 0;
}

template<class TKey,class TVal>
Dictionary<TKey,TVal>::~Dictionary()
{
  delete [] keys;
  delete [] values;
}

template<class TKey,class TVal>
int Dictionary<TKey,TVal>::Add( const TKey & tk,
                                const TVal & tv )
{
  if( !Find( tk ) ) // not already in dictionary?
  {
    if(IsFull())           // dictionary full?
      throw DictionaryFull();
    unsigned i = avail++;  // save position
    keys[i] = tk;          // add new key
    values[i] = tv;        // add associated value
    return 1;              // success!
  }
  throw DuplicateKey(); // attempt to add duplicate key
  return 0; // dummy statement to satisfy compiler
}

template<class TKey,class TVal>
int Dictionary<TKey,TVal>::Find( const TKey & tk )
{
  for(unsigned i = 0; i < avail; i++)
    if( tk == keys[i] )
    {
      current = i;   // save current position
      return 1;
    }
  return 0;
}

template<class TKey,class TVal>
int Dictionary<TKey,TVal>::IsFull() const
{
  return avail >= size;
}

template<class TKey,class TVal>
TVal Dictionary<TKey,TVal>::Get() const
{
  return values[current];
}

template<class TKey, class TVal>
ostream & operator <<( ostream & os,
        const Dictionary<TKey, TVal> & D )
{
  for(unsigned i = 0; i < D.avail; i++)
    cout << D.keys[i] << " -> "
         << D.values[i] << '\n';

  return os;
}


// DICT.CPP  - Dictionary Template Demonstration, Section 10.4.4.

#include <iostream.h>
#include <fstream.h>
//#include <except.h>  // xalloc exception
#include "dict.h"    // Dictionary class 
#include "fstring.h" // FString class
#include "nofile.h"  // NoFileError Exception class

// Create a Dictionary of customer account numbers
// (int) and file record numbers (long).

void create_customer_accounts()
{
  Dictionary<unsigned, long> accounts( 100 );
  cout << "Customer Accounts:\n";

  try {
	 accounts.Add( 101, 287 );
	 accounts.Add( 152, 368 );
	 accounts.Add( 173, 401 );
	 accounts.Add( 185, 368 ); // duplicate value is ok
	 accounts.Add( 152, 399 ); // duplicate key forbidden
  }
  catch( const DuplicateKey & dk ) { // who trhows this exception?
    cout << dk << endl;
  }
  cout << accounts << endl;  // display the list

  cout << "Account number to find? ";
  unsigned n;
  cin >> n;
  if( accounts.Find( n ))
    cout << "Account number " << n
         << " may be found at record "
         << accounts.Get() << '.' << endl;
  else
    cout << "Account not found." << endl;
  cout << endl;
}

// Create a dictionary of automobile part
// numbers (long) and part descriptions (String).

void create_parts_list()
{
  FString filename( "parts.txt" );
  ifstream infile( filename ); // overload the cast operator
  if( !infile ) throw NoFileError( filename );

  // Add part numbers and descriptions to a dictionary.

  unsigned long partNum;
  FString descrip;
  const unsigned plistSize = 200;

  cout << "Automobile parts list:\n";
  Dictionary<unsigned long, FString> pList( plistSize );

  try {
    
// Code in Book    
    infile >> partNum;
    while( !infile.eof() )
    {
      descrip.GetLine( infile );
      pList.Add( partNum, descrip );
      infile >> partNum;
    }
// A simpler way to do file I/O loops
    while( infile >> partNum )
    {
      descrip.GetLine( infile );
      pList.Add( partNum, descrip );
    }
  }
  catch( const DuplicateKey & dk ) {
    cout << dk << endl;
  }
  cout << pList;

  cout << "Part number to find? ";
  cin >> partNum;

  if( pList.Find( partNum ))
    cout <<
     "Part " << partNum << " is a "
             << pList.Get() << '.' << endl;
  else
    cout << "Part number not found." << endl;
}

// main: create two dictionaries, handle all
// uncaught exceptions.

int main()
{
  cout << "Dictionary Template Demo Program\n\n";
  try {
    create_customer_accounts();
    create_parts_list();
  }
/*  catch ( xalloc ) {
    cout << "Memory allocation error\n";
  }*/
  catch ( const DictionaryFull & df ) {
    cout << df;
  }
  catch ( const NoFileError & nf ) {
    cout << nf;
  }
  catch ( ... ) {
    cout << "Unknown exception caught.\n";
  }
  return 0;
}

Copyright chris wild 1998.
For problems or questions regarding this website contact [Chris Wild (e-mail:wild@cs.odu.edu].
Last updated: November 18, 1998.