Programs often operate on large datasets. In such cases, it's convenient to package the discrete data items together so the program can move them around en masse, as a single entity. Computer scientists have designed numerous data structures, called container classes in C++ and collections in Java, for this purpose. A basket is a familiar metaphor for a data structure: At some point, there may be too many items for us to hold in our hands, but if we put them in a basket, we can hold many items by holding the basket's handle. Most data structures also organize the data they store and allow programs to access it in specific ways. Linear data structures (e.g., an ArrayList, a vector, or a string) organize their contents serially in a line, which makes sequential or linear access relatively easy.
Programmers use iterators to access the data or elements stored in containers. Each iterator object is tightly bound to a container object, allowing the program to access the elements one at a time while the iterator "remembers" the current access locations. In the case of string objects, iterators return the elements or characters in sequential order, beginning with either the first or last character. As an introductory example to iterators, the ipalnumber example solves the palindrome-number problem using string iterators.
The string class has eight member functions that create different kinds of iterators. Four of the functions (illustrated in the following figure) allow programs to change the string characters through the iterators, while four "constant" functions disallow change. In addition to the member functions, iterators overload or reuse several operators for navigation and character access.
| string Member Functions | |
|---|---|
begin() |
Returns an iterator that points to the first character in the string. When incremented, the iterator advances forward (in the English reading direction) one character to the right - accessing the string characters left to right. for (string::iterator i = s.begin(); i != s.end(); i++) |
end() |
Returns an iterator that points to a sentinel (red) one character beyond the last character. Having an iterator point to a sentinel after and outside the string makes it easy to use loops to process the string characters. |
rbegin() |
Returns an iterator that points to the last character in the string. When incremented, the iterator "advances" or moves from the last string character toward the first (in the reverse English reading direction), accessing the characters from right to left.
for (string::reverse_iterator r = s.rbegin(); r != s.rend(); r++) |
rend() |
Returns an iterator that points to a sentinel (red) one character before the beginning of the string. Having the iterator point to a sentinel before and outside the string makes it easy to use loops to process its characters in the reverse order. |
| Iterator Operators | |
* |
The dereference operator returns the character at the current iteration location. |
= |
The assignment operator assigns an iterator object to an iterator variable. |
== and != |
Tests two iterator objects for equality or inequality. |
++ |
The pre- and post-auto-increment operators. Advances the iterator to the next character: to the right for forward iterators, and to the left for reverse iterators. |
-- |
The pre- and post-auto-decrement operators. Reverses the iterator to the previous character: to the left for forward iterators, and to the right for reverse iterators. |
The previous section solved the palindrome-number problem by reversing the candidate string. As the string class doesn't provide a reverse function, the example created one. The following figures rewrite the reverse function to demonstrate forward and reverse iterators.
string reverse(string s)
{
string r;
string::reverse_iterator i = s.rbegin(); // (a)
while(i != s.rend()) // (b)
r += *i++; // (c)
//for (string::reverse_iterator i = s.rbegin(); i != s.rend(); i++) // (d)
// r += *i;
return r; // (e)
} |
|
++, has a higher precedence than the indirection operator, *, the post-increment operator "uses the current value and then increments." Therefore, the expression dereferences the iterator, getting the current character, then advances the iterator.
string reverse(string s)
{
string r;
string::iterator i = s.end(); // (a)
while(i != s.begin()) // (b)
r += *--i; // (c)
//for (char c : s) // (d)
// r = c + r;
return r; // (e)
} |
|
| View | Download | Comments |
|---|---|---|
| ipalnumber.cpp | ipalnumber.cpp | Demonstrates four ways of using iterators to reverse a string |