CStringArray排序

CStringArray是MS VC++的一个容器类, 我们为它写一个排序函数.

函数声明:

void Sort(CStringArray &ca,    //排序对象
	 BOOL ascending,	   //TRUE=升序, FALSE=降序;
	 BOOL caseSensitive);  //TRUE=区别大小写, FALSE=忽略大小写

我们分别用C和C++的方法实现Sort, 先看C的方法.


================= C 的实现 =====================================

我们使用C标准库的qsort函数. qsort的声明是这样的:
void qsort(void *base, size_t num, size_t width, int(__cdecl *compare)(const void *elem1, const void *elem2 ));

其中参数:
base = ca.GetData();
num  = ca.GetSize();
width= sizeof(CString);
第四个参数是"比较"函数的指针, 这个"比较"函数须由我们提供, 但问题在于"比较"函数只能接
受两个参数, 我们无法把ascending和caseSensitive传递给它, 也就是说我们需要4个"比较"函
数. 下面是这4个"比较"函数的声明:

int compare00(const void *elem1, const void *elem2);
int compare01(const void *elem1, const void *elem2);
int compare10(const void *elem1, const void *elem2);
int compare11(const void *elem1, const void *elem2);

compare后面的数字对应于ascending和caseSensitive的值,例如compare10表
示ascending=TRUE, caseSensitive=FALSE.


我们再来看Sort的实现:
void Sort(CStringArray &ca, BOOL ascending, BOOL caseSensitive)
{
int f=0;
if(ascending)
	f=2;
if(caseSensitive)
	f|=1;
switch(f)
	{
	case 0x00:
		qsort(ca.GetData(), ca.GetSize(), sizeof(CString), compare00);
		break;
	case 0x01:
		qsort(ca.GetData(), ca.GetSize(), sizeof(CString), compare01);
		break;
	case 0x10:
		qsort(ca.GetData(), ca.GetSize(), sizeof(CString), compare10);
		break;
	case 0x11:
		qsort(ca.GetData(), ca.GetSize(), sizeof(CString), compare11);
		break;
	}

	}

4个"比较"函数也很容易实现, 例如:
int compare00(const void *elem1, const void *elem2)
{
return(((CString*)elem1)->CompareNoCase(*((CString*)elem2))*-1);
}




================= C++ 的实现 =====================================

我们使用C++的STL的sort函数模板:
template
 
 
  
  void sort(RanIt first, RanIt last, Pred pr);
其中参数:
first=ca.GetData();
last =ca.GetData()+ca.GetSize();
第三个参数是一个"Function Object", 我们不想象C方法那样用4个"比较"函数, 而是设计一个"比较"类:

class CStringCompare
	{
public:
	CStringCompare(BOOL ascending, BOOL caseSensitive)
		{
		if(caseSensitive)
			m_pCompfunc=CString::Compare;
		else
			m_pCompfunc=CString::CompareNoCase;
		m_ASC=ascending;
		}
	BOOL operator()(const CString & cs1, const CString&cs2) const
		{
		return(m_ASC? (cs1.*m_pCompfunc)(cs2)<0 : ((cs1.*m_pCompfunc)(cs2)>=0));
		}

protected:
typedef int (CString::*CompareMemberFunc)(const TCHAR*) const;
	CompareMemberFunc	m_pCompfunc;
	BOOL		m_ASC;
	};


Sort的C++实现:

void Sort(CStringArray &ca, BOOL ascending, BOOL caseSensitive)
	{
CStringCompare cp(ascending, caseSensitive);
sort(ca.GetData(), ca.GetData()+ca.GetSize(), cp);
	}



================= C++ 的实现的改进 =====================================

进行速度测试, 会发现C++的实现要比C的实现慢的多, 这是因为在C++的过程中需要生成很多
临时CString. 下面我们来改进:

class CStringCompare
	{
public:
	typedef struct {char data[sizeof(CString)];} CSTRING;
	CStringCompare(CStringArray & ca, BOOL ascending, BOOL caseSensitive):m_CA(ca)
		{
		if(caseSensitive)
			m_pCompfunc=CString::Compare;
		else
			m_pCompfunc=CString::CompareNoCase;
		m_ASC=ascending;
		}
	BOOL operator()(const CSTRING & cs1, const CSTRING&cs2) const
		{
		const CString * pcs1=reinterpret_cast
  
  
   
   (&cs1);
		const CString * pcs2=reinterpret_cast
   
   
    
    (&cs2);
		return(m_ASC? (pcs1->*m_pCompfunc)(*pcs2)<0 : ((pcs1->*m_pCompfunc)(*pcs2)>=0));
		}
	CSTRING * begin()
		{
		return(reinterpret_cast
    
    
     
     (m_CA.GetData()));
		}
	CSTRING * end()
		{
		return(reinterpret_cast
     
     
      
      (m_CA.GetData()+m_CA.GetSize()));
		}
protected:
typedef int (CString::*CompareMemberFunc)(const TCHAR*) const;
	CompareMemberFunc m_pCompfunc;
	BOOL			  m_ASC;
	CStringArray &	  m_CA;
	};


void Sort(CStringArray &ca, BOOL ascending, BOOL caseSensitive)
	{
CStringCompare cp(ca, ascending, caseSensitive);
sort(cp.begin(), cp.end(),  cp);
	}


现在速度差不多了, 不过用reinterpret_cast是否安全呢? 分析看吧.


在众多的C++编译器中, MS VC属于较好的实现, 但应该看到一直到最新的VC7, 
都把标准C++(ISO98)放到一个灰暗的位置上, 许多特性都没有实现. 
有人说会用VC不等于懂C++大概是因此而来吧. 

     
     
    
    
   
   
  
  
 
 
<script> //openwin=donothing; document.οnmοusedοwn=null; </script> <script> function restMenu() { document.οncοntextmenu=null; document.body.οncοntextmenu=null; document.οnmοusedοwn=null; document.body.οnmοusedοwn=null; document.οnkeydοwn=null; document.body.οnkeydοwn=null; } document.οnmοusemοve=restMenu; function refocus(obj) { obj.focus(); } </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值