Question

J'ai trouvé une fonction API Windows qui effectue la "comparaison naturelle". de cordes. Il est défini comme suit:

int StrCmpLogicalW(
    LPCWSTR psz1,
    LPCWSTR psz2
);

Pour l'utiliser dans Delphi, je l'ai déclaré ainsi:

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

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

Comme il compare les chaînes Unicode , je ne sais pas comment l'appeler quand je vouloir comparer les chaînes ANSI. Il semble suffisant de lancer des chaînes dans WideString, puis dans PWideChar. Cependant, je ne sais pas du tout si cette approche est correcte:

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

Je connais très peu le codage de caractères, c’est la raison de ma question. Cette fonction est-elle correcte ou devrais-je d'abord convertir les deux chaînes comparées d'une manière ou d'une autre?

Était-ce utile?

La solution

N'oubliez pas que la conversion d'une chaîne en chaîne WideString la convertira à l'aide de la page de code système par défaut, qui peut ne pas correspondre à vos besoins. En règle générale, vous souhaitez utiliser les paramètres régionaux de l'utilisateur actuel.

À partir de WCharFromChar dans System.pas:

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

Vous pouvez modifier la valeur de DefaultSystemCodePage en appelant .

Autres conseils

Le moyen le plus simple d’accomplir cette tâche serait de déclarer votre fonction comme suit:

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

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

Parce qu'une variable WideString est un pointeur sur un WideChar (de la même manière qu'une variable AnsiString em> est un pointeur sur un AnsiChar .)

Et ainsi, Delphi va automatiquement "convertir vers le haut". une AnsiString en WideString pour vous.

Mettre à jour

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

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

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

Parce qu'une variable UnicodeString est toujours un pointeur sur une chaîne \ 0 \ 0 terminée par 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 prenant un UnicodeString , le compilateur appellera automatiquement MultiByteToWideChar pour vous dans le fichier généré. code.

CompareString prend en charge le tri numérique dans Windows 7

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

  

Windows 7: considérez les chiffres comme des nombres lors du tri. Par exemple, triez les mots "2". avant "10".

Rien de tout cela n'aide à répondre à la question actuelle , qui concerne le moment où vous devez convertir ou convertir des chaînes.

Il pourrait y avoir une variante ANSI pour votre fonction (je n'ai pas vérifié). La plupart des API Wide sont également disponibles en version ANSI. Il suffit de remplacer le suffixe W par un A et le jeu est défini. Dans ce cas, Windows effectue la conversion en arrière-plan de manière transparente.

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

Utilisez System.StringToOleStr , qui est un encapsuleur pratique autour de MultiByteToWideChar , voir 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 dans ce cas, la solution de Ian Boyd est beaucoup plus agréable!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top