Ist es notwendig, String Wide in Delphi zu konvertieren?
-
06-07-2019 - |
Frage
fand ich eine Windows-API-Funktion, die „natürliche Vergleich“ von Strings führt. Es ist wie folgt definiert:
int StrCmpLogicalW(
LPCWSTR psz1,
LPCWSTR psz2
);
Um es in Delphi zu verwenden, ich erklärte es so:
interface
function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Weil es vergleicht Unicode Strings, ich bin nicht sicher, wie es rufen, wenn ich wollen ANSI-Zeichenfolgen vergleichen. Es scheint genug zu sein, Strings Wide zu werfen und dann zu PWideChar aber ich habe keine Ahnung, ob dieser Ansatz richtig ist:
function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;
Ich weiß sehr wenig über Zeichencodierung so das der Grund meiner Frage. Ist diese Funktion OK oder sollte ich zuerst konvertieren beide die verglichenen Strings irgendwie?
Lösung
Beachten Sie, dass eine Zeichenfolge in einem Wide Casting konvertiert es Standard-System-Codepage verwendet, die möglicherweise oder möglicherweise nicht, was Sie brauchen. Typischerweise würde, Sie möchten aktuellen Benutzers Gebietsschema verwenden.
Von WCharFromChar
in System.pas:
Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes,
WCharDest, DestChars);
Sie können DefaultSystemCodePage ändern, indem Aufruf SetMultiByteConversionCodePage .
Andere Tipps
Je einfacher Weg, um die Aufgabe zu erfüllen wäre, um Ihre Funktion zu erklären, wie:
interface
function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Da eine WideString
Variable ist ein Zeiger auf einen WideChar
(in gleicher Weise eine AnsiString
Variable ist ein Zeiger auf einen AnsiChar
.)
Und auf diese Weise Delphi automatisch "up-convert" ein Ansistring zu einem WideString
für Sie.
Update
Und da wir jetzt in der Welt der UnicodeString
sind, dann würden Sie es machen:
interface
function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Da eine UnicodeString
Variable noch ein Zeiger auf ein \0\0
terminierten String von WideChars
ist. Also, wenn Sie anrufen:
var
s1, s1: AnsiString;
begin
s1 := 'Hello';
s2 := 'world';
nCompare := StrCmpLogicalW(s1, s2);
end;
Wenn Sie versuchen, eine AnsiString
in eine Funktion zu übergeben, die eine UnicodeString
nimmt, wird der Compiler automatisch MultiByteToWideChar
für Sie in den generierten Code aufrufen.
CompareString unterstützt numerische Sortierung in Windows 7
Starten in Windows 7, Microsoft hinzugefügt SORT_DIGITSASNUMBERS
auf CompareString
:
Windows 7:. Treat Ziffern als Zahlen während des Sortierens, beispielsweise sortieren "2" vor "10"
All dies hilft, beantworten Sie die ist Frage, die mit beschäftigt, wenn Sie konvertieren oder gegossene Saiten.
Es kann eine ANSI-Variante für Ihre Funktion sein (ich nicht überprüft haben). Die meisten Weit API sind als eine ANSI-Version auch nur das W-Suffix zu einem A ändern, und Sie werden eingestellt. Windows macht die Hin-und-her Umwandlung in transparenter Weise für Sie in diesem Fall.
PS: Hier ist ein Artikel den Mangel an StrCmpLogicalA beschreiben: http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx
Verwenden Sie System.StringToOleStr
, die um MultiByteToWideChar
eine handliche Wrapper finden Sie unter < a href = "https://stackoverflow.com/a/1025852/757830"> Gabr Antwort :
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;
Aber dann Ian Boyd Lösung aussieht und ist viel schöner!