CharInSet函数无法使用非英文字母吗?

16

我已将一个应用程序从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总是有效的,即使我使用AnsiChar转换edt1.Text1,它仍然不能处理阿拉伯字母。

我做错了什么,或者CharInSet的工作方式不对吗?还是CharinSet中存在bug?

更新:

我的好朋友Issam Ali 提出了另一种解决方案,它已经运行良好:

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

@dan04,这是TEdit,我已经更改了代码以显示它为编辑而不是edt。 - Mohammed Nasman
3
编译器对你的 CharInSet 代码发出以下警告:[DCC Warning] Unit5.pas(30): W1061 缩小给定的 WideChar 常量 (#$0633) 到 AnsiChar 丢失信息。 - David Heffernan
Delphi XE中的字符串类型是Unicode格式。如果(Ch in ['S','س'])//在此处编写代码 - MajidTaheri
1
关于您的更新:它不可靠,而且始终依赖于DefaultSystemCodePage。 - Baoquan Zuo
5个回答

17

CharInSet对于超过255的字符是无用的。在您的情况下,您应该使用

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

工作正常,谢谢。我没有考虑过这个问题,因为我认为它会遇到与 in 相同的问题。 - Mohammed Nasman

3

这是因为set of char结构化类型(最多限制为256个元素)根本不支持Unicode。也就是说,任何字符Ord(ch) > High(AnsiChar)在集合构造函数中都会被截断,并会发出有关将WideChar缩小为AnsiChar的警告W1061。请看下面的测试用例:

  { 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

此外。

集合仅限于256个元素的序数值。因此AnsiChar适合,而(Unicode)Char不适合。 您可以使用CharInSet将Delphi的预Unicode版本移植到Unicode版本。由于集合的限制,集合与Chars的结合已经不再非常有用。

背后的原因是,集合被实现为位掩码。您可以自由地实现自己版本的集合。例如:

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

2

使用TCharHelper.IsInArray的方法如下:

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

1
你是否将源文件的编码设置为UTF-8(右键单击以打开上下文菜单)? 默认情况下是ANSI,但这种编码方式不能正常工作。

刚刚发现了https://dev59.com/Ok_Sa4cB1Zd3GeqP_1oj,所以我认为这并不像我想象的那么容易。 - mjn
我考虑过这个办法,但是我认为它不可行。我需要比较大约13个字母,使用数字值在调试时会更加困难,但如果没有其他解决方案,我将会使用它 :-/. - Mohammed Nasman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接