我们最熟悉的字符串比较函数莫过于
strcmp
了,但这个函数仅仅是根据字符进行比较,没有考虑字符串的逻辑意义,为此微软为我们提供了一个
StrCmpLogicalW
函数,它比较数字时不将其视为文本而是视为数值。
我们可以从下列这个简单的字符串数组排序的结果看出这两个函数的区别:
使用StrCmpLogicalW进行比较的结果:
2string
3string
20string
st2ring
st3ring
st20ring
string2
string3
string20
使用简单的
strcmp
函数进行比较的结果:3string
20string
st2ring
st3ring
st20ring
string2
string3
string20
20string
2string
3string
st20ring
st2ring
st3ring
string2
string20
string3
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;
}
#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 正则表达式引擎,