CharInSet не работает с не английскими буквами? - PullRequest
16 голосов
/ 21 ноября 2010

Я обновил приложение с Delphi 2007 до Delphi 2010, все прошло нормально, за исключением одного заявления, которое скомпилировалось нормально, но не работает:

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

Однако я знал, что не будет, поэтомуЯ изменил на CharInSet

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

, но он никогда не работал, когда строка س, но всегда работал с S, даже если я бросил edt1.Text 1 сAnsiChar это всегда не работает арабскими буквами.

Я делаю что-то не так, или это не так CharInSet работает? Или это ошибка в CharinSet?

ОБНОВЛЕНИЕ:

Мой Великий друг Иссам Али предложил другое решение, которое работает нормально:

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

Ответы [ 5 ]

17 голосов
/ 21 ноября 2010

CharInSet бесполезен для символов выше 255. В вашем случае вы должны использовать

  case C of
    'S','س' : ShowMessage('Found');
  end;
3 голосов
/ 22 ноября 2010

Это происходит потому, что структурированный тип set of char (ограничен максимум 256 элементами) вообще не поддерживает Юникод. То есть любые символы Ord(ch) > High(AnsiChar), усекаемые в конструкторе множеств, и предупреждение W1061 о сужении WideChar до AnsiChar испускается. Посмотрите на следующий тестовый пример:

  { 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 голосов
/ 22 ноября 2010

Дополнительно.

наборы ограничены порядковыми значениями 256 элементов. Так что AnsiChar подходит и (Unicode) Char не подходит. Вы можете использовать CharInSet для переноса версий Delphi, предшествующих Юникоду, в версии Юникода. Из-за ограничения набора, наборы больше не очень полезны с Chars.

Причина этого в том, что наборы реализованы как битовые маски. Вы можете реализовать свою собственную версию набора. Например:

type
  TSet<T> = class 
  public
    procedure Add(const AElem: T);
    function InSet(const AElem: T): Boolean;
  end;
1 голос
/ 27 мая 2017

Используйте TCharHelper.IsInArray следующим образом:

if Edit1.Text[1].IsInArray(['S','س']) then 
  ShowMessage('Found')
else
  ShowMessage('Not Found');
1 голос
/ 21 ноября 2010

Вы установили кодировку исходного файла на UTF-8 (щелкните правой кнопкой мыши, чтобы открыть контекстное меню)? (По умолчанию используется ANSI iirc, который не будет работать.)

...