2010-11-21 41 views
16

J'ai mis à jour une application de Delphi 2007 à Delphi 2010, tout allait bien, sauf une déclaration qui a compilé bien, mais ne fonctionne pas qui est:CharInSet ne fonctionne pas avec des lettres non anglaises?

If Edit1.Text[1] in ['S','س'] then 
    ShowMessage('Found') 
else 
    ShowMessage('Not Found') 

Cependant, je savais que non, alors je l'ai changé à CharInSet

If CharinSet(Edit1.Text[1],['S','س']) then 
    ShowMessage('Found') 
else 
    ShowMessage('Not Found') 

mais il n'a jamais travaillé lorsque la chaîne est س, mais toujours travailler avec S, même je rejetterai la edt1.Text 1 avec AnsiChar il toujours fonctionne pas les lettres arabes.

Je fais quelque chose de mal, ou ce n'est pas la façon dont CharInSet fonctionne ?, ou c'est un bug dans CharinSet?

MISE À JOUR:

Mon grand ami Issam Ali a suggéré une autre solution qui a travaillé très bien comme elle:

If CharinSet(AnsiString(edt1.Text)[1],['S','س']) then 
+0

De quel type est 'edt1'? – dan04

+0

@ dan04, c'est TEdit, j'ai changé le code pour montrer qu'il est comme edit au lieu de edt –

+3

Le compilateur émet l'avertissement suivant avec votre code CharInSet: [Avertissement DCC] Unit5.pas (30): W1061 Réduction donnée constante WideChar (# $ 0633) à AnsiChar perdu information –

Répondre

17

CharInSet est inutile pour les caractères ci-dessus 255. Dans votre cas, vous devez utiliser

case C of 
    'S','س' : ShowMessage('Found'); 
    end; 
+0

Ca marche bien merci, je n'y ai pas pensé, car je pensais que ça aurait le même problème que dans. –

1

Avez-vous réglé le codage de votre fichier source à UTF-8 (clic droit pour ouvrir la menu contextuel)? (La valeur par défaut est ANSI IIRC, qui ne fonctionnerait pas.)

+0

J'ai fait, et reconstruit le projet, mais ne fonctionne pas non plus. –

+0

Juste trouvé http: // stackoverflow.com/questions/3341754/donc je pense que ce n'est pas si facile que je pensais – mjn

+0

Je pensais à ce sujet, mais je ne pensais pas que c'est une solution réalisable, j'ai environ 13 lettre à comparer, l'utilisation de valeurs numériques sera plus difficile dans le débogage , mais je vais l'utiliser si je n'ai pas d'autre solution: - /. –

3

Cela se produit parce que set of char type structuré (limité à 256 éléments maximum) ne supporte pas Unicode du tout. C'est-à-dire que tous les caractères Ord(ch) > High(AnsiChar) sont tronqués dans le constructeur de l'ensemble et l'avertissement W1061 concernant le rétrécissement de WideChar vers AnsiChar est émis. Regardez le cas de test suivant:

{ naturally, fails, emits CharInSet() suggestion } 
    Result := 'س' in ['S','س']; 

    { fails because second argument is set of AnsiChar } 
    Result := CharInSet(
    'س', 
    ['S','س'] 
); 

    { workaround for WideChar in AnsiCharSet, fails } 
    Result := WideStrUtils.InOpSet(
    'س', 
    ['S','س'] 
); 

    { a syntactical workaround, which finally works } 
    Result := WideStrUtils.InOpArray(
    'س', 
    ['S','س'] 
); 

    if Result then 
    ShowMessage('PASS') 
    else 
    ShowMessage('FAIL'); 
2

En outre.

les ensembles sont limités à des valeurs ordinales de 256 éléments. Donc AnsiChar s'adapte et (Unicode) Char ne correspond pas. Vous pouvez utiliser CharInSet pour porter les versions pré-unicode de Delphi vers les versions unicode. En raison de la limitation de l'ensemble, les ensembles ne sont plus très utiles avec Chars.

La raison en est que les ensembles sont implémentés en tant que masques de bits. Vous êtes libre d'implémenter votre propre version d'un ensemble. Par exemple:

type 
    TSet<T> = class 
    public 
    procedure Add(const AElem: T); 
    function InSet(const AElem: T): Boolean; 
    end; 
0

Utilisation TCharHelper.IsInArray comme suit:

if Edit1.Text[1].IsInArray(['S','س']) then 
    ShowMessage('Found') 
else 
    ShowMessage('Not Found');