1/07/2004

QSort

QSort大家都很熟悉了,VC运行时刻库也提供了一个函数,可以方便地使用QSort算法
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
参见
[url=http://support.microsoft.com/support/ kb/articles/Q216/8/58.ASP]216858 - HOWTO: Quick Sorting Using MFC CArray-Derived Classes[/url]
[pre]
下面是我自己写的一个实现
#include
#include

class CContact:public CObject
{
public:
CContact(){bFailLoadPic=FALSE;}
CString strNickName;
CString strUserID;
CString strFirstName;
CString strFamilyName;
CString strEmail;
CString strPic;
BOOL bFailLoadPic;
CPictureHolder pic;
int Compare(const CContact& pContact) const;
BOOL WriteToFile(LPCTSTR lpszFile,LPCTSTR lpszStyleSheet=NULL);
};
typedef int (__cdecl *GENERICCOMPAREFN)(const void * elem1, const void * elem2);
typedef int (__cdecl *CONTACTCOMPAREFN)(const CContact ** elem1, const CContact ** elem2);

class CQuickSortContactArray :public CTypedPtrArray
{
public:
CQuickSortContactArray();
virtual ~CQuickSortContactArray();

void Clear();
void Sort(CONTACTCOMPAREFN pfnCompare = Compare);
static int __cdecl Compare(const CContact ** pstr1, const CContact ** pstr2);
BOOL ReadFromFile(LPCTSTR lpszFile);
BOOL ReadFromMemory(LPVOID lpData,DWORD cbData);
BOOL ReadFromStream(IStream* pStream);
protected:
CString GetValueString(IXMLDOMNodePtr pXMLDomNode,LPCTSTR lpszChildNodeName);
HRESULT CreateXMLDOM(IXMLDOMDocument2Ptr & pIXMLDOMDocument2);
BOOL AnalysisXMLDOM(IXMLDOMDocument2Ptr pIXMLDOMDocument2);
void ReportXMLDOMError(IXMLDOMDocument2Ptr pIXMLDOMDocument2);
};
// QuickSortContactArray.cpp: implementation of the CQuickSortContactArray class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TipControl.h"
#include "QuickSortContactArray.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
int CContact::Compare(const CContact& pContact) const
{
return strNickName.Compare(pContact.strNickName);
}
BOOL CContact::WriteToFile(LPCTSTR lpszFile,LPCTSTR lpszStyleSheet)
{
IXMLDOMDocument2Ptr pDoc;
HRESULT hr ;
try{
hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
if(pDoc){
pDoc->async = false;
pDoc->resolveExternals = false;
pDoc->validateOnParse = true;
}
else
return FALSE;
IXMLDOMProcessingInstructionPtr pProcessingInstruction;
IXMLDOMElementPtr pRoot,pParent,pChild;
pProcessingInstruction=pDoc->createProcessingInstruction(_T("xml"),
_T("version=''1.0'' encoding=''UTF-16''"));
pDoc->appendChild(pProcessingInstruction);

if(::PathFileExists(lpszStyleSheet)){
CString strTemp;
strTemp.Format(_T("type=''text/xsl'' href=''%s''"),lpszStyleSheet);
pProcessingInstruction=pDoc->createProcessingInstruction(_T("xml-stylesheet"),
(LPCTSTR)strTemp);
pDoc->appendChild(pProcessingInstruction);
}
pRoot=pDoc->createElement(_T("Data"));
hr=pDoc->appendChild(pRoot);
TRACE(_T("%s\r\n"),(LPCTSTR)pDoc->xml);
pParent=pDoc->createElement(_T("Contact"));
hr=pRoot->appendChild(pParent);
TRACE(_T("%s\r\n"),(LPCTSTR)pDoc->xml);
pChild=pDoc->createElement(_T("NickName"));
pChild->text=(LPCTSTR)strNickName;
hr=pParent->appendChild(pChild);
TRACE(_T("%s\r\n"),(LPCTSTR)pDoc->xml);
pChild=pDoc->createElement(_T("UserID"));
pChild->text=(LPCTSTR)strUserID;
hr=pParent->appendChild(pChild);

pChild=pDoc->createElement(_T("FirstName"));
pChild->text=(LPCTSTR)strFirstName;
hr=pParent->appendChild(pChild);

pChild=pDoc->createElement(_T("FamilyName"));
pChild->text=(LPCTSTR)strFamilyName;
hr=pParent->appendChild(pChild);

pChild=pDoc->createElement(_T("Email"));
pChild->text=(LPCTSTR)strEmail;
hr=pParent->appendChild(pChild);

pChild=pDoc->createElement(_T("Pic"));
pChild->text=(LPCTSTR)strPic;
hr=pParent->appendChild(pChild);
hr = pDoc->save(lpszFile);
}
catch(...){
return FALSE;
}

return SUCCEEDED(hr);
}
CQuickSortContactArray::CQuickSortContactArray()
{

}

CQuickSortContactArray::~CQuickSortContactArray()
{
Clear();
}
int CQuickSortContactArray::Compare(const CContact** pstr1, const CContact** pstr2)
{
ASSERT(pstr1);
ASSERT(pstr2);
return (*pstr1)->Compare(*(*pstr2));
}

void CQuickSortContactArray::Sort(CONTACTCOMPAREFN pfnCompare
/*= CQuickSortContactArray::Compare */)
{
//CContact ** prgstr =(CContact**)GetData();
qsort(GetData(),GetSize(),sizeof(CContact*),(GENERICCOMPAREFN)pfnCompare);
}
void CQuickSortContactArray::Clear()
{
CContact* pContact=NULL;
for(int i=0;i pContact=GetAt(i);
if(pContact)delete pContact;
}
RemoveAll();
}
HRESULT CQuickSortContactArray::CreateXMLDOM(IXMLDOMDocument2Ptr & pIXMLDOMDocument2)
{
// Create the DOM
HRESULT hr = pIXMLDOMDocument2.CreateInstance(__uuidof(MSXML2::DOMDocument40));
if(pIXMLDOMDocument2){
pIXMLDOMDocument2->async = false;
pIXMLDOMDocument2->resolveExternals = false;
pIXMLDOMDocument2->validateOnParse = true;
}
return hr;
}
void CQuickSortContactArray::ReportXMLDOMError(IXMLDOMDocument2Ptr pIXMLDOMDocument2)
{
IXMLDOMParseErrorPtr pError;
pError = pIXMLDOMDocument2->parseError;
_bstr_t parseError =_bstr_t("At line ")+ _bstr_t(pError->Getline())
+ _bstr_t("\n")+ _bstr_t(pError->Getreason());
AfxMessageBox((LPCTSTR)parseError);
}
BOOL CQuickSortContactArray::ReadFromFile(LPCTSTR lpszFile)
{
IXMLDOMDocument2Ptr pIXMLDOMDocument2;
HRESULT hr ;
try
{
hr = CreateXMLDOM(pIXMLDOMDocument2);
// Load the document into the DOM
hr = pIXMLDOMDocument2->load(lpszFile);
// If document does not load report the parse error
if(hr!=VARIANT_TRUE){
ReportXMLDOMError(pIXMLDOMDocument2);
return FALSE;
}
if(!AnalysisXMLDOM(pIXMLDOMDocument2))
Clear();
}catch(...){
CString strError;
strError.Format(IDS_STRING102,lpszFile);
::AfxMessageBox(strError);
return FALSE;
}
return TRUE;
}
BOOL CQuickSortContactArray::ReadFromMemory(LPVOID lpData,DWORD cbData)
{
COleStreamFile osf;
if(!osf.CreateMemoryStream())return FALSE;
osf.Write(lpData,cbData);
osf.SeekToBegin();
return ReadFromStream(osf.GetStream());
}
BOOL CQuickSortContactArray::ReadFromStream(IStream* pStream)
{
IXMLDOMDocument2Ptr pIXMLDOMDocument2;
HRESULT hr ;
try
{
hr = CreateXMLDOM(pIXMLDOMDocument2);
// Load the document into the DOM
hr = pIXMLDOMDocument2->load(pStream);
// If document does not load report the parse error
if(hr!=VARIANT_TRUE){
ReportXMLDOMError(pIXMLDOMDocument2);
return FALSE;
}
if(!AnalysisXMLDOM(pIXMLDOMDocument2))
Clear();
}catch(...){
return FALSE;
}
return TRUE;
}

CString CQuickSortContactArray::GetValueString(IXMLDOMNodePtr pXMLDomNode,LPCTSTR lpszChildNodeName)
{
CString strRet;
IXMLDOMNodePtr pChild=pXMLDomNode->selectSingleNode(lpszChildNodeName);
if(pChild)
strRet=(LPCTSTR)pChild->text;
return strRet;
}
BOOL CQuickSortContactArray::AnalysisXMLDOM(IXMLDOMDocument2Ptr pIXMLDOMDocument2)
{
Clear();
IXMLDOMElementPtr pXMLDocElement = NULL;
pXMLDocElement = pIXMLDOMDocument2->documentElement;
IXMLDOMNodeListPtr pXMLDomNodeList = NULL;
pXMLDomNodeList = pXMLDocElement->selectNodes("Contact");
int count = 0;
count = pXMLDomNodeList->length;
for(int i=0;i IXMLDOMNodePtr pXMLDomNode= pXMLDomNodeList->item[i];
CContact* pContact=new CContact;
pContact->strUserID=GetValueString(pXMLDomNode,_T("UserID"));
pContact->strNickName=GetValueString(pXMLDomNode,_T("NickName"));
pContact->strFirstName=GetValueString(pXMLDomNode,_T("FirstName"));
pContact->strFamilyName=GetValueString(pXMLDomNode,_T("FamilyName"));
pContact->strEmail=GetValueString(pXMLDomNode,_T("Email"));
pContact->strPic=GetValueString(pXMLDomNode,_T("Pic"));
Add(pContact);
}
Sort();
return TRUE;
}
[/pre]

No comments: