详解STL的find_if函数

在写程序的时候,需要经常在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是用于比较的函数或者函数对象(仿函数)。这里有个问题需要注意,那就是为什么这里要将比较函数定义为函数对象呢?这个问题在下面进行分析下。

1map的查找方法

       如果给定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到底是什么类型,下面有相信定义。

       上面给出了仿函数的写法,下面是针对mapfind_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;

    .......

}
;

2map插入时的排序

 

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

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 。可见mapvalue_typepair类型的数据类型。

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;

    ......

}
;  

2vector的查找方法

       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;

}

你可能感兴趣的:(vector,String,tree,iterator,Class,reference)