是否有必要在Delphi中将字符串转换为WideString?
-
06-07-2019 - |
题
我找到了一个执行“自然比较”功能的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会使用默认系统代码页转换它,这可能是您需要的,也可能不是。通常,您需要使用当前用户的区域设置。
来自System.pas中的 WCharFromChar
:
Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes,
WCharDest, DestChars);
您可以通过调用 SetMultiByteConversionCodePage <来更改DefaultSystemCodePage / A>
其他提示
完成任务的更简单方法是将您的函数声明为:
interface
function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
因为 WideString
变量是指向 WideChar
的指针(与 AnsiString
变量<相同) em>是指向 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开始,Microsoft将 SORT_DIGITSASNUMBERS
添加到 CompareString
:
Windows 7:在排序过程中将数字视为数字,例如,排序“2”。在“10”之前。
这些都无法解答实际问题,该问题涉及何时必须转换或投射字符串。
您的函数可能有一个ANSI变体(我没有检查过)。大多数Wide API也可以作为ANSI版本使用,只需将W后缀更改为A,即可设置。在这种情况下,Windows会为您进行交互式转换。
PS:这是一篇描述缺乏StrCmpLogicalA的文章: http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx
使用 System.StringToOleStr
,是 MultiByteToWideChar
的便捷包装,请参阅 Gabr的回答:
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;
但是, Ian Boyd的解决方案看起来更好!