字符串逻辑比较函数---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;
}

复制代码



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/07/06/1236910.html,如需转载请自行联系原作者
目录
相关文章
|
Java 调度 Android开发
构建高效Android应用:探究Kotlin多线程编程
【2月更文挑战第17天】 在现代移动开发领域,性能优化一直是开发者关注的焦点。特别是在Android平台上,合理利用多线程技术可以显著提升应用程序的响应性和用户体验。本文将深入探讨使用Kotlin进行Android多线程编程的策略与实践,旨在为开发者提供系统化的解决方案和性能提升技巧。我们将从基础概念入手,逐步介绍高级特性,并通过实际案例分析如何有效利用Kotlin协程、线程池以及异步任务处理机制来构建一个更加高效的Android应用。
|
机器学习/深度学习 调度
详解 Diffusion (扩散) 模型
详解 Diffusion (扩散) 模型
|
4月前
|
人工智能 自然语言处理 搜索推荐
Qwen 家族再上新!
Qwen3 Embedding 是基于 Qwen3 基础模型训练的文本嵌入模型系列,可将离散符号转化为连续向量,捕捉语义关系。结合 Qwen3 Reranker 模型,通过“初筛+精排”流程提升搜索与推荐系统的相关性排序能力。该系列模型支持多语言、提供灵活架构(0.6B-8B 参数规模),并在 MTEB 多语言榜单中排名第一。用户可通过 Hugging Face、ModelScope 和 GitHub 快速体验模型服务。
349 1
|
9月前
|
存储 编译器 C语言
深入理解GCC 和 G++ 编译器
GCC 和 G++ 是 GNU 工具链中的核心编译器,支持 C 和 C++ 程序开发。本文详细介绍其编译流程、常用选项及动态链接与静态链接的区别。编译过程分为预处理、编译、汇编和链接四个阶段,每个阶段有特定任务和命令选项。常用选项如 `-E`、`-S`、`-c` 和 `-o` 分别用于预处理、生成汇编代码、生成目标文件和指定输出文件。动态链接节省空间且易于更新,但依赖运行时库;静态链接独立高效,但文件较大且更新困难。合理选择优化选项(如 `-O0` 至 `-O3`)可提升程序性能。掌握这些知识有助于开发者更高效地编写、调试和优化代码。
379 23
深入理解GCC 和 G++ 编译器
python打包pyinstaller如何使用
解决打包时缺失`libpython3.so`的问题,需确保Python在编译时使用`--enable-shared`选项以支持共享库模式。之后,将生成的`libpython3.so`及`libpython3.9.so.1.0`复制到系统库目录`/usr/lib64`。参考链接提供详细步骤。
|
人工智能 自然语言处理 安全
使用阿里云服务网格高效管理LLM流量:(一)流量路由
ASM支持通过LLMProvider和LLMRoute资源管理大型语言模型流量。LLMProvider负责注册LLM服务,LLMRoute负责设定流量规则,应用可灵活切换模型,满足不同场景需求。
|
存储 缓存 并行计算
Transformers 4.37 中文文档(九十九)(8)
Transformers 4.37 中文文档(九十九)
388 0
|
Java 开发工具 Android开发
鸿蒙HarmonyOS 与 Android 的NDK有什么区别?
鸿蒙(HarmonyOS)和Android的NDK(Native Development Kit)是两个不同的概念,它们在设计理念、架构、开发方式和目标平台等方面存在着一些显著的不同。
863 0
|
Linux 网络安全 开发工具
一个固定 WSL2 ip 的简单方法
本文介绍了如何在Win11 22H2及以上版本中让WSL与Windows共享IP,避免重启后IP变化带来的问题。只需在用户目录下创建`.wslconfig`文件,输入特定配置并重启WSL,即可实现IP一致,简化WSL网络设置。此外,还提供了一种在其他系统版本中通过Windows SSH连接WSL的替代方法。
3760 0
|
存储 安全 API
阿里云——云存储:对象存储管理与安全
阿里云——云存储:对象存储管理与安全
925 0