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 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 ) { 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; }