11-1 Computing Fundamentals with C++ Object-Oriented Programming and Design, 2nd Edition Rick Mercer Franklin, Beedle & Associates, 1999 ISBN Presentation Copyright 1999, Franklin, Beedle & Associates Students who purchase and instructors who adopt Computing Fundamentals with C++, Object-Oriented Programming and Design by Rick Mercer are welcome to use this presentation as long as this copyright notice remains intact.
11-2 Chapter 11 A Container with Iterators Chapter Objectives declare and use bag objects that store collections of objects define classes with vector data members implement member functions that manipulate vectors implement and use iterator functions for traversing over all the items in a collection
The bag class Programmers use many container classes A class with the main purpose of storing a collection of elements that can be accessed different container classes allow different access –for example a vector allows direct access to any element Other standard containers: stack, queue, list, and map The bag class is presented here as review of class definitions vectors and vector processing It's a container class capable of storing many items
11-4 A bag class continued A bag object as discussed in Chapter 11--there are others stores a collection of elements that are not in any particular order are not necessarily unique has operations that include bag::add bag::add bag::remove bag::remove bag::capacity bag::capacity bag::size bag::size class definition for this bag class follows
11-5 class bag { public://--constructors bag(); bag(); bag(int capacity); bag(int capacity);//--modifiers void add(BAG_ELEMENT_TYPE newElement); void add(BAG_ELEMENT_TYPE newElement); bool remove(BAG_ELEMENT_TYPE removalCandidate); bool remove(BAG_ELEMENT_TYPE removalCandidate);//--accessors int capacity(); int capacity(); int size(); int size(); bool isEmpty(); bool isEmpty(); // -- iterator functions on next slide private: vector my_data; vector my_data; int my_size; int my_size;}; The bag class definition
11-6 The public iterator functions void first(); // post: my_index points to the first item, or if the // bag is empty, isDone would now return true void next(); // post: point to the next item, or isDone returns true bool isDone() const; // post: Returns true if collection has been traversed BAG_ELEMENT_TYPE currentItem() const; // post: Returns the item pointed to by the my_index
11-7 Client code that uses bag #include #include using namespace std; // This must precede #include "bag" (better way shown later) typedef string BAG_ELEMENT_TYPE; // <- for a bag of strings #include "bag" int main() { // This program sends all possible messages to a bag object bag bagOfStrings; bag bagOfStrings; bagOfStrings.add( "A string" ); bagOfStrings.add( "A string" ); bagOfStrings.add( "Another string" ); bagOfStrings.add( "Another string" ); bagOfStrings.add( "and still another" ); bagOfStrings.add( "and still another" ); bagOfStrings.add( "and a fourth" ); bagOfStrings.add( "and a fourth" ); bagOfStrings.remove( "and still another" ); // delete one bagOfStrings.remove( "and still another" ); // delete one bagOfStrings.remove( "I'm not in the bag!" ); // can't bagOfStrings.remove( "I'm not in the bag!" ); // can't return 0; return 0;}
11-8 A bag of ints A bag object stores a collection objects To store int objects for example, do this: typedef int BAG_ELEMENT_TYPE; typedef int BAG_ELEMENT_TYPE; #include "bag" #include "bag" int main() int main() { bag bagOfInts( 100 ); bag bagOfInts( 100 ); bagOfInts.add( 72 ); bagOfInts.add( 72 ); bagOfInts.add( 97 ); bagOfInts.add( 97 ); //... //...
The bag Constructors The constructors create an empty bag bag::bag() { // Default is an empty bag with capacity 16 my_size = 0; my_size = 0; my_data.resize(16); my_data.resize(16);} bag::bag(int initialCapacity) { // Create an empty bag of any capacity desired my_size = 0; my_size = 0; my_data.resize(initialCapacity); my_data.resize(initialCapacity);} bag default; // call default constructor bag default; // call default constructor bag hold500(500); // construct with one argument bag hold500(500); // construct with one argument
The bag Modifying Member Functions The bag::add operation adds all new elements to the "end" of the vector. If there is no room, the vector is resized void bag::add(BAG_ELEMENT_TYPE newElement) { // First, increase the bag capacity if necessary if(my_size >= my_data.capacity()) if(my_size >= my_data.capacity()) { my_capacity = 2 * my_data.capacity(); my_capacity = 2 * my_data.capacity(); my_data.resize( my_capacity ); my_data.resize( my_capacity ); } // Store argument into vector of BAG_ELEMENT_TYPEs... // Store argument into vector of BAG_ELEMENT_TYPEs... my_data[my_size] = newElement; my_data[my_size] = newElement; //...and make sure my_size is always increased by +1: //...and make sure my_size is always increased by +1: my_size++; my_size++;}
11-11 bag::remove bag::remove uses sequential search to find the element to be removed If the element is found move the last element ( my_data[my_size-1] ) into the location of the removal element decrease my_size by 1 does the following code look familiar?
11-12 bag::remove bool bag::remove(BAG_ELEMENT_TYPE removalCandidate) { int subscript = 0; int subscript = 0; // Sequentially search for removalCandidate // Sequentially search for removalCandidate while( (subscript < my_size) while( (subscript < my_size) && (my_data[subscript] != removalCandidate)) { && (my_data[subscript] != removalCandidate)) { subscript++; subscript++; } if(subscript == my_size) // removalCandidate not found if(subscript == my_size) // removalCandidate not found return false; return false; else { // move last element to removalCandidate's spot else { // move last element to removalCandidate's spot my_data[subscript] = my_data[my_size-1]; my_data[subscript] = my_data[my_size-1]; // and then decrease size by 1 // and then decrease size by 1 my_size--; my_size--; // report success to the message sender // report success to the message sender return true; return true; }}
11-13 The state of bagOfStrings before removing "Another string" Data Members State my_data[0] "A string" my_data[1] "Another string" my_data[2] "and still another" my_data[3] "and a fourth" … my_size 4 local objects in bag::remove removalCandidate "Another string" subscript 1
11-14 "Another string" The state after removing "another string" Wipe out "Another string" No longer meaningful Decrease size 1. Find removalCandidate in my_data[1] 2. Overwrite it with the "last" bag element and decrease size my_data[0] "A string" my_data[1] "And a fourth" my_data[2] "and still another" my_data[3] "And a fourth"... my_size 3
The bag Accessor functions int bag::capacity() const { // Return how many elements could be stored return my_data.capacity(); return my_data.capacity();} int bag::size() const { // Return how many elements are in the bag return my_size; return my_size;} bool bag::isEmpty() const { // Return true if there are 0 elements in the bag return my_size == 0; return my_size == 0;}
The Iterator Pattern vectors have subscripts for iterating over all the meaningful elements standard containers, including vectors use a separate iterator class more later bags use member functions firstisDonecurrentItemnext
11-17 Iterating over items in a bag bag aBag; int sum = 0; int sum = 0; int n = 9; int n = 9; for(int j = 1; j <= n; j=j+2) for(int j = 1; j <= n; j=j+2) { aBag.add(j); aBag.add(j); } cout << "Iterate over the entire collection" << endl; cout << "Iterate over the entire collection" << endl; for( aBag.first(); ! aBag.isDone(); aBag.next() ) for( aBag.first(); ! aBag.isDone(); aBag.next() ) { cout.width(4); cout.width(4); // reference "current" bag element // reference "current" bag element cout << aBag.currentItem(); cout << aBag.currentItem(); // reference it again // reference it again sum = sum + aBag.currentItem(); sum = sum + aBag.currentItem(); } cout << "\nSum: " << sum << endl; cout << "\nSum: " << sum << endl; Output ? Demonstrate testbag.cpp
11-18 The iterator implementations void bag::first() { // Set internal index to reference the 1st element my_index = 0; my_index = 0;} bool bag::isDone() const { // Return true if previous next was the last element return my_index >= my_size; return my_index >= my_size;} void bag::next() { // Set internal index to reference the next element // or to allow isDone to return true // or to allow isDone to return true my_index++; my_index++;} BAG_ELEMENT_TYPE bag::currentItem() const { // Set internal index to reference the 1st element return my_data[my_index]; return my_data[my_index];}
11-19 The Iterator pattern will be repeated as are all patterns The iterator pattern will be used again In Chapter 13: Object-Oriented Software Development to display all CDs in a CD collection to display all track in a CD In Section 14.2 iterator objects are used to traverse the elements in the standard C++ containers such as vector and list –the iterator pattern is implemented quite differently