How to use Standard template library in C++

how to include standard template library c++ and standard template library algorithms and advantages and standard template library c++ interview questions and tutorial
Dr.NaveenBansal Profile Pic
Dr.NaveenBansal,India,Teacher
Published Date:25-10-2017
Your Website URL(Optional)
Comment
CHAPTER 7 Standard Template Library The standard template library (STL) is the C++ library providing generic programming for many standard data structures and algorithms. The STL provides three types of components—containers, iterators, and algorithms—that support a standard for generic programming. The library is built using templates and is highly orthogonal in design. It is orthogonal in that components can be used in combination with one another on native and user- provided types through proper instantiation of the various elements of the STL. The fol- lowing sections serve only as an overview and brief introduction to the STL, which is large and complicated. Many newer systems have important further extensions to the STL. 7.1 7.1 A Simple STL Example We start with an example of using the container class vector. It was briefly discussed in Section 6.6.2, vector in STL, on page 267. This class is a generalization of the native array type in C++ and, as such, is easily understood and used. Indeed, one of the most effective uses of the STL is to replace the use of ordinary C++ arrays with STL vec- tors. The STL vector type has many important advantages over the array, such as dynamic expansion, thus avoiding overflow. Further, it can be readily navigated with both iterators and indices and has a rich interface of built-in operations. In file stl_vector1.cpp // Simple STL vector program include iostream include vector using namespace std;Ira Pohl’s C++ by Dissection 7.1 A Simple STL Example 281 int main () vectorint v(100); // 100 is vector's size for (int i = 0; i 100; ++i) vi = i; for (vectorint::iterator p = v.begin(); p = v.end(); ++p) cout p '\t'; cout endl; Dissection of the stl_vector Program // Simple STL vector program include iostream include vector using namespace std; The library vector contains the STL’s template for the component vector. vectorint v(100); // 100 is vector's size The STL container vector is used in place of an ordinary int array. As with any other template, it is instantiated with an existing type. Here, we use the native type int. The template class has a number of constructors. The one used here generates an int vector of size 100. for (int i = 0; i 100; ++i) vi = i; The first for statement is written in exactly the same manner as a C++ loop on ordinary data. In most instances, vectors can be used in place of native arrays without changing working code besides the dec- larations. for (vectorint::iterator p = v.begin(); p = v.end(); ++p) cout p '\t'; The second for statement is written using the iterator p. An iterator behaves as a pointer. STL provides the member functions begin() and end() as initial and terminal position values for the container. Note that end() returns the iterator position (or address), one past the last element of the container. Thus, end() is a guard location, or a value signaling that you are finished traversing the container.Ira Pohl’s C++ by Dissection 7.1 A Simple STL Example 282 The next example uses the list container, an iterator, and the generic algorithm accumu- late(). The list and numeric libraries are required. In file stl_container.cpp include iostream include list // list container include numeric // for accumulate using namespace std; // Using the list container void print(listdouble &lst) listdouble::iterator p; // traverse iterator for (p = lst.begin(); p = lst.end(); ++p) cout p '\t'; cout endl; int main() double w4 = 0.9, 0.8, 88, -99.99 ; listdouble z; for (int i = 0; i 4; ++i) z.push_front(wi); print(z); z.sort(); print(z); cout "sum is " accumulate(z.begin(), z.end(), 0.0) endl; In this example, a list container is instantiated to hold doubles. An array of doubles is pushed into the list. The print() function uses an iterator to print each element of the list in turn. Notice again that iterators work like pointers. Both the list and the vector have the standard begin() and end() member functions for starting and ending loca- tions of the container. Also, the list interface includes a stable sorting algorithm, the sort() member function. In a stable sort, equal elements remain in the same relative position. The accumulate() function is a generic function in the numeric package that uses 0.0 as an initial value and computes the sum of the list container elements by going from the starting location z.begin() to the ending guard location z.end(). Notice that print() itself could be parameterized by using an iterator range and a return value of the position where the printing leaves off, making it a more general algorithm. Let us do this:Ira Pohl’s C++ by Dissection 7.2 Containers 283 // Using the iterator range // b is the beginning location // e is the guard location and ends the iteration template class Iterator Iterator print(Iterator b, Iterator e) for (Iterator p = b; p = e; ++p) cout p '\t'; cout endl; return p; //guard value This version of print is far more general. It works on any standard container, including native array types. It also illustrates some conventions that STL uses. Typically, the end- ing location is a guard value and is the location one past the last element processed. Thus, the loop termination test is p = e, so as not to process this location. 7.2 7.2 Containers Containers come in two major families: sequence and associative. Sequence containers (vectors, lists, and deques) are ordered by having a sequence of elements. The vector is the most useful. The deque is a double-ended queue container, conveniently added to at both front and back. The list makes internal insertion and deletion efficient and conve- nient. Associative containers (sets, multisets, maps, and multimaps) have keys for look- ing up elements. The set is a container that stores a value according to an ordering relationship. A set contains only unique values. The multiset allows multiple copies of the same item to be stored. The map container is a basic associative array and requires that a comparison operation on the stored elements be defined. The multimap is a gen- eralization of a map that allows nonunique keys. So, one key value may be linked to more than one value. The two varieties of container share a similar interface. STL Typical Container Interfaces Constructors, including default and copy constructors Element access Element insertion Element deletion Destructor Iterators Containers are traversed using iterators that are available as templates and optimized for use with STL containers.Ira Pohl’s C++ by Dissection 7.2 Containers 284 In file stl_deque.cpp // A typical container algorithm template class Summable Summable sum(dequeSummable &dq) dequeSummable::iterator p; Summable s = 0; for (p = dq.begin(); p = dq.end(); ++p) s += p; return s; Dissection of the deque sum() Function template class Summable double sum(dequeSummable &dq) We sum the elements contained in this double-ended queue container dq. It is passed by reference to avoid copying costs for the potentially large data structure. The choice for identifier Summable is used to indicate that the instantiated type should have properties that allow for addition and should recognize a value of 0. It is a convention to capitalize the template class identifier because it is a meta-variable that is instantiated with an actual type when used by the compiler to produce machine code. dequeSummable::iterator p; The deque container is traversed using an iterator. The iterator p is dereferenced to obtain each stored value in turn. This algorithm works with sequence containers and all types having operator+=() defined. Containers allow equality and comparison operators and have an extensive list of standard data and function members. for (p = dq.begin(); p = dq.end(); ++p) s += p; This is a standard traversal idiom for STL containers. Notice how it works for ordinary pointers as well. This algorithm would be more gen- eral if instead of a specific container type it used a parameterization based on an iterator range. Container classes, as shown in Table 7.1, are designated as CAN in the following descrip- tion of their interface. The identifier CAN was chosen because a can is something that holds items. All container classes have these definitions available. For example, in using the vector container class, vectorchar::value_type means a character value is stored in theIra Pohl’s C++ by Dissection 7.2 Containers 285 Table 7.1 STL Container Definitions CAN::value_type Type of value held in the CAN CAN::reference Reference type to value CAN::const_reference const reference CAN::pointer Pointer to value type CAN::iterator Iterator type CAN::const_iterator const iterator accessing const values CAN::reverse_iterator Reverse iterator moving backward CAN::const_reverse_iterator const reverse iterator CAN::difference_type Represents the difference between two CAN::iterator values CAN::size_type Size is an integral type that can represent a difference_type value vector container and could be traversed with a vectorchar::iterator. For exam- ple: In file stl_vector_char.cpp include iostream include typeinfo include vector using namespace std; int main() char c; vectorchar::value_type v; if (typeid(c) == typeid(v)) cout "vectorchar::value_type is just char" endl; else cout "vectorchar::value_type differs " "from char" endl; Containers have an extensive list of standard member functions, as shown in Table 7.2. Containers allow equality and comparison operators, as shown in Table 7.3. 7.2.1 Sequence Containers Sequence containers (vector, list, and deque) have a sequence of accessible elements. In many cases, the C++ array type can also be treated as a sequence container. In the stl_vector2 program, we create a five-element vector v. The deque and vector libraries are used.Ira Pohl’s C++ by Dissection 7.2 Containers 286 Table 7.2 STL Container Members CAN::CAN() Default constructor CAN::CAN(c) Copy constructor c.begin() Beginning location of CAN c c.end() Guard location of CAN c c.rbegin() Beginning used by a reverse iterator c.rend() Guard used by a reverse iterator c.size() Number of elements in CAN c.max_size() Largest possible size c.empty() true if the CAN is empty c.swap(d) Swap two CANs Table 7.3 STL Container Operators == = = = Equality and comparison operators using CAN::value_type In file stl_vector2.cpp // Sequence Containers - insert a vector into a deque // Simple STL vector program include iostream include vector include deque using namespace std; int main() int data5 = 6, 8, 7, 6, 5 ; vectorint v(5, 6); // 5 element vector dequeint d(data, data + 5); dequeint::iterator p; cout "\nDeque values" endl; for (p = d.begin(); p = d.end(); ++p) cout p '\t'; // print:6 8 7 6 5 cout endl; d.insert(d.begin(), v.begin(), v.end()); for (p = d.begin(); p = d.end(); ++p) cout p '\t';// print:6 6 6 6 6 6 8 7 6 5 cout endl; Ira Pohl’s C++ by Dissection 7.2 Containers 287 Dissection of the stl_vector Program int data5 = 6, 8, 7, 6, 5 ; vectorint v(5, 6); // 5 element vector dequeint d(data, data + 5); dequeint::iterator p; The vector v initializes a five-element int container to value 6. The deque d uses the iterator values data and data + 5 to initialize a five-element double-ended queue container. This is one of the stan- dard container class constructors. Notice how it uses an iterator range to pass in arguments for the constructor. Many of the STL func- tions use iterator ranges as arguments. Here, array pointers are used as iterator values. The starting value is the pointer address d, and the ending guard value is the pointer address d+5. The iterator p is declared but is not initialized. The dequeint d is initialized sequentially to the five values 6, 8, 7, 6, and 5. for (p = d.begin(); p = d.end(); ++p) cout p '\t'; // print:6 8 7 6 5 In this standard idiom, notice that d.end() is used to terminate the loop, because it is the end-of-container iterator guard value. Also notice that the ++ increment has pointer semantics advancing the iterator to the next container position. Dereferencing also works anal- ogously to pointer semantics. d.insert(d.begin(), v.begin(), v.end()); The insert() member function places the range of iterator values v.begin() up to but not including v.end() at the position d.begin(). The insert() member function is very typical of mem- ber functions in STL, using the first iterator value as an insertion point and an iterator range for the values to be inserted. for (p = d.begin(); p = d.end();++p) cout p '\t';// print:6 6 6 6 6 6 8 7 6 5 As a consequence of inserting five new elements of value 6 at the front of the deque d, the output of the traversal loop for d is now the 10 elements, as shown in the comment. Some sequence container member functions are given in Table 7.4. Sequence classes are designated as SEQ in the following description of their interface; these are in addition to the already described CAN interface. End values designated in Table 7.4 below as e_it are understood as guard values.Ira Pohl’s C++ by Dissection 7.2 Containers 288 Table 7.4 STL Sequence Members SEQ::SEQ(n, v) n elements of value v SEQ::SEQ(b_it, e_it) Starts at b_it and goes to e_it c.insert(w_it, v) Inserts v before w_it c.insert(w_it, v, n) Inserts n copies of v before w_it c.insert(w_it, b_it, e_it) Inserts b_it to e_it before w_it c.erase(w_it) Erases the element at w_it c.erase(w_it, e_it) Erases w_it to e_it 7.2.2 Associative Containers The associative containers (sets, multisets, maps, and multimaps) have key-based acces- sible elements and an ordering relation Compare, which is the comparison method for the associative container. In section Section 7.6, STL: Function Objects, on page 315, we show you how to program such a method as a class that has the function call opera- tor() overloaded. Briefly, a set is a container that stores a unique value according to an ordering relation- ship. For example, it might store a series of strings according to lexicographic (alpha- betic or dictionary order) comparison, or integers according to their value. The multiset is a generalization of a set that can store multiple copies of the same item. The map is a container that has a pair of values. Each element is a key-value pair. It allows you to look up the value based on the key in an efficient manner. This is also known as an associative array. The multimap generalizes map to allow nonunique keys. So, one key may be linked to more than one value. We have an example of using the map and string libraries: In file stl_age.cpp // Associative Containers - looking up ages include iostream include map include string using namespace std; int main() mapstring, int, lessstring name_age; name_age"Pohl,Laura" = 12; name_age"Dolsberry,Betty" = 39; name_age"Pohl,Tanya" = 14; cout "Laura is " name_age"Pohl,Laura" " years old." endl; Ira Pohl’s C++ by Dissection 7.2 Containers 289 Dissection of the stl_age Program include map include string These are two standard library header files needed for the map con- tainer where it is used for looking up information based on a string. mapstring, int, lessstring name_age; The map name_age is an associative array where the key is a string type and the Compare object is lessstring. The map is a template that requires three arguments. This means that an int value is stored in the map and found using a string value. The ordering rela- tionship is lessstring. name_age"Pohl,Laura" = 12; name_age"Dolsberry,Betty" = 39; name_age"Pohl,Tanya" = 14; The ages of the three people are stored in the map name_age. cout "Laura is " name_age"Pohl,Laura" " years old." endl; Here, associative retrieval is used to get back the age of Laura Pohl. Unlike an ordinary array, which takes constant time to retrieve a stored value, the map requires logarithmic time per lookup. The associative containers have several standard constructors for initialization. What distinguishes these constructors from sequence container constructors is the use of a comparison method. The insertions work when no element of the same key is already present. Associative classes are shown as ASSOC in Table 7.5. Keep in mind that these are in addition to the already described CAN interface. Table 7.5 STL Associative Definitions ASSOC::key_type Retrieval key type ASSOC::key_compare Comparison method object for keys ASSOC::value_compare Comparison method object for values The associative containers have several standard constructors for initialization, as shown in Table 7.6. What distinguishes associative constructors from sequence container constructors is the use of a comparison method, as in Table 7.7. The insertion works when no element of the same key is already present, as seen in Table 7.8. Ira Pohl’s C++ by Dissection 7.2 Containers 290 Table 7.6 STL Associative Constructors ASSOC() Default constructor using Compare ASSOC(cmp) Constructor using cmp as the comparison method ASSOC(b_it, e_it) Uses element range b_it to e_it using Compare ASSOC(b_it, e_it, cmp) Uses element range b_it to e_it and cmp as the comparison method Table 7.7 STL Insert and Erase Member Functions c.insert(t) Inserts t, if no existing element has the same key as t; returns pair iterator, bool with bool being true if t was not present c.insert(w_it, t) Inserts t with w_it as a starting position for the search; fails on sets and maps if key value is already present; returns position of insertion c.insert(b_it, e_it) Inserts the elements in this range c.erase(k) Erases elements whose key value is k, returning the number of erased elements c.erase(w_it) Erases the pointed-to element c.erase(b_it, e_it) Erases the range of elements Table 7.8 STL Member Functions c.find(k) Returns iterator to element having given key k; otherwise, ends c.count(k) Returns the number of elements with key k c.lower_bound(k) Returns iterator to first element having value greater or equal to key k c.upper_bound(k) Returns iterator to first element having value greater than key k c.equal_range(k) Returns an iterator pair for lower_bound and upper_bound The associative containers are sets, multisets, maps, and multimaps. They have key- based accessible elements. These containers have an ordering relation, Compare, which is the comparison method for the associative container. As a further associative container example, we use a multiset to count the number of times each vegetable enters our diet in the course of 100 meals. We use a random num- ber generator to select which vegetable we will have in a given meal. Besides printing out the number of times each vegetable is in a meal, we will print out how the multiset stores this information.Ira Pohl’s C++ by Dissection 7.2 Containers 291 In file stl_multiset.cpp // Associative Containers - checking up on your diet include iostream include set // used for both set and multiset include vector using namespace std; enum vegetables broccoli, tomato, carrot, lettuce, beet, radish, potato ; int main() vectorvegetables my_diet(100); vectorvegetables::iterator pos; vegetables veg; multisetvegetables, greatervegetables v_food; multisetvegetables, greatervegetables::iterator vpos; for (pos = my_diet.begin(); pos = my_diet.end(); ++pos) pos = static_castvegetables(rand() % 7); v_food.insert(pos); cout "How often a vegetable is eaten." endl; cout " broccoli, tomato, carrot, lettuce," "beet, radish, potato " endl; for (veg = broccoli; veg = potato; veg = static_castvegetables(veg + 1) ) cout v_food.count(veg) endl; cout "\nOffering of vegetables" endl; for (vpos = v_food.begin(); vpos = v_food.end(); ++vpos) cout vpos '\t'; cout endl; Ira Pohl’s C++ by Dissection 7.2 Containers 292 Dissection of stl_multiset Program include set // used for both set and multiset include vector using namespace std; enum vegetables broccoli, tomato, carrot, lettuce, beet, radish, potato ; This program generates a random diet of vegetables. It then uses the special properties of multiset to perform a count on how often each vegetable is eaten in our diet. The set elements are taken from the type vegetable. The set library file contains both the set and multi- set templates. vectorvegetables my_diet(100); vectorvegetables::iterator pos; vegetables veg; We store into the vector my_diet a selection of vegetables. The vector is declared to be size 100 and to have an associated iterator variable pos. The variable veg is of the enumerated type vegetables. multisetvegetables, greatervegetables v_food; multisetvegetables, greatervegetables ::iterator vpos; The multiset requires a comparison relationship that is used to order and efficiently retrieve elements of the set. Notice how an iterator gets declared. All the template arguments must be reproduced when declaring the related iterator. for (pos = my_diet.begin(); pos = my_diet.end(); ++pos) pos = static_castvegetables(rand() % 7); v_food.insert(pos); We randomly generate the seven possible vegetables. These values are inserted into both a vector my_diet and a multiset v_food. for (veg = broccoli; veg = potato; veg = static_castvegetables(veg + 1) ) cout v_food.count(veg) endl; The count() method of a multiset prints the count for each value the multiset stores. Thus, v_food.count(broccoli) tells us how many times we eat broccoli.Ira Pohl’s C++ by Dissection 7.2 Containers 293 7.2.3 Container Adaptors Container adaptor classes modify existing containers to produce various public behav- iors based on an existing implementation. Three provided container adaptors are stack, queue, and priority_queue. The stack can be adapted from vector, list, and deque and needs an implementation that supports back, push_back, and pop_back operations. From these underlying operations and representations, the stack adaptor template produces the equivalent standard stack container with operations for pop and push. The stack is a last-in-first-out data structure. The queue can be adapted from list or deque and needs an implementation that sup- ports empty, size, front, back, push_back and pop_front operations. From these underlying operations and representations, the queue adaptor template produces the equivalent standard queue container with operations for pop and push. The queue is a first-in-first-out data structure. The priority_queue is a queue that has values accessible in an order decided by a comparison operation. It can be adapted from vector or deque and needs an imple- mentation that supports empty, size, push_back, pop_back, and front operations. It also needs a comparison function object , and its underlying container must support random-access iteration. We adapt the stack from an underlying vector implementation. Notice that the STL ADTs replace our individually designed implementations of these types. The stack, vec- tor, and string libraries are required. Well, I did bring the heater, but I forgot the plug adapter In file stl_stack.cpp // Adapt a stack from a vector include iostream include stack include vector include string using namespace std;Ira Pohl’s C++ by Dissection 7.2 Containers 294 int main() stackstring, vectorstring str_stack; string quote3 = "The wheel that squeaks the loudest\n", "Is the one that gets the grease\n", "Josh Billings\n" ; for (int i = 0; i 3; ++i) str_stack.push(quotei); while (str_stack.empty()) cout str_stack.top(); str_stack.pop(); The output from this program is Josh Billings Is the one that gets the grease The wheel that squeaks the loudest Dissection of stl_stack Program int main() stackstring, vectorstring str_stack; The stack uses an underlying representation. In this case, it uses a vector. In effect, it is a facade for the vector implementation that restricts the use of vector to a last-in-first-out data structure, namely, the stack. The template’s first argument is the type stored in the stack, in this case, a string. The second argument is the stack’s imple- mentation. for (int i = 0; i 3; ++i) str_stack.push(quotei); The basic operation is a push onto the stack. Notice how the three strings are lines from a common adage. After being pushed onto the stack, they have the last line on the top of the stack.Ira Pohl’s C++ by Dissection 7.2 Containers 295 while (str_stack.empty()) cout str_stack.top(); str_stack.pop(); The top of the stack is printed. Then the stack element is popped. This continues until the stack is empty. This results in the adage printed line-by-line in reverse order. Notice how push(), pop(), empty() and top() are all standard methods for the stack container. Special functions exist for adaptor classes, as is shown inTable 7.9 through Table 7.11. Table 7.9 STL Adapted stack Functions void push(const value_type& Places v on stack v) void pop() Removes top element of stack value_type& top() const Returns top element of stack bool empty() const Returns true if stack is empty size_type size() const Returns number of elements in stack operator== and operator Equality and lexicographically less than Table 7.10 STL Adapted queue Functions void push(const value_type& v) Places v on end of queue void pop() Removes front element of queue value_type& front() const Returns front element of queue value_type& back() const Returns back element of queue bool empty() const Returns true if queue is empty size_type size() const Returns number of elements in queue operator== and operator Equality and lexicographically less than Table 7.11 STL Adapted priority_queue Functions void push(const value_type& v) Places v in priority_queue void pop() Removes top element of priority_queue value_type& top() const Returns top element of priority_queue bool empty() const Checks for priority_queue empty size_type size() const Shows number of elements in priority_queueIra Pohl’s C++ by Dissection 7.3 Iterators 296 In the minimal description in the table, the use of the equality operator or less-than operator causes the entire contents of two stacks to be compared for equality or less- than, respectively. The less-than is lexicographic, meaning the first elements are com- pared, and that continues in sequence, element pair by element pair, until a less-than is determined. Check your vendor’s product for specific system-dependent implementa- tions. In general, it is best to stay with the standard. This avoids locking you into partic- ular products. 7.3 7.3 Iterators Navigation over containers is by iterator. As seen in our earlier examples, iterators should be thought of as an enhanced pointer type. Here is a simple example of iterator and pointer use: In file stl_iterator.cpp // Compare iterator and pointer traversal include iostream include set using namespace std; int main() int primes4 = 2, 3, 5, 7 , ptr = primes; setint, greaterint s; setint, greaterint :: const_iterator c_it; while (ptr = primes + 4) s.insert(ptr++); cout "The primes below 10 : " endl; for (c_it = s.begin(); c_it = s.end(); ++c_it) cout c_it '\t'; cout endl; The preceding program uses an iterator for a set container to output one-digit primes. Such an iterator needs to have the ability to increment and to be dereferenced. Notice how the iteration travels over a range from s.begin() until s.end(). This idiom is repeated throughout the examples found here. There are five iterator types: input, output, forward, bidirectional, and random-access. Not all iterator types may be available for a given container class. For example, random- access iterators are available for vectors but not for maps. Input iterators support equality operations, dereferencing, and increment. An iterator that satisfies these conditions can be used for one-pass algorithms that read values of a data structure in one direction. A special case of the input iterator is the istream_iterator.Ira Pohl’s C++ by Dissection 7.3 Iterators 297 Output iterators support dereferencing restricted to the left-hand side of assignment and increment. An iterator that satisfies these conditions can be used for one-pass algo- rithms that write values to a data structure in one direction. A special case of the output iterator is the ostream_iterator. Forward iterators support all input/output iterator operations, as well as unrestricted use of assignment. This allows position within a data structure to be retained from pass to pass. Therefore, general one-directional multipass algorithms can be written with forward iterators. Bidirectional iterators support all forward iterator operations as well as both the incre- ment and decrement operators. Therefore, general bidirectional multipass algorithms can be written with bidirectional iterators. Random-access iterators support all bidirectional iterator operations, as well as address arithmetic operations, such as indexing. Also, random-access iterators support compar- ison operations. Therefore, algorithms, such as quicksort, that require efficient ran- dom-access in linear time can be written with these iterators. Container classes and algorithms dictate the category of iterator available or needed; therefore, vector containers allow random-access iterators, but lists do not. Sorting generally requires a random-access iterator, but finding requires only an input iterator. 7.3.1 Iterators for istream and ostream An istream_iterator is derived from an input iterator to work specifically with read- ing from streams. An ostream_iterator is derived from an output iterator to work specifically with writing to streams. We write a program that prompts for five numbers, reads them, and computes their sum, with I/O using these iterators. The template for istream_iterator is instantiated with a type and some older compilers require instead type, distance. This distance is usually specified by ptrdiff_t. More recent STL implementations do not require the ptrdiff_t argument, as it is defaulted. As defined in cstddef or stddef, it is an integer type representing the difference between two pointer values. Both vector and iterator libraries are needed. In file stl_io.cpp // Use of istream_iterator and ostream_iterator include iterator include iostream include vector using namespace std;Ira Pohl’s C++ by Dissection 7.3 Iterators 298 int main() vectorint d(5); int i, sum; cout "enter 5 numbers" endl; istream_iteratorint in(cin); ostream_iteratorint out(cout, "\t"); sum = d0 = in; // input first value for (i = 1; i 5; ++i) di = ++in; // input consecutive values sum += di; for (i = 0; i 5; ++i) out = di; // output consecutive values cout "sum = " sum endl; Dissection of the stl_io Program vectorint d(5); The vector container is the workhorse of STL. If you only learn this one part of the library, you gain 90 percent of the benefit from using it. Here, we have a simple vector constructor that gets us five ele- ments. cout "enter 5 numbers endl; istream_iteratorint in(cin); The istream iterator in is constructed with the argument cin. This is, of course, the standard input stream, normally the keyboard. The iterator must input int values as specified by its template parameter. Some older compilers require the use of ptrdiff_t, which is a dis- tance type that the iterator uses to advance in getting a next element. It is the number of bytes each int requires for storage. If it is required, the istream_iterator statement is replaced by istream_iteratorint, ptrdiff_t in(cin); ostream_iteratorint out(cout, "\t") The ostream_iterator out is constructed with the output stream cout and the char delimiter \t. Thus, the tab character is issued to the stream cout after each int value is written. Recent implementa- tions of istream_iterator do not require the ptrdiff_t argument.Ira Pohl’s C++ by Dissection 7.3 Iterators 299 sum = d0 = in; // input first value for (i = 1; i 5; ++i) di = ++in; // input consecutive values sum += di; The iterator in is a pointerlike object. When dereferenced, it forces a next value to be fetched from the standard input stream. Here, we obtain five values and place them in an array while summing them. for (i = 0; i 5; ++i) out = di; // output consecutive values cout " sum = " sum endl; Here, we use the output iterator out to take values from the array d and print them to the standard output stream. These five values are spaced using the tab character. We could as well have used out = sum, but then we could have not commented the output with the string " sum = ". The output stream iterator is isomorphic to the input stream iterator. When a value is assigned to the iterator, it is written to the instantiated output stream, using operator . As seen in the preceding example, the output stream iterator must specify the asso- ciated output stream as a parameter to the constructor. An optional second parameter to the constructor is a string that is used as a separator between values. An ostream_iterator is derived from an output_iterator to work specifically with writing to streams. The ostream_iterator can be constructed with a char delimiter, in this case \t. Thus, the tab character is issued to the stream cout after each int value is written. In this program, the iterator out, when it is dereferenced, writes the assigned int value to cout: In file stl_o_iterator.cpp // Use of ostream_iterator iterator include iostream include iterator using namespace std; int main() int d5 = 2, 3, 5, 7, 11 ; // primes ostream_iteratorint out(cout, "\t"); for (int i = 0; i 5; ++i) out = di; cout endl;

Advise: Why You Wasting Money in Costly SEO Tools, Use World's Best Free SEO Tool Ubersuggest.