上一篇文章也讲过,find()函数只能处理简单类型的内容,也就是缺省类型,如果你想用一个自定义类型的数据作为查找依据则会出错!这里将讲述另外一个函数find_if()的用法

这是find()的一个更强大的版本。这个例子演示了find_if(),它接收一个函数对象的参数作为参数, 并使用它来做更复杂的评价对象是否和给出的查找条件相付。
假设我们的list中有一些按年代排列的包含了事件和日期的记录。我们希望找出发生在1997年的事件。

代码如下:

 

[c-sharp] view plaincopy
 
  1. //----------------------------------------------------------------------------------------  
  2. //      Desc:       STL_find_if()_How to find things in an STL list MkII  
  3. //      Author:     pigfly  
  4. //      Data:       2010.12.01  
  5. //      Copyright (C) 2010 pigfly  
  6. //----------------------------------------------------------------------------------------  
  7.  
  8. #include <iostream>  
  9. #include <string>  
  10. #include <list>  
  11. #include <algorithm>  
  12. using namespace std;  
  13.   
  14. class EventIsIn1997 {  
  15. public:   
  16.     bool operator () (string& EventRecord) {  
  17.         // year field is at position 12 for 4 characters in EventRecord  
  18.         return EventRecord.substr(11,4)=="1997";  
  19.         //return this->substr(11,4)=="1997"  
  20.     }  
  21. };  
  22.   
  23. int main (void) {  
  24.     list<string> Events;  
  25.   
  26.     // string positions 0123456789012345678901234567890123456789012345  
  27.     Events.push_back("07 January 1995 Draft plan of house prepared");  
  28.     Events.push_back("07 February 1996 Detailed plan of house prepared");  
  29.     Events.push_back("10 January 1997 Client agrees to job");  
  30.     Events.push_back("15 January 1997 Builder starts work on bedroom");  
  31.     Events.push_back("30 April 1997 Builder finishes work");  
  32.   
  33.     list<string>::iterator EventIterator = find_if (Events.begin(), Events.end(), EventIsIn1997());  
  34.   
  35.     // find_if completes the first time EventIsIn1997()() returns true  
  36.     // for any object. It returns an iterator to that object which we  
  37.     // can dereference to get the object, or if EventIsIn1997()() never  
  38.     // returned true, find_if returns end()  
  39.     if (EventIterator==Events.end()) {  
  40.         cout << "Event not found in list" << endl;  
  41.     }  
  42.     else {  
  43.         cout << *EventIterator << endl;  
  44.     }  
  45. }  

 

输出:

10 January 1997 Client agrees to job

这里请注意,find_if()的第三个参数是EventIsIn1997(),它是个仿函数,接收一个string对象,在运算符()的内部定义我所要的查找条件,本例的查找条件是:EventRecord.substr(11,4)=="1997",注意,这里的仿函数返回类型必须是bool类型,这客观反应在find_if()函数查找过程中的是否匹配!

下面我们在看看,数据类型是自定义的结构体的查找过程:

代码:

 

[c-sharp] view plaincopy
 
  1. //----------------------------------------------------------------------------------------  
  2. //      Desc:       STL_find_if() used in vector container, struct data  
  3. //      Author:     pigfly  
  4. //      Data:       2010.12.01  
  5. //      Copyright (C) 2010 pigfly  
  6. //----------------------------------------------------------------------------------------  
  7.  
  8. #include <iostream>  
  9. #include <vector>  
  10. #include <string>  
  11. #include <algorithm>  
  12. using namespace std;  
  13.   
  14. struct value_t  
  15. {  
  16.     int a;  
  17.     int b;  
  18. };  
  19.   
  20. class vector_finder  
  21. {  
  22. public:  
  23.     vector_finder( const int a, const int b ) :m_v_a(a),m_v_b(b){}  
  24.     bool operator ()( vector<struct value_t>::value_type &value)  
  25.     {  
  26.         return (value.a==m_v_a)&&(value.b = m_v_b);  
  27.     }  
  28. private:  
  29.     int m_v_a;  
  30.     int m_v_b;  
  31. };  
  32.   
  33. int main()  
  34. {  
  35.     vector<value_t> my_vector;  
  36.     value_t my_value;  
  37.   
  38.     my_value.a = 11; my_value.b = 1001;  
  39.     my_vector.push_back(my_value);  
  40.   
  41.     my_value.a = 12; my_value.b = 1002;  
  42.     my_vector.push_back(my_value);  
  43.   
  44.     my_value.a = 13; my_value.b = 1003;  
  45.     my_vector.push_back(my_value);  
  46.   
  47.     my_value.a = 14; my_value.b = 1004;  
  48.     my_vector.push_back(my_value);  
  49.   
  50.     vector<value_t>::iterator it = find_if( my_vector.begin(), my_vector.end(), vector_finder(13,1003));  
  51.     if( it == my_vector.end() )  
  52.         cout<<"not found!"<<endl;  
  53.     else  
  54.         cout<<"found value a:"<<(*it).a <<", b:"<<(*it).b<<endl;  
  55.     return 0;  
  56. }  

 

输出:

found value a:13, b:1003

在这里,我们同样构造了一个仿函数,也就是class vector_finder,也就是vector_finder()函数,注意它的结构与我们要查找的结构体之间的关系,我们发现,它们是非常相象的。

这里的重点就在于class vector_finder的构造!

下面再看看,在map容器中的应用:

代码

 

[c-sharp] view plaincopy
 
  1. //----------------------------------------------------------------------------------------  
  2. //      Desc:       STL_find_if() used in map container, string data  
  3. //      Author:     pigfly  
  4. //      Data:       2010.12.01  
  5. //      Copyright (C) 2010 pigfly  
  6. //----------------------------------------------------------------------------------------  
  7.  
  8. #include <iostream>  
  9. #include <map>  
  10. #include <string>  
  11. #include <algorithm>  
  12. using namespace std;  
  13.   
  14. class map_finder  
  15. {  
  16. public:  
  17.     map_finder( string cmp_string ) : m_string(cmp_string) {}  
  18.     bool operator () (const map<int,string>::value_type pair)  
  19.     {  
  20.         return pair.second == m_string;  
  21.     }  
  22. private:  
  23.     string m_string;  
  24. };  
  25.   
  26. int main()  
  27. {  
  28.     map<int ,string> my_map;  
  29.     my_map.insert( make_pair(10,"china"));  
  30.     my_map.insert( make_pair(20,"usa"));  
  31.     my_map.insert( make_pair(30,"english"));  
  32.     my_map.insert( make_pair(40,"hongkong"));  
  33.   
  34.     map<int,string>::iterator it = find_if(my_map.begin(),my_map.end(),map_finder("english"));  
  35.     if( it == my_map.end() )  
  36.         cout<<"not found!"<<endl;  
  37.     else  
  38.         cout<<"found key:"<<(*it).first<<", value:"<<(*it).second<<endl;  
  39.     return 0;  
  40. }  

 

输出:

found key:30,vlaue:english

 

由于这里只是讲究一下find_if()的用法,没有去关心它的细节,如果希望了解更多,比如仿函数的模板原形,甚至整个STL,可以看看《STL源码剖析

 

find_if()在实应用中,查询对象可以是原先为空VECTOR,在平台软件有实现过。