我发现,执行字符串的“自然比较” Windows API函数。 它定义如下:
int StrCmpLogicalW(
LPCWSTR psz1,
LPCWSTR psz2
);
为了在Delphi中使用它,我宣布这样说:
interface
function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
因为它比较的Unicode字符串,我不知道如何调用它时,我想比较ANSI字符串。 这似乎是足够的施展串WideString的,然后到PWideChar,不过,我不知道这种做法是否正确:
function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;
我知道很少的字符编码,所以这是我的问题的原因。 这是OK功能或者我应该先以某种方式转换都比较字符串?
请记住,铸造一个字符串转换为WideString的使用将默认系统代码页可能会或可能不会是你所需要的转换。 通常情况下,你想使用当前用户的语言环境。
从WCharFromChar
在System.pas:
Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes,
WCharDest, DestChars);
你可以通过调用改变DefaultSystemCodePage SetMultiByteConversionCodePage 。
完成该任务的更简单的方法是声明你的功能:
interface
function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
因为一个WideString
变量是指向一个WideChar
(以同样的方式的AnsiString
变量是指向一个AnsiChar
。)
而这样一来Delphi会自动“向上转换”的AnsiString类型的WideString
为您服务。
更新
而且,由于我们的世界现在已经UnicodeString
,你会做它:
interface
function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
因为一个UnicodeString
变量仍然是一个指针,指向一个\0\0
的终止字符串WideChars
。 所以,如果你拨打:
var
s1, s1: AnsiString;
begin
s1 := 'Hello';
s2 := 'world';
nCompare := StrCmpLogicalW(s1, s2);
end;
当您尝试通过一个AnsiString
成需要的功能UnicodeString
,编译器会自动调用MultiByteToWideChar
在生成的代码为您服务。
CompareString支持数字排序在Windows 7
在Windows 7开始,微软添加SORT_DIGITSASNUMBERS
到CompareString
:
视窗7:“10”之前,在排序过程中对待位数字,例如,排序“2”。
这一切都不有助于回答的实际问题,这与当你不得不转换或铸造字符串交易。
有可能是一个ANSI变种作为你的功能(我没有检查)。 最全的API可作为一个ANSI版本太多,只是改变后缀W到A,和你设置。 Windows不会背的反复转换transparantly你在这种情况下。
PS:这里的描述缺乏StrCmpLogicalA的文章: http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx
使用System.StringToOleStr
,这大约是一个方便的包装MultiByteToWideChar
,看到贾布尔的回答 :
function AnsiNaturalCompareText(const S1, S2: string): integer;
var
W1: PWideChar;
W2: PWideChar;
begin
W1 := StringToOleStr(S1);
W2 := StringToOleStr(S2);
Result := StrCmpLogicalW(W1, W2);
SysFreeString(W1);
SysFreeString(W2);
end;
但后来, 伊恩·博伊德的解决方案看起来是好得多!