Est-il nécessaire de convertir string en WideString dans Delphi?

j'ai trouvé une fonction API Windows qui effectue une "comparaison naturelle" des chaînes. Il est défini comme suit:

int StrCmpLogicalW(
    LPCWSTR psz1,
    LPCWSTR psz2
);

Pour l'utiliser en Delphi, je l'ai déclaré cette façon:

interface
  function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;

implementation
  function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

Parce qu'il compare Unicode strings, Je ne sais pas comment l'appeler quand je veux comparer les strings ANSI. Il semble qu'il suffise de lancer des cordes à WideString et ensuite à PWideChar, cependant, je n'ai aucune idée si cette approche est correcte:

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

je sais très peu de choses sur l'encodage des caractères c'est donc la raison de ma question. Est-ce que cette fonction est OK ou dois-je d'abord convertir les deux chaînes comparées d'une façon ou d'une autre?

18
demandé sur Peter Mortensen 2009-06-21 22:50:30

4 réponses

gardez à l'esprit que le casting d'une chaîne de caractères à un WideString la convertira en utilisant le codepage du système par défaut qui peut ou non être ce dont vous avez besoin. Typiquement, vous voulez utiliser la locale de l'utilisateur courant.

WCharFromChar dans le Système.pas:

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

11
répondu gabr 2012-04-20 17:47:15

la façon La plus facile à accomplir la tâche serait de déclarer votre fonction:

interface
   function StrCmpLogicalW(const sz1, sz2: WideString): Integer; stdcall;

implementation
   function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

parce que a WideString variable un pointeur vers un WideChar (de la même manière un AnsiString variable un pointeur vers un AnsiChar.)

Et ainsi Delphi "up-convert" automatiquement une réponse à un WideString pour vous.

mise à Jour

Et puisque nous sommes maintenant dans le monde de l' UnicodeString, vous feriez c':

interface
   function StrCmpLogicalW(const sz1, sz2: UnicodeString): Integer; stdcall;

implementation
   function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';

parce que a UnicodeString variable est toujours un pointeur vers un terminà © chaîne de WideChars. Donc, si vous appelez:

var
    s1, s1: AnsiString;
begin
    s1 := 'Hello';
    s2 := 'world';

    nCompare := StrCmpLogicalW(s1, s2);
end;

Lorsque vous essayez de passer un AnsiString dans une fonction qui prend un UnicodeString, le compilateur appellera automatiquement MultiByteToWideChar pour vous dans le code généré.

CompareString supporte le tri numérique dans Windows 7

À partir de Windows 7, Microsoft a ajouté SORT_DIGITSASNUMBERS pour CompareString:

Windows 7: traiter les chiffres comme des nombres lors du tri, par exemple, trier "2" avant "10".

rien de tout cela n'aide à répondre à la question, qui traite du moment où vous devez convertir ou lancer des cordes.

5
répondu Ian Boyd 2014-08-14 18:15:46

il pourrait y avoir une variante ANSI pour votre fonction à (je n'ai pas vérifié). Les API les plus larges sont disponibles en version ANSI aussi, il suffit de changer le suffixe W en un A, et vous êtes prêt. Windows fait la conversion de va-et-vient de manière transparente pour vous dans ce cas.

PS: voici un article décrivant le manque de StrCmpLogicalA:http://blogs.msdn.com/joshpoley/archive/2008/04/28/strcmplogicala.aspx

3
répondu PatrickvL 2009-06-21 19:22:10

Utiliser System.StringToOleStr, ce qui est pratique un wrapper autour de MultiByteToWideChar réponse 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;

Mais alors, la solution de Ian Boyd regarde et est beaucoup plus agréable!

2
répondu NGLN 2017-05-23 12:16:27