王朝网络
分享
 
 
 

MFC容器的迭代器之一(Array)

王朝other·作者佚名  2006-01-10
宽屏版  字体: |||超大  

MFC的容器虽然实现了基本的功能,但是有些比较常用的并没有直接提供给我们,比如查找,排序.通常,作这些操作都要我们自己去实现,可这样作,时间,效率,可靠性,都会超支.如果可以将STL的查找,排序算法应用到MFC上,那将是一件很愉快的事. 查找,排序对容器有一定的要求,即iterator,如果实现了MFC容器相对应的iterator,问题自然解开. 下面顺序制作Array和List的迭代器.

一. Array是最基本的容器,在一块连续的空间上构造对象序列. CArray提供了一个函数GetData(),使得我们可以访问这块空间. STL对于基本数组提供了支持,所以,我们可以直接使用这块空间的指针当Iterator.

CDWordArray arr;

arr.Add( 1 );

arr.Add( 2 );

arr.Add( 3 );

arr.Add( 4 );

DWORD* posBegin = arr.GetData();

DWORD* posEnd = arr.GetData() + arr.GetSize();

DWORD* posFind = std::find( posBegin, posEnd, 3 );

DWORD dwVal = *posFind;

ASSERT( dwVal == 3 );

对于CArray也可以这样作. 以下是我封装的辅助类.

//////////////////////////////////////////////////////////////////////////

// *****QQQ******* W******W******W EEEEEEEEEEEEEEE RRRRRRRRRRRRR**

// ***QQ***QQ***** WW****WWW****WW EE************* RR********RRRRR

// *QQ*******QQ*** *WW**WW*WW**WW* EE************* RR******RRRRR**

// QQ****Q****QQ** *WW**WW*WW**WW* EEEEEEEEEEEEEEE RR****RRRRR****

// *QQ****QQ*QQ*** *WW**WW*WW**WW* EEEEEEEEEEEEEEE RR**RRRR*******

// **QQ*****QQ**** *WW**WW*WW**WW* EE************* RRRR***********

// ***QQ***QQ*QQ** **W**W***W**W** EE************* RR**RRRR*******

// *****QQQ*****QQ ***WW*****WW*** EEEEEEEEEEEEEEE RR****RRRRRRRRR

// Author Terry board

// Email qwer4821@163.com

// Date 2005-7-7 16:28:40

// File MCArrayUtil.hpp

//////////////////////////////////////////////////////////////////////////

#ifndef MCArrayUtil_qwer_

#define MCArrayUtil_qwer_

//////////////////////////////////////////////////////////////////////////

#include <functional>

#include <algorithm>

//////////////////////////////////////////////////////////////////////////

//

//

//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

namespace qwer

{

//////////////////////////////////////////////////////////////////////////

template < typename TYPE, typename ARG_TYPE >

class MCArrayUtil

{

public:

typedef TYPE value_type;

typedef TYPE& reference;

typedef const TYPE& const_reference;

typedef TYPE* _Tptr;

typedef const TYPE* _Ctptr;

typedef int size_type;

typedef _Tptr iterator;

typedef _Ctptr const_iterator;

typedef ptrdiff_t difference_type;

typedef std::reverse_iterator<const_iterator, value_type,

const_reference, _Ctptr, difference_type>

const_reverse_iterator;

typedef std::reverse_iterator<iterator, value_type,

reference, _Tptr, difference_type>

reverse_iterator;

//!

typedef ARG_TYPE arg_type;

typedef CArray< TYPE, ARG_TYPE > base_array;

protected:

base_array& m_arrRef;

public:

MCArrayUtil();

MCArrayUtil( base_array& arr )

:m_arrRef(arr)

{

}

MCArrayUtil( const MCArrayUtil& arrUtil )

:m_arrRef( arrUtil.m_arrRef )

{

}

operator = ( const MCArrayUtil& arrUtil );

operator = ( base_array& arr );

public:

_Tptr GetData() const

{

return const_cast< _Tptr >(m_arrRef.GetData());

}

size_type GetSize() const

{

return m_arrRef.GetSize();

}

public:

inline iterator begin( )

{

return GetData();

}

inline const_iterator begin() const

{

return GetData();

}

inline iterator end( )

{

return GetData() + GetSize();

}

inline const_iterator end() const

{

return GetData() + GetSize();

}

inline iterator indexToIterator( size_type nIndex )

{

if ( CheckIndex( nIndex ) )

{

return begin() + nIndex;

}

else

{

return end( );

}

}

inline const_iterator indexToIterator( size_type nIndex ) const

{

if ( CheckIndex( nIndex ) )

{

return begin( ) + nIndex;

}

else

{

return end( );

}

}

inline size_type iteratorToIndex( iterator it )

{

return it - begin();

}

inline size_type iteratorToIndex( const_iterator it ) const

{

return it - begin();

}

inline bool checkIndex( size_type nIndex )

{

return ( nIndex >= 0 && nIndex < GetSize() );

}

size_type find( arg_type val ) const

{

return iteratorToIndex( std::find( begin(), end(), val ) );

}

template < typename Predicate >

size_type find_if( Predicate pre ) const

{

return iteratorToIndex( std::find_if( begin(), end(), pre ) );

}

void sort( )

{

std::sort( begin(), end() );

}

template < typename Predicate >

void sort( Predicate pre )

{

std::sort( begin(), end(), pre );

}

//////////////////////////////////////////////////////////////////////////

size_type size() const

{

return m_arrRef.GetSize();

}

bool empty() const

{

return ( size() > 0 );

}

void push_back( const value_type& val )

{

m_arrRef.Add( val );

}

void push_front( const value_type& val )

{

m_arrRef.InsertAt( 0, val );

}

void pop_front()

{

m_arrRef.RemoveAt( 0 );

}

void pop_back()

{

m_arrRef.RemoveAt( size() - 1 );

}

void clear()

{

m_arrRef.RemoveAll();

}

};

//////////////////////////////////////////////////////////////////////////

template < typename Array, typename TYPE >

class MBaseArray

{

public:

typedef TYPE value_type;

typedef TYPE& reference;

typedef const TYPE& const_reference;

typedef TYPE* _Tptr;

typedef const TYPE* _Ctptr;

typedef int size_type;

typedef _Tptr iterator;

typedef _Ctptr const_iterator;

typedef ptrdiff_t difference_type;

typedef std::reverse_iterator<const_iterator, value_type,

const_reference, _Ctptr, difference_type>

const_reverse_iterator;

typedef std::reverse_iterator<iterator, value_type,

reference, _Tptr, difference_type>

reverse_iterator;

//!

typedef TYPE arg_type;

typedef Array base_array;

protected:

base_array& m_arrRef;

public:

MBaseArray();

MBaseArray( base_array& arr )

:m_arrRef(arr)

{

}

MBaseArray( const MBaseArray& arrUtil )

:m_arrRef( arrUtil.m_arrRef )

{

}

operator = ( const MBaseArray& arrUtil );

operator = ( base_array& arr );

public:

_Tptr GetData() const

{

return const_cast< _Tptr >(m_arrRef.GetData());

}

size_type GetSize() const

{

return m_arrRef.GetSize();

}

public:

inline iterator begin( )

{

return GetData();

}

inline const_iterator begin() const

{

return GetData();

}

inline iterator end( )

{

return GetData() + GetSize();

}

inline const_iterator end() const

{

return GetData() + GetSize();

}

inline iterator indexToIterator( size_type nIndex )

{

if ( CheckIndex( nIndex ) )

{

return begin( ) + nIndex;

}

else

{

return end( );

}

}

inline const_iterator indexToIterator( size_type nIndex ) const

{

if ( CheckIndex( nIndex ) )

{

return begin( ) + nIndex;

}

else

{

return end( );

}

}

inline size_type iteratorToIndex( iterator it )

{

return it - begin();

}

inline size_type iteratorToIndex( const_iterator it ) const

{

return it - begin();

}

inline bool checkIndex( size_type nIndex )

{

return ( nIndex >= 0 && nIndex < GetSize() );

}

size_type find( arg_type val ) const

{

return iteratorToIndex( std::find( begin(), end(), val ) );

}

template < typename Predicate >

size_type find_if( Predicate pre ) const

{

return iteratorToIndex( std::find_if( begin(), end(), pre ) );

}

void sort( )

{

std::sort( begin(), end() );

}

template < typename Predicate >

void sort( Predicate pre )

{

std::sort( begin(), end(), pre );

}

};

//////////////////////////////////////////////////////////////////////////

typedef MBaseArray< CByteArray, BYTE > MCByteArray;

typedef MBaseArray< CWordArray, WORD > MCWordArray;

typedef MBaseArray< CUIntArray, UINT > MCUIntArray;

typedef MBaseArray< CDWordArray, DWORD > MCDWordArray;

typedef MBaseArray< CStringArray, CString > MCStringArray;

//////////////////////////////////////////////////////////////////////////

template < typename Array >

class MBaseArrayUtil

{

};

template<>

class MBaseArrayUtil< CByteArray > : public MCByteArray

{

public:

typedef MCByteArray base_class;

public:

MBaseArrayUtil( base_array& arr )

:base_class( arr )

{

}

MBaseArrayUtil( const MBaseArrayUtil& arr )

:base_class( arr )

{

}

};

template<>

class MBaseArrayUtil< CWordArray > : public MCWordArray

{

public:

typedef MCWordArray base_class;

public:

MBaseArrayUtil( base_array& arr )

:base_class( arr )

{

}

MBaseArrayUtil( const MBaseArrayUtil& arr )

:base_class( arr )

{

}

};

template<>

class MBaseArrayUtil< CUIntArray > : public MCUIntArray

{

public:

typedef MCUIntArray base_class;

public:

MBaseArrayUtil( base_array& arr )

:base_class( arr )

{

}

MBaseArrayUtil( const MBaseArrayUtil& arr )

:base_class( arr )

{

}

};

template<>

class MBaseArrayUtil< CDWordArray > : public MCDWordArray

{

public:

typedef MCDWordArray base_class;

public:

MBaseArrayUtil( base_array& arr )

:base_class( arr )

{

}

MBaseArrayUtil( const MBaseArrayUtil& arr )

:base_class( arr )

{

}

};

template<>

class MBaseArrayUtil< CStringArray > : public MCStringArray

{

public:

typedef MCStringArray base_class;

public:

MBaseArrayUtil( base_array& arr )

:base_class( arr )

{

}

MBaseArrayUtil( const MBaseArrayUtil& arr )

:base_class( arr )

{

}

public:

struct FindorNoCase : public std::binary_function< CString, CString, bool >

{

bool operator () ( const CString& strL, const CString& strR ) const

{

return ( strL.CompareNoCase( strR ) == 0 );

}

};

public:

size_type FindNoCase( LPCTSTR str ) const

{

return find_if( std::bind2nd(FindorNoCase(), str ) );

}

};

//////////////////////////////////////////////////////////////////////////

typedef MBaseArrayUtil< CByteArray > MCByteArrayUtil;

typedef MBaseArrayUtil< CWordArray > MCWordArrayUtil;

typedef MBaseArrayUtil< CUIntArray > MCUIntArrayUtil;

typedef MBaseArrayUtil< CDWordArray > MCDWordArrayUtil;

typedef MBaseArrayUtil< CStringArray > MCStringArrayUtil;

//////////////////////////////////////////////////////////////////////////

} //end namespace qwer

//////////////////////////////////////////////////////////////////////////

#endif

但是对于 CTypedPtrArray ,由于元素是指针,查找和排序的实现,需要依赖于functor. 如果不想编写特殊的functor,而是希望借用已有的或者编译器支持的operator等,设计一个Adaptor是必需的.以下代码对操作于指针对象上的functor进行封装.

//! argument_type of unary functor is pointer

template < typename UnaryFunctor >

struct unary_ptr_function : public std::unary_function< UnaryFunctor::argument_type*, UnaryFunctor::result_type >

{

protected:

UnaryFunctor& m_funcRef;

public:

result_type operator () ( argument_type arg ) const

{

return m_funcRef(*arg);

}

unary_ptr_function( UnaryFunctor& func )

:m_funcRef(func)

{

}

};

//! first_argument_type of binary functor is pointer

template < typename BinaryFunctor>

struct binary_ptr1st_function : public std::binary_function< BinaryFunctor::first_argument_type*,

BinaryFunctor::second_argument_type,

BinaryFunctor::result_type >

{

protected:

BinaryFunctor& m_funcRef;

public:

result_type operator () ( first_argument_type arg1, second_argument_type arg2 ) const

{

return m_funcRef( *arg1, arg2 );

}

binary_ptr1st_function( BinaryFunctor& func )

:m_funcRef( func )

{

}

};

//! second_argument_type of binary functor is pointer

template < typename BinaryFunctor>

struct binary_ptr2nd_function : public std::binary_function< BinaryFunctor::first_argument_type,

BinaryFunctor::second_argument_type*,

BinaryFunctor::result_type >

{

protected:

BinaryFunctor& m_funcRef;

public:

result_type operator () ( first_argument_type arg1, second_argument_type arg2 ) const

{

return m_funcRef( arg1, *arg2 );

}

binary_ptr2nd_function( BinaryFunctor& func )

:m_funcRef( func )

{

}

};

//! first_argument_type and second_argument_type of binary functor is pointer

template < typename BinaryFunctor>

struct binary_ptr_function : public std::binary_function< BinaryFunctor::first_argument_type*,

BinaryFunctor::second_argument_type*,

BinaryFunctor::result_type >

{

protected:

BinaryFunctor& m_funcRef;

public:

result_type operator () ( first_argument_type arg1, second_argument_type arg2 ) const

{

return m_funcRef( *arg1, *arg2 );

}

binary_ptr_function( BinaryFunctor& func )

:m_funcRef( func )

{

}

};

//! unary functor bindor

template < typename UnaryFunctor >

unary_ptr_function< UnaryFunctor > BindUnaryPtrFunc( UnaryFunctor& func )

{

return unary_ptr_function<UnaryFunctor>(func);

};

template < typename BinaryFunctor >

binary_ptr1st_function< BinaryFunctor > BindBinaryPtrFunc1st( BinaryFunctor& func )

{

return binary_ptr1st_function< BinaryFunctor >( func );

}

template < typename BinaryFunctor >

binary_ptr2nd_function< BinaryFunctor > BindBinaryPtrFunc2nd( BinaryFunctor& func )

{

return binary_ptr2nd_function< BinaryFunctor >( func );

}

template < typename BinaryFunctor >

binary_ptr_function< BinaryFunctor > BindBinaryPtrFunc( BinaryFunctor& func )

{

return binary_ptr_function< BinaryFunctor >( func );

}

有了以上这些Adaptor,实现CTypedPtrArray的查找,排序就非常容易了.

//////////////////////////////////////////////////////////////////////////

// *****QQQ******* W******W******W EEEEEEEEEEEEEEE RRRRRRRRRRRRR**

// ***QQ***QQ***** WW****WWW****WW EE************* RR********RRRRR

// *QQ*******QQ*** *WW**WW*WW**WW* EE************* RR******RRRRR**

// QQ****Q****QQ** *WW**WW*WW**WW* EEEEEEEEEEEEEEE RR****RRRRR****

// *QQ****QQ*QQ*** *WW**WW*WW**WW* EEEEEEEEEEEEEEE RR**RRRR*******

// **QQ*****QQ**** *WW**WW*WW**WW* EE************* RRRR***********

// ***QQ***QQ*QQ** **W**W***W**W** EE************* RR**RRRR*******

// *****QQQ*****QQ ***WW*****WW*** EEEEEEEEEEEEEEE RR****RRRRRRRRR

// Author Terry board

// Email qwer4821@163.com

// Date 2005-7-18 15:13:30

// File MPtrArrayUtil.hpp

//////////////////////////////////////////////////////////////////////////

#ifndef MPtrArrayUtil_qwer_

#define MPtrArrayUtil_qwer_

#include <MSTLFunctor.hpp>

//////////////////////////////////////////////////////////////////////////

#ifndef SAFE_DELETE

#define SAFE_DELETE(p) if((p) != NULL) {delete (p); (p) = NULL;}

#endif //!SAFE_DELETE

//////////////////////////////////////////////////////////////////////////

//

//

//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

namespace qwer

{

//////////////////////////////////////////////////////////////////////////

//! CTypedPtrArray 辅助类, 实现iterator,find,sort

//! Array 为 CPtrArray 或者 CObjArray, ClassType 为元素的值类型(不是指针)

template < typename Array, typename ClassType >

class MPtrArrayUtil

{

public:

typedef ClassType ElementValueType;

typedef ElementValueType* TYPE;

typedef TYPE value_type;

typedef TYPE& reference;

typedef const TYPE& const_reference;

typedef TYPE* _Tptr;

typedef const TYPE* _Ctptr;

typedef int size_type;

typedef _Tptr iterator;

typedef _Ctptr const_iterator;

typedef ptrdiff_t difference_type;

typedef std::reverse_iterator<const_iterator, value_type,

const_reference, _Ctptr, difference_type>

const_reverse_iterator;

typedef std::reverse_iterator<iterator, value_type,

reference, _Tptr, difference_type>

reverse_iterator;

//!

typedef TYPE arg_type;

typedef Array base_array;

protected:

base_array& m_arrRef;

public:

MPtrArrayUtil();

MPtrArrayUtil( base_array& arr )

:m_arrRef(arr)

{

}

MPtrArrayUtil( const MPtrArrayUtil& arrUtil )

:m_arrRef( arrUtil.m_arrRef )

{

}

operator = ( const MPtrArrayUtil& arrUtil );

operator = ( base_array& arr );

public:

_Tptr GetData() const

{

return reinterpret_cast< _Tptr >(m_arrRef.GetData());

}

size_type GetSize() const

{

return m_arrRef.GetSize();

}

public:

inline iterator begin( )

{

return GetData();

}

inline const_iterator begin() const

{

return GetData();

}

inline iterator end( )

{

return GetData() + GetSize();

}

inline const_iterator end() const

{

return GetData() + GetSize();

}

inline iterator indexToIterator( size_type nIndex )

{

if ( CheckIndex( nIndex ) )

{

return begin() + nIndex;

}

else

{

return end( );

}

}

inline const_iterator indexToIterator( size_type nIndex ) const

{

if ( CheckIndex( nIndex ) )

{

return begin( ) + nIndex;

}

else

{

return end( );

}

}

inline size_type iteratorToIndex( iterator it )

{

return it - begin();

}

inline size_type iteratorToIndex( const_iterator it ) const

{

return it - begin();

}

inline bool checkIndex( size_type nIndex )

{

return ( nIndex >= 0 && nIndex < GetSize() );

}

size_type find( ElementValueType val ) const

{

return iteratorToIndex( std::find_if( begin(), end(),

qwer::BindUnaryPtrFunc( std::bind2nd( std::equal_to< ElementValueType >(), val ) ) )

);

}

template < typename Predicate >

size_type find_if( Predicate pre ) const

{

return iteratorToIndex( std::find_if( begin(), end(),

qwer::BindUnaryPtrFunc(pre) )

);

}

void sort( )

{

std::sort( begin(), end(), qwer::BindBinaryPtrFunc( std::less<ElementValueType>() ) );

}

template < typename Predicate >

void sort( Predicate pre )

{

std::sort( begin(), end(), qwer::BindBinaryPtrFunc(pre) );

}

//////////////////////////////////////////////////////////////////////////

void DeleteAll()

{

for ( int i = 0; i < m_arrRef.GetSize(); i++ )

{

SAFE_DELETE( m_arrRef[i] );

}

m_arrRef.RemoveAll();

}

void DeleteAt( int nIndex, int nCount = 1 )

{

for ( int i = nIndex; i < min(m_arrRef.GetSize(), nIndex + nCount); i++ )

{

SAFE_DELETE( m_arrRef[i] );

}

m_arrRef.RemoveAt( nIndex, nCount );

}

//////////////////////////////////////////////////////////////////////////

size_type size() const

{

return m_arrRef.GetSize();

}

bool empty() const

{

return ( size() > 0 );

}

void push_back( const value_type& val )

{

m_arrRef.Add( val );

}

void push_front( const value_type& val )

{

m_arrRef.InsertAt( 0, val );

}

void pop_front()

{

m_arrRef.RemoveAt( 0 );

}

void pop_back()

{

m_arrRef.RemoveAt( size() - 1 );

}

void clear()

{

m_arrRef.RemoveAll();

}

//////////////////////////////////////////////////////////////////////////

};

//////////////////////////////////////////////////////////////////////////

} //end namespace qwer

//////////////////////////////////////////////////////////////////////////

#endif

应用举例:

1. 字符串数组类

CStringArray arrTest;

MCStringArrayUtil util(arrTest);

util.FindNoCase( "a" );

2. Array模板类

class CMan : public CObject

{

public:

int m_nWeight; //! uint is g

...

};

typedef qwer::MCArrayUtil< CMan, CMan& > CManArrayUtil;

CManArrayUtil util( m_arrMan );

util.sort();

3. 指针的数组类

typedef CTypedPtrArray< CPtrArray, CMan* > CManPtrArray;

typedef qwer::MPtrArrayUtil< CPtrArray, CMan > CManPtrArrayUtil;

CManPtrArray arrMan;

CManPtrArrayUtil util(arrMan);

arrMan.Add( new CMan(100) );

arrMan.Add( new CMan(10) );

arrMan.Add( new CMan(12) );

qwer::BindUnaryPtrFunc( Functor_5() );

int nIndex = -1;

CMan** posBegin = util.begin();

CManPtrArrayUtil::iterator posEnd = util.end();

CManPtrArrayUtil::iterator posFind = std::find_if( util.begin(), util.end(),

BindUnaryPtrFunc(Functor_5()) );

posFind = std::find_if( util.begin(), util.end(),

BindUnaryPtrFunc( std::bind2nd(std::equal_to< CMan >(),CMan(10)) ) );

nIndex = util.find( CMan(10) );

ASSERT( 1 == nIndex );

util.sort();

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有