È necessario convertire la stringa in WideString in Delphi?
-
06-07-2019 - |
Domanda
Ho trovato una funzione API di Windows che esegue il "confronto naturale" di stringhe. È definito come segue:
int StrCmpLogicalW(
LPCWSTR psz1,
LPCWSTR psz2
);
Per usarlo in Delphi, l'ho dichiarato in questo modo:
interface
function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Poiché confronta le stringhe Unicode , non sono sicuro di come chiamarlo quando vuoi confrontare le stringhe ANSI. Sembra essere abbastanza per lanciare stringhe su WideString e poi su PWideChar, tuttavia, non ho idea se questo approccio sia corretto:
function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;
So molto poco sulla codifica dei caratteri, quindi questa è la ragione della mia domanda. Questa funzione è OK o devo prima convertire entrambe le stringhe confrontate in qualche modo?
Soluzione
Tieni presente che il cast di una stringa in WideString la convertirà utilizzando la tabella codici di sistema predefinita che potrebbe essere o meno ciò di cui hai bisogno. In genere, si desidera utilizzare le impostazioni internazionali dell'utente corrente.
Da WCharFromChar
in System.pas:
Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes,
WCharDest, DestChars);
È possibile modificare DefaultSystemCodePage chiamando .
Altri suggerimenti
Il modo più semplice per eseguire l'attività sarebbe dichiarare la tua funzione come:
interface
function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Poiché una variabile WideString
è un puntatore a una WideChar
(allo stesso modo una variabile AnsiString
< em> è un puntatore a un AnsiChar
.)
E in questo modo Delphi automaticamente "quot-up-convert" " un AnsiString per un WideString
per te.
Aggiornamento
E poiché ora siamo nel mondo di UnicodeString
, dovresti farcela:
interface
function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall;
implementation
function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Perché una variabile UnicodeString
è ancora un puntatore a una stringa terminata \ 0 \ 0
di WideChars
. Quindi se chiami:
var
s1, s1: AnsiString;
begin
s1 := 'Hello';
s2 := 'world';
nCompare := StrCmpLogicalW(s1, s2);
end;
Quando provi a passare un AnsiString
in una funzione che accetta un UnicodeString
, il compilatore chiamerà automaticamente MultiByteToWideChar
per te nel generato codice.
CompareString supporta l'ordinamento numerico in Windows 7
A partire da Windows 7, Microsoft ha aggiunto SORT_DIGITSASNUMBERS
a CompareString
:
Windows 7: considera le cifre come numeri durante l'ordinamento, ad esempio ordina " 2 " prima di "10".
Niente di tutto ciò aiuta a rispondere alla effettiva domanda, che riguarda quando devi convertire o lanciare stringhe.
Potrebbe esserci una variante ANSI per la tua funzione (non ho verificato). La maggior parte delle API Wide sono disponibili anche come versione ANSI, basta cambiare il suffisso W in una A e il gioco è fatto. In questo caso Windows esegue la conversione avanti e indietro in modo trasparente per te.
PS: ecco un articolo che descrive la mancanza di StrCmpLogicalA: http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx
Usa System.StringToOleStr
, che è un utile wrapper per MultiByteToWideChar
, vedi Risposta di 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;
Ma poi, La soluzione di Ian Boyd sembra ed è molto più bella!