delphi string widestring

¿Es necesario convertir la cadena a WideString en Delphi?



(4)

La forma más fácil de realizar la tarea sería declarar su función como:

interface function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall; implementation function StrCmpLogicalW; external ''shlwapi.dll'' name ''StrCmpLogicalW'';

Debido a que una variable WideString es un puntero a un WideChar (de la misma manera que una variable AnsiString es un puntero a un AnsiChar .)

Y de esta manera, Delphi automáticamente "convertirá" una AnsiString en una WideString para usted.

Actualizar

Y como ahora estamos en el mundo de UnicodeString , lo lograrías:

interface function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall; implementation function StrCmpLogicalW; external ''shlwapi.dll'' name ''StrCmpLogicalW'';

Debido a que una variable UnicodeString sigue siendo un puntero a una cadena terminada /0/0 de WideChars . Así que si llamas:

var s1, s1: AnsiString; begin s1 := ''Hello''; s2 := ''world''; nCompare := StrCmpLogicalW(s1, s2); end;

Cuando intenta pasar un AnsiString a una función que toma un UnicodeString , el compilador llamará automáticamente a MultiByteToWideChar en el código generado.

CompareString admite la ordenación numérica en Windows 7

A partir de Windows 7, Microsoft agregó SORT_DIGITSASNUMBERS a CompareString :

Windows 7: trate los dígitos como números durante la clasificación, por ejemplo, ordene "2" antes de "10".

Nada de esto ayuda a responder la pregunta real , que trata de cuándo se deben convertir o lanzar cadenas.

Encontré una función de API de Windows que realiza una "comparación natural" de cadenas. Se define de la siguiente manera:

int StrCmpLogicalW( LPCWSTR psz1, LPCWSTR psz2 );

Para usarlo en Delphi, lo declaré así:

interface function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall; implementation function StrCmpLogicalW; external ''shlwapi.dll'' name ''StrCmpLogicalW'';

Debido a que compara las cadenas Unicode , no estoy seguro de cómo llamarlo cuando quiero comparar cadenas ANSI. Parece ser suficiente para enviar cadenas a WideString y luego a PWideChar, sin embargo, no tengo idea de si este enfoque es correcto:

function AnsiNaturalCompareText(const S1, S2: string): integer; begin Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2))); end;

Sé muy poco acerca de la codificación de caracteres, por lo que esta es la razón de mi pregunta. ¿Esta función es correcta o debo convertir primero las cadenas comparadas de alguna manera?


Puede que haya una variante ANSI para su función (no he comprobado). La mayoría de las APIs anchas también están disponibles como una versión ANSI, simplemente cambie el sufijo W a una A, y listo. Windows hace la conversión de ida y vuelta de forma transparente para usted en ese caso.

PD: Aquí hay un artículo que describe la falta de StrCmpLogicalA: http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx


Tenga en cuenta que convertir una cadena en una WideString la convertirá usando la página de códigos predeterminada del sistema, que puede o no ser lo que necesita. Por lo general, desearías usar la configuración regional del usuario actual.

Desde WCharFromChar en System.pas:

Result := MultiByteToWideChar(DefaultSystemCodePage, 0, CharSource, SrcBytes, WCharDest, DestChars);

Puede cambiar SetMultiByteConversionCodePage llamando a SetMultiByteConversionCodePage .


Use System.StringToOleStr , que es un envoltorio práctico alrededor de MultiByteToWideChar , vea la respuesta de 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;

Pero entonces, ¡ la solución de Ian Boyd se ve y es mucho mejor!