这是一段对List Control进行排序的代码,现在有这个一个问题,对于一些数字型的东西,如"123"和"21",这段代码会认为"123" < "21",我想更正这个错误,谢谢!可以先进行位数上的比较.
BOOL CSortFileList::SortTextItems(int nCol, BOOL bAscending, int low, int high,BOOL bIsNumber)
{
int i;
int lo = low;
int hi = high;
CString  midItem;
CStringArray rowText;
LV_ITEM lvitemlo, lvitemhi; if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;

if( high == -1 ) high = GetItemCount() - 1; if( hi <= lo ) return FALSE; midItem = GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
// find the first element that is greater than or equal to 
// the partition element starting from the left Index.
if( bAscending )
while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
++lo;
else
while( ( lo < high ) && ( GetItemText(lo, nCol) > midItem ) )
++lo; // find an element that is smaller than or equal to 
// the partition element starting from the right Index.
if( bAscending )
while( ( hi > low ) && ( GetItemText(hi, nCol) > midItem ) )
--hi;
else
while( ( hi > low ) && ( GetItemText(hi, nCol) < midItem ) )
--hi; // if the indexes have not crossed, swap
// and if the items are not equal
if( lo <= hi )
{
// swap only if the items are not equal
if( GetItemText(lo, nCol) != GetItemText(hi, nCol))
{
// swap the rows
int nColCount =((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
rowText.SetSize( nColCount );
for( i=0; i<nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED | 
LVIS_FOCUSED |  LVIS_SELECTED | 
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK; lvitemhi = lvitemlo;
lvitemhi.iItem = hi; GetItem( &lvitemlo );
GetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i)); lvitemhi.iItem = lo;
SetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(hi, i, rowText[i]); lvitemlo.iItem = hi;
SetItem( &lvitemlo );
} ++lo;
--hi;
}
} // If the right index has not reached the left side of array
// must now sort the left partition.
if( low < hi )
SortTextItems( nCol, bAscending , low, hi,bIsNumber); // If the left index has not reached the right side of array
// must now sort the right partition.
if( lo < high )
SortTextItems( nCol, bAscending , lo, high,bIsNumber); return TRUE;
}

解决方案 »

  1.   

    可能会有点错误,你自己看情况改一下
    BOOL IsAllNumber(CString str)//这个函数判断某个字符串是不是全是数字
    {
    int i;
    i=atoi(str);
    CString strComp;
    strComp.Format("%d",i);
    if (str==strComp) 
    return TRUE;
    else
    return FALSE;

    }
    BOOL CSortFileList::SortTextItems(int nCol, BOOL bAscending, int low, int high,BOOL bIsNumber)
    {
    int i;
    int lo = low;
    int hi = high;
    CString  midItem;
    CStringArray rowText;
    LV_ITEM lvitemlo, lvitemhi;
    if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
    return FALSE;

    if( high == -1 ) high = GetItemCount() - 1; if( hi <= lo ) return FALSE; midItem = GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
    while( lo <= hi )
    {
    // rowText will hold all column text for one row
    // find the first element that is greater than or equal to 
    // the partition element starting from the left Index.
    //判断:如果全是数字的话,采用数字的比较
    if(IsAllNumber(midItem) && IsAllNumber(GetItemText(lo, nCol))
    {
    if( bAscending )
    while( ( lo < high ) && ( atoi(GetItemText(lo, nCol)) < atoi(midItem) ) )
    ++lo;
    else
    while( ( lo < high ) && ( atoi(GetItemText(lo, nCol)) > atoi(midItem) ) )
    ++lo; // find an element that is smaller than or equal to 
    // the partition element starting from the right Index.
    if( bAscending )
    while( ( hi > low ) && ( atoi(GetItemText(hi, nCol)) > atoi(midItem) ) )
    --hi;
    else
    while( ( hi > low ) && ( atoi(GetItemText(hi, nCol)) < atoi(midItem )) )
    --hi; }elseif{//下面是原来的字符串比较
    if( bAscending )
    while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
    ++lo;
    else
    while( ( lo < high ) && ( GetItemText(lo, nCol) > midItem ) )
    ++lo; // find an element that is smaller than or equal to 
    // the partition element starting from the right Index.
    if( bAscending )
    while( ( hi > low ) && ( GetItemText(hi, nCol) > midItem ) )
    --hi;
    else
    while( ( hi > low ) && ( GetItemText(hi, nCol) < midItem ) )
    --hi;
    }
    // if the indexes have not crossed, swap
    // and if the items are not equal
    if( lo <= hi )
    {
    // swap only if the items are not equal
    if( GetItemText(lo, nCol) != GetItemText(hi, nCol))
    {
    // swap the rows
    int nColCount =((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
    rowText.SetSize( nColCount );
    for( i=0; i<nColCount; i++)
    rowText[i] = GetItemText(lo, i);
    lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
    lvitemlo.iItem = lo;
    lvitemlo.iSubItem = 0;
    lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED | 
    LVIS_FOCUSED |  LVIS_SELECTED | 
    LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK; lvitemhi = lvitemlo;
    lvitemhi.iItem = hi; GetItem( &lvitemlo );
    GetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
    SetItemText(lo, i, GetItemText(hi, i)); lvitemhi.iItem = lo;
    SetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
    SetItemText(hi, i, rowText[i]); lvitemlo.iItem = hi;
    SetItem( &lvitemlo );
    } ++lo;
    --hi;
    }
    } // If the right index has not reached the left side of array
    // must now sort the left partition.
    if( low < hi )
    SortTextItems( nCol, bAscending , low, hi,bIsNumber); // If the left index has not reached the right side of array
    // must now sort the right partition.
    if( lo < high )
    SortTextItems( nCol, bAscending , lo, high,bIsNumber); return TRUE;
    }
      

  2.   

    上面的是错的,这下应该没问题了
    BOOL IsAllNumber(CString str)
    {
    int i;
    i=atoi(str);
    CString strComp;
    strComp.Format("%d",i);
    if (str==strComp) 
    return TRUE;
    else
    return FALSE;

    }
    BOOL CompString(CString str1,CString str2,BOOL oper)
    {
    //oper=TRUE是判断大于,否则判断小于
    if (IsAllNumber(str1) && IsAllNumber(str2)) {
    if ((atoi(str1)>atoi(str2)) && oper ) {
    return TRUE;
    }
    else{
    return FALSE;
    }
    }
    if ((str1 > str2) && oper) {
    return TRUE;
    }
    else{
    return FALSE; }
    }
    BOOL CSortFileList::SortTextItems(int nCol, BOOL bAscending, int low, int high,BOOL bIsNumber)
    {
    int i;
    int lo = low;
    int hi = high;
    CString  midItem;
    CStringArray rowText;
    LV_ITEM lvitemlo, lvitemhi; if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
    return FALSE;

    if( high == -1 ) high = GetItemCount() - 1; if( hi <= lo ) return FALSE; midItem = GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
    while( lo <= hi )
    {
    // rowText will hold all column text for one row
    // find the first element that is greater than or equal to 
    // the partition element starting from the left Index.
    if( bAscending )
    while( ( lo < high ) && ( CompString(GetItemText(lo, nCol),midItem,FALSE)) )
    ++lo;
    else
    while( ( lo < high ) && ( CompString(GetItemText(lo, nCol),midItem,TRUE)) )
    ++lo; // find an element that is smaller than or equal to 
    // the partition element starting from the right Index.
    if( bAscending )
    while( ( hi > low ) && ( CompString(GetItemText(hi, nCol),midItem, TRUE)  ) )
    --hi;
    else
    while( ( hi > low ) && ( CompString(GetItemText(hi, nCol), midItem,FALSE )) )
    --hi; // if the indexes have not crossed, swap
    // and if the items are not equal
    if( lo <= hi )
    {
    // swap only if the items are not equal
    if( GetItemText(lo, nCol) != GetItemText(hi, nCol))
    {
    // swap the rows
    int nColCount =((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
    rowText.SetSize( nColCount );
    for( i=0; i<nColCount; i++)
    rowText[i] = GetItemText(lo, i);
    lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
    lvitemlo.iItem = lo;
    lvitemlo.iSubItem = 0;
    lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED | 
    LVIS_FOCUSED |  LVIS_SELECTED | 
    LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK; lvitemhi = lvitemlo;
    lvitemhi.iItem = hi; GetItem( &lvitemlo );
    GetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
    SetItemText(lo, i, GetItemText(hi, i)); lvitemhi.iItem = lo;
    SetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
    SetItemText(hi, i, rowText[i]); lvitemlo.iItem = hi;
    SetItem( &lvitemlo );
    } ++lo;
    --hi;
    }
    } // If the right index has not reached the left side of array
    // must now sort the left partition.
    if( low < hi )
    SortTextItems( nCol, bAscending , low, hi,bIsNumber); // If the left index has not reached the right side of array
    // must now sort the right partition.
    if( lo < high )
    SortTextItems( nCol, bAscending , lo, high,bIsNumber); return TRUE;
    }
      

  3.   

    /*请参考如下代码,关键要将列表的显示数据格式和要排列的数据分开处理,比如显示的数据是:
    123
    21
    32
    但是格式化的数据为:
    0000123
    0000021
    0000032
    这样处理的数据显示肯定没问题*///首先声明全局结构
    typedef struct{
    CString strFileName;
    CString strFileSize;
    }ITEMDATA,*PITEMDATA;//在产生列表时填充该结构的实例
    sFileSizeSort.Format("%20.0fKB",fFileSize);pData=new ITEMDATA;
    pData->strFileName=sFileName;
    //用格式化的数据填充全局结构的实例,用来排序(0000123,0000021,0000032)
    pData->strFileSize=sFileSizeSort;//同时填充列表
    m_lstFileList.AddItem(lFileCnt,0,wfd.cFileName,1);
    //用未格式化的数据填充列表(123,21,32)
    m_lstFileList.AddItem(lFileCnt,2,sFileSize);
    m_lstFileList.SetItemData(lFileCnt,(LPARAM)pData);//在列表的表头发生鼠标单击事件时
    {
      HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
      CListCtrlEx* pList=(CListCtrlEx*)GetDlgItem(IDC_LIST_FILELIST);
      static int i;
      if(i==0){
        pList->SortItems(SortFuncASC,phdn->iItem);
        i=1;
        *pResult = 0;
        return;
      }
      if(i==1){
        pList->SortItems(SortFuncDESC,phdn->iItem);
        i=0;
        *pResult = 0;
        return;
      }
    }
    //升序函数
    int CALLBACK SortFuncASC(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
      int nRtnVal;
      PITEMDATA pData1=(PITEMDATA)lParam1;
      PITEMDATA pData2=(PITEMDATA)lParam2;
      switch(lParamSort)
      {
      case 0:
        nRtnVal=strcmp(pData1->strFileName,pData2->strFileName);
        break;
      case 2:
        nRtnVal=strcmp(pData1->strFileSize,pData2->strFileSize);
        break;
      default:
        break;
     }
     return nRtnVal;
    }
    //降序函数
    int CALLBACK SortFuncDESC(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
      int nRtnVal;
      PITEMDATA pData1=(PITEMDATA)lParam1;
      PITEMDATA pData2=(PITEMDATA)lParam2;
      switch(lParamSort)
     {
      case 0:
        nRtnVal=strcmp(pData2->strFileName,pData1->strFileName);
        break;
      case 2:
        nRtnVal=strcmp(pData2->strFileSize,pData1->strFileSize);
        break;
      default:
        break;
     }
     return nRtnVal;
    }
      

  4.   

    To: rengo,结果还有不行。后来我将重写了。现在可以了。谢谢!