【问题标题】:CharInSet accepting Unicode NULL characterCharInSet 接受 Unicode NULL 字符
【发布时间】:2012-05-17 01:34:08
【问题描述】:

我正在从内存中读取一些数据,而这块内存区域是 Unicode。所以要制作一个 ansi 字符串,我需要这样的东西:

  while CharInSet(Chr(Ord(Buff[aux])), ['0'..'9', #0]) do
    begin
      Target:= Target + Chr(Ord(Buff[aux]));
      inc(aux);
    end;

其中 Buff 是字节数组,目标是字符串。我只想在目标为 0..9 时继续获取 Buff 并添加目标,但是当它找到 NULL memory char (00) 时,它就会停止。如何在 Target 中继续添加数据,直到第一个字母或非数字字符? #0 无效。

【问题讨论】:

  • -1。问题不清楚,接受的答案的代码与问题的代码相同。

标签: delphi delphi-2010


【解决方案1】:

我什至不会打扰CharInSet(),因为您处理的是字节而不是字符:

var
  b: Byte;

while aux < Length(Buff) do
begin
  b := Buff[aux];
  if ((b >= Ord('0')) and (b <= Ord('9'))) or (b = 0) then
  begin
    Target := Target + Char(Buff[aux]); 
    Inc(aux); 
  end else
    Break;
end; 

【讨论】:

  • 该代码等同于问题中显然不起作用的代码。也就是说,目前还不清楚问题是什么。
  • 我的代码不依赖于编译器对CharInSet()的实现。但是,是的,它大致相等。我在 XE2 中测试了原始代码,它对我来说可以正常工作。 CharInSet() 处理 #0 就好了。所以问题很可能在于Buff 首先是如何准备的。
  • 很高兴您同意我的观点,即问题中的代码与此答案中的代码含义相同,以缓冲区溢出保护为模。
  • @HwTrap 另外,为什么要在字符串中间添加#0 字符?我就是不能把这个加起来。
  • 由于他使用的是 D2012,并且假设 TargetUnicodeString,因此需要将 #0 字符放在中间以保持正确的 UTF-16 编码。
【解决方案2】:

如果您的数据是 Unicode,那么我假设编码是 UTF-16。在这种情况下,您无法逐字节处理它。一个字符单元是 2 个字节宽。先将数据放入Delphi字符串,然后解析:

var
  str: string;
....
SetString(str, PChar(Buff), Length(Buff) div SizeOf(Char));

这样做,您的循环可能如下所示:

for i := 1 to Length(str) do
  if not CharInSet(str[i], ['0'..'9']) then
  begin
    SetLength(str, i-1);
    break;
  end;

我相信您的困惑是由于逐字节处理造成的。对于 UTF-16 编码的文本,ASCII 字符被编码为一对字节,其中最重要的是零。我怀疑这解释了你试图通过CharInSet 调用实现的目标。

如果您想处理其他数字字符,则可以使用Character 单元并使用TCharacter.IsDigit() 进行测试。

【讨论】:

  • 感谢您的关注和评论。给你+1分,但第一个答案只是以简单的形式解决了我的问题。无论如何,再次感谢您!
  • 我无法理解 Remy 的回答如何解决问题。除了避免代码中的缓冲区溢出之外,它的作用与您的代码完全相同。您说 buff 中的数据是 Unicode。如果这是真的,你为什么要一个字节一个字节地处理它?!我想知道你是否真的明白这里发生了什么。
猜你喜欢
  • 1970-01-01
  • 2014-11-17
  • 2016-07-26
  • 1970-01-01
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多