|
 |
 |
[an error occurred while processing this directive]
The program creates the list of names, sorts it, and displays it onscreen. The first output should show the names in the following order:
Andrew
Andrew
Andrew
Margaret
Martin
Peter
Then the program counts the number of Andrews in the list and shows
There are 3 Andrews in the list
The next step is to remove duplicates and to add James before Margaret. The output should show the new list:
Andrew
James
Margaret
Martin
Peter
Finally, check for the existence of the name Peter in the list. To do this, execute the NameExists method twice: the first time with the name Peter starting with a capital P, and the second time with the name peter starting with a small p. The output should show the line with the name only once:
Peter
Comments
Developing classes using STL is not a straightforward process. You have to decide the appropriate type of the container and whether to use algorithms or member functions. Sequential containers have some of the necessary functions. The selection of algorithms should be done thoroughly in order to allow extension of the class methods. The next How-To shows how you can extend the functionality of the class using STL predicates.
9.2 Use predicates with sequence operations?
Problem
Sequence operations such as find, count, and unique use a comparison based on the == operator. The == operator is defined for the data type that is used in the container and it often does not cover my needs. I want to be able to find elements that satisfy certain criteria. For example, I want to find the elements that end with er, or count all elements that start with M. How do I use other functions than == operator with the sequential algorithms?
Technique
To extend the functionality of the find, count, and unique algorithms, specify certain predicates that will be used in the comparison instead of the equality operator (==). Predicates are unary functions that return a result representing true or false. The result should be convertible to the bool data type. You are going to create a few more methods using predicates for the class that maintains names for the text processing.
Steps
- 1. Create a method that uses a predicate with the count algorithm
In this How-To, you will learn to create a new method that counts all names in the list that start with the letters from A to L. One possible reason for doing this is to separate the set of names when it is becoming too big. To count the names, use the count_if algorithm that allows you to specify a function for selecting certain data.
The function should be a predicateÑthat is, a unary function whose result represents the truth or falsehood of some condition. In this example, the function will return true if the name starts with a letter from A to L. The function will be used in the new CountNamesAL method that is added to the persname class. The following code is added to the class definition that will be now in the file persnam1.h:
// Count names that start with A to L
int CountNamesAL(void);
The function definition is also added to the class and located in the file persnam1.cpp.
// Count names that start with A to L
int persname::CountNamesAL(void)
{
return count_if (PName.begin(), PName.end(),
bind2nd(less<string>(),M));
}
The count_if algorithm uses a new function bind2nd. It converts a binary function to a unary predicate. The result of the
bind2nd(less<string>(),M)
is true if the element is lexicographically smaller than M. In other words, it will return true if the word starts with a letter from A to L.
Microsoft Visual C++ 5 was used to test this example. If you use Borland C++ 5, you must change the line with the return statement in the CountNamesAL function to
int iCount;
count_if (PName.begin(), PName.end(), bind2nd
⇒(less<string>(),M), iCount);
return iCount;
To test this algorithm, the main program was modified slightly.
// This is the program to test
// persname class
// pn1test.cpp
#include <iostream>
#include persnam1.h
int main()
{
persname Names;
Names.Add (Andrew);
Names.Add (Peter);
Names.Add (John);
Names.Add (Andrew);
Names.Add (Andrew);
Names.Add (Margaret);
Names.Sort();
Names.DisplayAll();
cout << endl;
// The following code replaces the code in the previous example
cout << There are << Names.CountNamesAL() <<
names starting from A to L << endl;
return 0;
}
If you run the program, the output will be
There are 4 names starting from A to L
- 2. Create a method that uses a predicate with the find algorithm
You can use predicates with other algorithms such as find. The extended version of this algorithm also has the suffix _if. Lets write the function to find the first occurrence of the word that starts with a letter greater than I.
The new member function of the persname class is called FindNameJ. The FindNameJ declaration and definition follow:
// Find the first name that start with J
string FindNameJ(void);
and
string persname::FindNameJ(void)
{
list <string>::iterator i;
i = find_if(PName.begin(), PName.end(),
bind2nd(greater<string>(),IZZZ));
return *i;
}
To start the search from the letter J, the code uses a trick. All words starting with J to Z are described as greater than IZZZ.
|