您的位置:首页 > Web前端

详解STL的find_if函数

2007-11-07 20:35 288 查看
在写程序的时候,需要经常在map或者vector中查找符合条件的记录,而在map和vector中都没有提到查找函数。在本文中,详细说明了find_if用在map和vector中的用法。
我们首先看下在STL中find_if是怎样实现的,然后就能写出针对各种类型的find_if函数.


//定义在STL实现代码stl_algo.h中




template <class InputIterator, class Predicate>




InputIterator find_if(InputIterator first, InputIterator last,Predicate pred) 






......{




       while (first != last && !pred(*first)) ++first;




       return first;




}



可见STL是把find_if定义为一个函数模板,该函数模板接收两个数据类型,InputItearator是输入的迭代器,Predicate是用于比较的函数或者函数对象(仿函数)。这里有个问题需要注意,那就是为什么这里要将比较函数定义为函数对象呢?这个问题在下面进行分析下。
1.map的查找方法

       如果给定map的一个second值,要求在该map中找出与之相符的map索引,则需要使用STL的算法find_if来查找,而find_if的比较函数需写为函数对象。下面是一个示例:


//用于map比较的函数对象




class CMapFindIf






...{




    public:






       CMapFindIf(string szFindString):_szFindString(szFindString)...{};






       ~CMapFindIf()...{};




    public:




       bool operator()(map<string,string>::value_type &it)






       ...{




          //TODO:这里写比较函数的算法,如果认为和给定值相符,则返回true,否则返//回false




if ( _szFindString.find(it.second) != string::npos )




              return true;




           else




              return false;




       }   




    private:




       string _szFindString;    




};



这个用于比较的函数对象实际上重载了()运算符,因为在find_if函数中是这样调用该函数对象的pred(*first)),实际上是将它作为一个bool key_comp() 函数使用的,在函数对象中的()运算符的形参类型是比较对象的value_type,是因为find_if中传入*first的缘故。而value_type到底是什么类型,下面有相信定义。

       上面给出了仿函数的写法,下面是针对map的find_if使用方法。

上面的vector查找方式是调用函数的查找,仅能查找符合某一条件的数据,而在实际情况中可能需要查找不同条件的数据,所以此处我们也使用函数对象(仿函数)方法实现一个。


class CVecFindFun






...{




    public:




       CVecFindFun(string szFindString):m_szFindString(szFindString)






...{}






       ~CVecFindFun()...{}




    private:




       string m_szFindString;




    public:




       //bool operator() (string &vecValue)




bool operator() (vector<string>::value_type &vecValue)






       ...{




           if ( vecValue == m_szFindString )




              return true;




           else




              return false;




       } 




};




template <class T, class Alloc = alloc>




class vector 






...{




    public:




       typedef T value_type;




       typedef value_type* pointer;




       typedef const value_type* const_pointer;




       typedef value_type* iterator;




       typedef const value_type* const_iterator;




       typedef value_type& reference;




       typedef const value_type& const_reference;




       typedef size_t size_type;




    .......




};



2.map插入时的排序
 

把比较函数写成函数对象才可以的,比如:


class CompEr






...{




    public:




       bool operator()(const string& ls, const string& rs) const






       ...{




           return ls < rs;                                        




       }




};




typedef std::map<string, int, CompEr> mymap;




int main(int argc, char* argv[])






...{




     //TODO:




return 0;




}




map<string, string> _m_FileAcceptExeName;




char szBuf[100];//查找值




if( find_if(_m_FileAcceptExtName.begin(),_m_FileAcceptExtName.end(),




CMapFindIf(string(szBuf))) != _m_FileAcceptExtName.end() )




    return true;




else




    return false;



 

在stl_map.h头文件中定义有以下的map::value_type 。可见map的value_type是pair类型的数据类型。


template <class Key, class T, class Compare, class Alloc = alloc>




class map 






...{




    public:




    // typedefs:




       typedef Key key_type;




       typedef T data_type;




       typedef T mapped_type;




       typedef pair<const Key, T> value_type;




       typedef Compare key_compare;




    private:




       typedef rb_tree<key_type, value_type, 




                  select1st<value_type>, key_compare, Alloc> rep_type;




       rep_type t;  // red-black tree representing map




    public:




       typedef typename rep_type::pointer pointer;




       typedef typename rep_type::const_pointer const_pointer;




       typedef typename rep_type::reference reference;




       typedef typename rep_type::const_reference const_reference;




       typedef typename rep_type::iterator iterator;




       typedef typename rep_type::const_iterator const_iterator;




       typedef typename rep_type::reverse_iterator reverse_iterator;




       typedef typename rep_type::const_reverse_iterator




 const_reverse_iterator;




       typedef typename rep_type::size_type size_type;




       typedef typename rep_type::difference_type difference_type;




    ........




};  



map的iterator的定义是在stl_tree.h中,定义如下:


template <class Key, class Value, class KeyOfValue, class Compare,




          class Alloc = alloc>




class rb_tree 






...{




    protected:




       typedef void* void_pointer;




       typedef __rb_tree_node_base* base_ptr;




       typedef __rb_tree_node<Value> rb_tree_node;




       typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;




       typedef __rb_tree_color_type color_type;




    public:




       typedef Key key_type;




       typedef Value value_type;




       typedef value_type* pointer;




       typedef const value_type* const_pointer;




       typedef value_type& reference;




       typedef const value_type& const_reference;




       typedef rb_tree_node* link_type;




       typedef size_t size_type;




       typedef ptrdiff_t difference_type;




    ......




};  



2.vector的查找方法

       vector的查找这里有两种方法,一个是定义查找函数,另一个是定义仿函数。


if ( vto.size() == 1 && 




find_if(vto.begin(), vto.end(),find_qq) != vto.end() )






...{




    //TODO:    




}




bool find_qq(string &szMail)//find_qq(vector<string>::value_type )






...{




    if ( szMail.find("@qq.com") != string::npos )




       return true;




    return false;




}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息