![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
[an error occurred while processing this directive]
Now that you have created a const_iterator pointing at the first element of str, you can use it to access all the other elements thereof. For that purpose, use a while loop. The loop checks in each iteration whether you have reached the last element of the container by invoking the member function string::end(): while ( p != str.end()) The loop body consists of two operations. First, the current element is displayed. As you can see, in order to access the element the iterator must be dereferenced, as you would dereference an ordinary pointer. The trick here is that all STL iterators overload operator *, which enables you to use pointer syntax. Nifty, isnt it? cout<< *p <<endl; The following statement in the loop body increments p using the overloaded ++ operator. The effect of which, you can guess, is to move p to the next element of str. p++; Of course, you could have combined these separate operations in a single statement, like this: cout<< *p++ <<endl; but its less readable. Comments When you want to modify elements of a container, you need to use non-const iterators. The following example demonstrates how it is actually done. In the following program, use list as your container. The STL list class template is defined in the header <list>. The specialization list<double> is used to instantiate an object named salaries. Next, three elements of type double are inserted to salaries. Imagine salaries represents a payroll. Now suppose you want to raise by 15% the salaries of all employees. In order to do that, you need to traverse through the elements currently stored in salaries and modify each one. For that purpose, use a plain iterator. #include <iostream> #include <list> using namespace std; void main() { list <double> salaries; // a payroll salaries.push_back(5000.00); salaries.push_back(4500.00); salaries.push_back(1333.33); list<double>::iterator p = salaries.begin(); //point to the first element while ( p != salaries.end()) { cout<<salary before a raise: << *p <<endl; *p = *p * 1.15; //add 15 percent to the existing rate cout<<salary after a 15% raise: << *p <<endl; p++; //proceed to the next salary } }// main Our first step is to create a suitable iterator. This iterator is intended to modify the elements; therefore, you have to use an ordinary iterator rather than a const iterator. Our iterator is defined in the following line: list<double>::iterator p = salaries.begin(); p is initialized with the address of the first element in the list, which is the value returned from begin(). Next, define a while loop that traverses through the elements of salaries. while ( p != salaries.end()) { cout<<salary before a raise: << *p <<endl; *p = *p * 1.15; cout<<salary after a 15% raise: << *p <<endl; p++; The first statement inside the loop displays the element to which p currently points. Next, change the element just displayed. Increase the element by 15%. Remember that you have to dereference the iterator to obtain the element. After changing the element, display it once more. Finally, increment the iterator to point to the next element in salaries. The loop is reiterated as long as p does not reach the last element of salaries. You might have noticed something suspicious here: The loop is reiterated as long as the final element hasnt been reached. Still, when this program is run you will notice that all of the elements in salaries have been modifiedincluding the last one. How can it be? Here is the secret. The member function end() does not really return the position of the last element, but one position past the last element. Surprising as it might seem, you can find similar behavior in C strings. A null character is always appended one position past the last position of the char array. The null character marks the boundary of the string. A similar trick is applied in STL containers. Every container automatically appends another element one position after the last one. This special element is equivalent to the null character in C strings, or the EOF marker at the end of a file. Thus, our iterator p does reach the final element in the loop. As noted before, besides the incurred performance penalty, reallocation has another undesirable side effect. When a container reallocates its elements, their addresses change correspondingly, invalidating existing iterators. Therefore, you have to reassign the iterators values by invoking the appropriate member function once more. Using an invalid iterator yields undefined behaviorexactly as if you were using a pointer with the address of a deleted object. Because the reallocation process is automatic, the programmer has no way of knowing when it takes place, and when an iterator becomes invalid. By forestalling reallocation, not only do you get enhanced performance, but you also eliminate the chance of dangling iterators. 7.7 Implement a queue data model?Problem I need a container that implements the first-in-first-out (FIFO) data model. FIFO is a queue of elements. As opposed to a stack, the first element inserted into a queue is located at the topmost position, whereas the last element inserted is located at the bottom. When a pop operation is performed, the element at the topmost position (which was the first to be inserted) is removed from the queue, and the element located one position lower is now at the top. Remember that the terms queue and FIFO mean the same thing, so they are used here interchangeably. Technique In this example, you will see how to use STLs queue container to implement a FIFO data model.
|
![]() |
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.
|