字符串逻辑比较函数---StrCmpLogicalW的模拟实现

    我们最熟悉的字符串比较函数莫过于strcmp了,但这个函数仅仅是根据字符进行比较,没有考虑字符串的逻辑意义,为此微软为我们提供了一个StrCmpLogicalW函数,它比较数字时不将其视为文本而是视为数值。

我们可以从下列这个简单的字符串数组排序的结果看出这两个函数的区别:

使用StrCmpLogicalW进行比较的结果:

复制代码
2string
3string
20string
st2ring
st3ring
st20ring
string2
string3
string20
复制代码
  使用简单的strcmp函数进行比较的结果:
复制代码
20string
2string
3string
st20ring
st2ring
st3ring
string2
string20
string3
复制代码

下面这段代码就是模仿这个函数的实现:

复制代码
#include <iostream>
#include 
<afx.h>
#include 
"deelx.h"
using namespace std;

#define MATCH_NUMBERS "[+-]?\\d+(\\.\\d+)?"


 
int Compare(CString csText1, CString csText2)
{
        
static CRegexp reg(MATCH_NUMBERS);
        
int nEnd1 = 0, nEnd2 = 0;
        
        
while(1)
        
{
            MatchResult ret1 
= reg.Match(csText1, nEnd1);
            MatchResult ret2 
= reg.Match(csText2, nEnd2);
            
            CString 
const& csSubText1 = ret1.IsMatched() ? csText1.Mid(nEnd1, ret1.GetStart() - nEnd1) : csText1;
            CString 
const& csSubText2 = ret2.IsMatched() ? csText2.Mid(nEnd2, ret2.GetStart() - nEnd2) : csText2;
            
            
//子串不同,则返回
            if (csSubText1 != csSubText2)
                
return csSubText1 > csSubText2 ? 1 : -1;
            
            
/*
                既然两个字符串相等, 而两个字符串又已经消耗完, 那自然可以返回了.
            
*/

            
if (! ret1.IsMatched() && ! ret2.IsMatched()) return 0;
            
            
if (ret1.IsMatched() && ret2.IsMatched())
            
{//字符串还未消耗完毕,继续按逻辑比较
                /* 
                    GetGroupStart() 返回正则表达式中"(\\.\\d+)" 这一个组的起始位置. 如果没有匹配, 则返回-1; (可查看deelx 的说明文档) 
                    这个组是否匹配意味着捕获的数字是否带有小数点以及小数部分.
                    如果捕获的两个数字有一个带有小数部分. 则按浮点数处理. 否则按整数处理
                
*/

                
if (ret1.GetGroupStart(1>= 0 || ret2.GetGroupStart(1>= 0)
                
{//带小数点,按浮点数比较数值大小
                    double dNum1 = _tcstod(csText1.Mid(ret1.GetStart(), ret1.GetEnd() - ret1.GetStart()), 0);
                    
double dNum2 = _tcstod(csText2.Mid(ret2.GetStart(), ret2.GetEnd() - ret2.GetStart()), 0);
                    
if (dNum1 != dNum2) return dNum1 > dNum2 ? 1 : -1;
                }

                
else
                
{//按整数处理,比较两个数的数值大小
                    __int64 nNum1 = _ttoi64(csText1.Mid(ret1.GetStart(), ret1.GetEnd() - ret1.GetStart()));
                    __int64 nNum2 
= _ttoi64(csText2.Mid(ret2.GetStart(), ret2.GetEnd() - ret2.GetStart()));
                    
if (nNum1 != nNum2) return nNum1 > nNum2 ? 1 : -1;
                }

                
                nEnd1 
= ret1.GetEnd();
                nEnd2 
= ret2.GetEnd();
            }

            
else
            
{//现在两个里面肯定有且只有一个IsMatch() 不为真
                return ret1.IsMatched() ? 1 : -1;
            }

        }

        
return 0;
    }


 
int main()
{
    CString str1(
"st3ring"),str2 ("st20ring");
    
int result;
    result 
= Compare(str1,str2);
    std::cout
<<"result is: "<<result<<endl;
    result 
= strcmp(str1.GetBuffer(10),str2.GetBuffer(10));
    cout
<<"result is: "<<result<<endl;
    system(
"pause");
    
return 0;
}

复制代码

代码中使用了一个开源的正则表达式引擎,DEELX 正则表达式引擎

posted on   Phinecos(洞庭散人)  阅读(2538)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
历史上的今天:
2007-07-06 SWT Designer 6.0安装小记

导航

统计

点击右上角即可分享
微信分享提示