- Table of Contents
- Copyright
- About the Authors
- About the Contributors
- Acknowledgments
- Tell Us What You Think!
- Introduction
- How to Use This Book
- What You Need to Use This Book
- What's New in Visual C++ 6.0
- Contacting the Main Author
- Part I: Introduction
- Chapter 1. The Visual C++ 6.0 Environment
- Part II: MFC Programming
- Chapter 2. MFC Class Library Overview
- Chapter 3. MFC Message Handling Mechanism
- Chapter 4. The Document View Architecture
- Chapter 5. Creating and Using Dialog Boxes
- Chapter 6. Working with Device Contexts and GDI Objects
- Chapter 7. Creating and Using Property Sheets
- Chapter 8. Working with the File System
- Chapter 9. Using Serialization with File and Archive Objects
- Part III: Internet Programming with MFC
- Chapter 10. MFC and the Internet Server API (ISAPI)
- Chapter 11. The WinInet API
- Chapter 12. MFC HTML Support
- Part IV: Advanced Programming Topics
- Chapter 13. Using the Standard C++ Library
- Chapter 14. Error Detection and Exception Handling Techniques
- Chapter 15. Debugging and Profiling Strategies
- Chapter 16. Multithreading
- Chapter 17. Using Scripting and Other Tools to Automate the Visual C++ IDE
- Part V: Database Programming
- Chapter 18. Creating Custom AppWizards
- Chapter 19. Database Overview
- Chapter 20. ODBC Programming
- Chapter 21. MFC Database Classes
- Chapter 22. Using OLE DB
- Chapter 23. Programming with ADO
- Part VI: MFC Support for COM and ActiveX
- Chapter 24. Overview of COM and Active Technologies
- Chapter 25. Active Documents
- Chapter 26. Active Containers
- Chapter 27. Active Servers
- Chapter 28. ActiveX Controls
- Part VII: Using the Active Template Library
- Chapter 29. ATL Architecture
- Chapter 30. Creating COM Objects Using ATL
- Chapter 31. Creating ActiveX Controls Using ATL
- Chapter 32. Using ATL to Create MTS and COM+ Components
- Part VIII: Finishing Touches
- Chapter 33. Adding Windows Help
- Part IX: Appendix
Algorithms
STL algorithms are functions that perform operations to the items in one or more containers. These algorithm functions are standalone template functions. Because they are so general, they can be applied to ordinary C++ arrays or containers you create yourself.
Algorithms are written to work on iterators, not components. They are parameterized by iterator types and unattached from the containers they operate on. Thus, all containers of the same iterator category can use the same algorithms. Table 13.5 describes the available algorithms.
Table 13.5. STL Algorithms
| Algorithm | Description |
| adjacent_find | Locates consecutive pairs of matching elements. A predicate version of the function exists. |
| binary_search | Returns True if a given value resides within a given range. A predicate version of this function exists. |
| copy | Copies objects from one range to another. |
| copy_backward | Copies objects from one range to another, with the destination range receiving the elements in reverse order. |
| count | Returns the number of occurrences of a given value within a sequence. |
| count_if | Returns the number of elements that satisfy a predicate. |
| equal | Returns True if objects in two ranges are equal. A predicate version of this function exists. |
| equal_range | Returns a pair that can be inserted in a sequence, and then preserves the ordering of the sequence. A predicate version of this function exists. |
| fill | Fills all objects within a range of a given value. |
| fill_n | Fills objects to each n in a range from the first object to the nth object. |
| find | Returns an iterator to the first object matching a given value. |
| find_end | Finds the last occurrence of a subsequence. |
| find_first_of | Finds the first element equal to a given value. A predicate version of this function exists. |
| find_if | Returns an iterator to the first object for which the predicate equals True. |
| for_each | Applies a designated operation to each element in a container. It cannot change the contents of each container. |
| generate | Fills all objects within a range with a value generated by the function. |
| generate_n | Fills all objects from the first element to the nth element within a range with a value generated by the function. |
| includes | Returns True if every object of one range is in every object of another range. A predicate version of this function exists. |
| inplace_merge | Merges two sorted subsequences into a single sorted sequence. A predicate version of this function exists. |
| iter_swap | Swaps to elements by their two iterators. |
| lexicographical_compare | Returns True if the sequence of the first range is lexicographically less than the sequence of the second range. |
| lower_bound | Returns the lower bound of a given range. |
| make_heap | Creates a heap out of a given range of values. A predicate exists for this function. |
| max | Returns the largest value of two given objects. |
| max_element | Returns the iterator of the largest element of two given objects. A predicate exists for this function. |
| merge | Merges two ranges into a third range. A predicate version of the function exists. |
| min | Returns the smallest value of two given objects. |
| min_element | Returns the iterator of the smallest element of two given objects. A predicate exists for this function. |
| mismatch | Returns the first pair of corresponding objects that are not equal. A predicate version of this function exists. |
| next_permutation | Changes the order of a sequence to the next lexicographic permutation. |
| nth_element | Partitions elements in a sequence by the given nth element. |
| partial_sort | Sorts only the middle to the beginning of a range. The remaining elements of the range (middle to end) remain in an undefined order. |
| partial_sort_copy | Sorts only the middle to the beginning of a range and copies the resulting partial sort to another sequence. |
| partition | Returns the first element for which the predicate returns False. This algorithm arranges elements in a range, with the elements that returned True for the predicate at the beginning of the sequence. |
| pop_heap | Removes an element from the heap. |
| prev_permutation | Changes the order of a sequence to the previous lexicographic permutation. |
| push_heap | Inserts an element into the heap. |
| random_shuffle | Shuffles the elements in random order. A predicate function exists. |
| remove | Removes all elements from a sequence that match a given value. |
| remove_copy | Copies the elements of a sequence to another sequence, removing any elements that match the given value. |
| remove_copy_if | Copies the elements of a sequence to another sequence, removing any elements that satisfy a predicate. |
| remove_if | Removes all elements of a sequence that satisfy a predicate. |
| replace | Replaces all elements of a sequence that match a given value to a new given value. |
| replace_copy | Copies all elements of a sequence that match a given value to a new given value |
| replace_copy_if | Replaces all elements from a sequence that satisfy a predicate with a given value. |
| replace_if | Replaces all elements of a sequence that satisfy a predicate to a new given value. |
| reverse | Reverses the order of objects in a range. |
| reverse_copy | Copies one range to another, reversing the order. |
| rotate | Rotates the items in a sequence by n positions. |
| rotate_copy | Rotates the items in a sequence by n positions, and copies the results to another sequence of the same size. |
| search | Returns the start position of the match if the second range exists in the first. A predicate function exists. |
| search_n | Returns the start position of the match if the second range exists in the first to the nth object. A predicate function exists. |
| set_difference | Determines differences of elements from two ranges, with the results sorted. A predicate version of this function exists, determining the order of the results. |
| set_intersection | Determines the intersection of elements from two ranges, with the results sorted. A predicate version of this function exists, determining the order of the results. |
| set_symmetric_difference | Determines the symmetric difference of elements from two ranges, with the results sorted. A predicate version of this function exists, determining the order of the results. |
| set_union | Determines the union of elements from two ranges, with the results sorted. A predicate version of this function exists, determining the order of the results. |
| sort | Sorts elements within a range. A predicate version of this function exists. |
| sort_heap | Sorts elements within a heap. A predicate version of this function exists. |
| stable_partition | Partitions a sequence into two groups. The first group is the group of elements that satisfy the predicate. The second group consists of the elements that did not satisfy the predicate. |
| stable_sort | Sorts the elements in a sequence, preserving the relative order for equal elements. |
| swap | Swaps two elements. |
| swap_ranges | Swaps two elements from two ranges. |
| transform | Transforms objects from one range into new objects in a second range. |
| unique | Removes all objects but the first one of equal value. A predicate version of this function exists. |
| unique_copy | Copies objects from one range to another, but only ones of unique values. |
| upper_bound | Returns the lower bound of a given range. |
After examining these functions, you may have noticed that the functions mention the term predicate, especially the functions ending in _if.
A predicate is simply another parameter that is included in the calling of the function. A predicate is a power option simply because it enables the developer to write a separate function. This function is applied against every object in the range, and the results are processed as the _if algorithm dictates. The replace_if example later in this chapter demonstrates the use of a predicate.
A few of the most common algorithms are covered in the following sections.
count()
The count() algorithm counts the number of elements that contain a particular value. The function call requires the beginning and ending ranges of the search, plus the value that is to be matched. The following code shows an example:
Example 13.5. Count Example
// Count program example
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
typedef vector<int> INTVECTOR;
void main(){
int total_count = 0 ;
INTVECTOR MyVector;
// MyVector will contain [ 1, 2, 2, 3 ]
MyVector.push_back(1) ;
MyVector.push_back(2) ;
MyVector.push_back(2) ;
MyVector.push_back(3) ;
//Get total count of 1s
total_count = count(MyVector.begin(), MyVector.end(), 1);
cout << "Total Count of 1s = " << total_count << endl;
//Get total count of 1s
total_count = count(MyVector.begin(), MyVector.end(), 2);
cout << "Total Count of 2s = " << total_count << endl;
//Get total count of 3s
total_count = count(MyVector.begin(), MyVector.end(), 3);
cout << "Total Count of 3s = " << total_count << endl;
} //END
The output of this program follows:
Total Count of 1s = 1 Total Count of 2s = 2 Total Count of 3s = 1
find()
The find() algorithm does pretty much what it says, returning the position of the first element it finds that matches the desired value. The following listing is an example of finding values using vectors:
Example 13.6. Find Example
// Find program example
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
typedef vector<int> INTVECTOR;
void main(){
int *location ; // stores the position of the first
// matching element.
INTVECTOR MyVector;
// MyVector will contain [ 8, 6, 7, 5 ]
MyVector.push_back(8) ;
MyVector.push_back(6) ;
MyVector.push_back(7) ;
MyVector.push_back(5) ;
//Get Position of number 8 - Should return 0
location = find (MyVector.begin(), MyVector.end(), 8);
cout << "Position of 8 is " << location - MyVector.end() + MyVector.size() << endl;
//Get Position of number 6 - Should return 1
location = find (MyVector.begin(), MyVector.end(), 6);
cout << "Position of 6 is " << location - MyVector.end() + MyVector.size() << endl;
//Get Position of number 7 - Should return 2
location = find (MyVector.begin(), MyVector.end(), 7);
cout << "Position of 7 is " << location - MyVector.end() + MyVector.size() << endl;
//Get Position of number 5 - Should return 3
location = find (MyVector.begin(), MyVector.end(), 5);
cout << "Position of 5 is " << location - MyVector.end()x + MyVector.size() << endl;
} //END
The output of this program follows:
Position of 8 is 0 Position of 6 is 1 Position of 7 is 2 Position of 5 is 3
Notice how MyVector.size was used to quickly get the number of elements from the container.
for_each()
The for_each() algorithm enables you to use the values of every item of an object in a relatively easy way. The actual object values themselves cannot be changed, but the resulting values can be obtained for other use. The function that accesses their values and works with them is supplied by the developer.
The following listing takes a list of vector numbers and calls a function to display their value doubled:
Example 13.7. For Each Example
// for_each program example
//
// Functions:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
typedef vector<int> INTVECTOR;
// Function to print out vector values
void unchanged_value(int vector_value)
{
cout << vector_value << endl;
}
// Function to print out vector values * 2
void double_value(int vector_value)
{
cout << vector_value * 2 << endl;
}
//Main
void main(){
INTVECTOR Numbers(5) ; //Declare 5 vectors of integer
//Set values of Numbers vectors
Numbers[0] = 0;
Numbers[1] = 1;
Numbers[2] = 2;
Numbers[3] = 3;
Numbers[4] = 4;
cout << "Numbers unchanged:" << endl;
for_each(Numbers.begin(), Numbers.end(), unchanged_value);
cout << endl;
cout << "Numbers doubled:" << endl;
for_each(Numbers.begin(), Numbers.end(), double_value) ;
} //END
The output of this program follows:
Numbers unchanged: 0 1 2 3 4 Numbers doubled: 0 2 4 6 8
merge()
The merge() algorithm takes two objects and merges their values into a third object. To do this successfully with vectors, the destination container must have its elements initialized. The following listing merges two number vectors into a destination vector and displays the results:
Example 13.8. Merge Example
// merge program example
//
// Functions:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
typedef vector<int> INTVECTOR;
//Main
void main(){
INTVECTOR Set1(6) ; //Declare 5 vectors of integer
INTVECTOR Set2(3) ; //Declare 5 vectors of integer
INTVECTOR Destination(9) ; //Declare 8 vectors of integer
// Iterator is used to loop through the vector.
INTVECTOR::iterator MyIterator;
//Set values of Set1
Set1[0] = 0;
Set1[1] = 1;
Set1[2] = 2;
Set1[3] = 4;
Set1[4] = 6;
Set1[5] = 8;
//Set values of Set2
Set2[0] = 1;
Set2[1] = 3;
Set2[2] = 6;
// Initialize vector Destination
for(int i = 0; i < 9; i++)
Destination[i] = 0;
merge(Set1.begin(), Set1.end(), Set2.begin(), Set2.end(), Destination.begin());
// print content of NumbersDeque
cout << "Merged Results = { " ;
for(MyIterator = Destination.begin();
MyIterator != Destination.end();
MyIterator++)
cout << *MyIterator << " " ; cout << " }\n" << endl ;
} //END
The output of this program follows:
Merged Results = { 0 1 1 2 3 4 6 6 8 }
sort()
The sort() algorithm simply sorts a set of objects. The following listing displays the code to achieve the results of a sorted numeric vector:
Example 13.9. Sort Example
//Sort program example
//
// Functions:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
typedef vector<int> INTVECTOR;
//Main
void main(){
INTVECTOR SortSet(7 ) ; //Declare 7 vectors of integer
// Iterator is used to loop through the vector.
INTVECTOR::iterator MyIterator;
//Set values of SortSet
SortSet[0] = 10;
SortSet[1] = -1;
SortSet[2] = 6;
SortSet[3] = 0;
SortSet[4] = -10;
SortSet[5] = 1;
SortSet[6] = -6;
sort(SortSet.begin(), SortSet.end());
// print content of SortSet
cout << "Sorted Results = { " ;
for(MyIterator = SortSet.begin();
MyIterator != SortSet.end();
MyIterator++)
cout << *MyIterator << " " ; cout << " }\n" << endl ;
} //END
The output of this program follows:
Sorted Results = { -10 -6 -1 0 1 6 10 }
swap()
The swap() algorithm swaps two elements of a set. All that is needed are the two positions of the elements. The following listing demonstrates the swap with a numeric vector:
Example 13.10. Swap Example
//swap program example
//
// Functions:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
typedef vector<int> INTVECTOR;
//Main
void main(){
INTVECTOR SwapSet(5) ; //Declare 5 vectors of integer
// Iterator is used to loop through the vector.
INTVECTOR::iterator MyIterator;
//Set values of SwapSet
SwapSet[0] = 1111;
SwapSet[1] = 222;
SwapSet[2] = 555;
SwapSet[3] = 222;
SwapSet[4] = 6666;
// print content of SwapSet
cout << "Contents before Swap = { " ;
for(MyIterator = SwapSet.begin();
MyIterator != SwapSet.end();
MyIterator++)
cout << *MyIterator << " " ; cout << " }\n" << endl ;
swap(SwapSet[0], SwapSet[4]);
// print content of SwapSet
cout << "Contents after Swap = { " ;
for(MyIterator = SwapSet.begin();
MyIterator != SwapSet.end();
MyIterator++)
cout << *MyIterator << " " ; cout << " }\n" << endl ;
} //END
The output of this program follows:
Contents before Swap = { 1111 222 555 222 6666 }
Contents after Swap = { 6666 222 555 222 1111 }
Using _if: The replace_if () Algorithm
The replace_if function is a special type of algorithm. Whenever you see an _if at the end of an algorithm, it signals that it can use a function. This extra function is called a predicate.
The listing below demonstrates the use of replace_if function:
Example 13.11. Replace If Example
//replace_if program example
//
// Functions:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std ;
typedef vector<int> INTVECTOR;
//Main
void main(){
INTVECTOR ReplaceSet(7) ; //Declare 7 vectors of integer
// Iterator is used to loop through the vector.
INTVECTOR::iterator MyIterator;
//Set values of ReplaceSet
ReplaceSet[0] = 5;
ReplaceSet[1] = 7;
ReplaceSet[2] = 4;
ReplaceSet[3] = 3;
ReplaceSet[4] = 6;
ReplaceSet[5] = 1;
ReplaceSet[6] = 0;
// print content of ReplaceSet
cout << "Contents before Replace_If = { " ;
for(MyIterator = ReplaceSet.begin();
MyIterator != ReplaceSet.end();
MyIterator++)
cout << *MyIterator << " " ; cout << " }\n" << endl ;
replace_if(ReplaceSet.begin(),ReplaceSet.end(),bind2nd(less<int>(), 5), 0 ) ;
// print content of ReplaceSet
cout << "Contents after Replace_If = { " ;
for(MyIterator = ReplaceSet.begin();
MyIterator != ReplaceSet.end();
MyIterator++)
cout << *MyIterator << " " ; cout << " }\n" << endl ;
} //END
The output of this program follows:
Contents before Replace_If = { 5 7 4 3 6 1 0 }
Contents after Replace_If = { 5 7 0 0 6 0 0 }
The previous examples should get you started on how to use the algorithms with the STL. As you can see from Table 13.5, many more algorithms exist.
Reverse Iterator
In this section, you will examine the reverse iterator. This iterator gives you the capability to iterate through a container backward. You might think that to iterate backward, all you would have to do is perform the following code:
// print vectors in reverse order
cout << "Contents reverse in order:" << endl;
for(MyIterator = SetToReverse.end();
MyIterator != SetToReverse.begin();
MyIterator—)
cout << *MyIterator << endl;
This code will not work with a forward iterator. Forward iterators only support the ++ operator and can only progress forward.
Declaring a reverse iterator looks like this:
INTVECTOR::reverse_iterator MyReverseIterator;
You also must use the member functions rbegin() and rend() when using a reverse iterator. You cannot use these functions with a forward iterator. When using rbegin(), the reverse iterator is starting at the end of the container. The iterator also must be incremented.
The following example shows a forward iterator and a reverse iterator operating on the same set of vectors:
//reverse iterator program example
//
// Functions:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std ;
typedef vector<int> INTVECTOR;
//Main
void main(){
INTVECTOR SetToReverse(4) ; //Declare 4 vectors of integer
// Iterator is used to loop through the vector.
INTVECTOR::iterator MyIterator;
INTVECTOR::reverse_iterator MyReverseIterator;
//Set values of SetToReverse
SetToReverse[0] = 0;
SetToReverse[1] = 1;
SetToReverse[2] = 2;
SetToReverse[3] = 3;
// print vectors in forward order
cout << "Contents iterated in order:" << endl;
for(MyIterator = SetToReverse.begin();
MyIterator != SetToReverse.end();
MyIterator++)
cout << *MyIterator << endl;
cout << endl ;
// print vectors in reverse order
cout << "Contents iterated in reverse:" << endl;
for(MyReverseIterator = SetToReverse.rbegin();
MyReverseIterator != SetToReverse.rend();
MyReverseIterator++)
cout << *MyReverseIterator << endl;
cout << endl ;
} //END
The output of this program follows:
Contents iterated in order: 0 1 2 3 Contents iterated in reverse: 3 2 1 0
Remember: Even though the reverse iterator is starting at the end of the container, use ++ to iterate through it backward.
Using STL with MFC and ATL | Next Section

Account Sign In
View your cart