CStringArray排序

类别:VC语言 点击:0 评论:0 推荐:

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
函数模板:
    templatevoid 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++大概是因此而来吧. //openwin=donothing;document.onmousedown=null; function restMenu() {document.oncontextmenu=null;document.body.oncontextmenu=null;document.onmousedown=null;document.body.onmousedown=null;document.onkeydown=null;document.body.onkeydown=null; }document.onmousemove=restMenu;function refocus(obj){obj.focus();}

本文地址:http://com.8s8s.com/it/it213.htm