Delphi CharInSet接受Unicode空字符

Delphi CharInSet接受Unicode空字符,delphi,delphi-2010,Delphi,Delphi 2010,我正在从内存中读取一些数据,这个内存区域是Unicode格式的。因此,要制作一个ansi字符串,我需要如下内容: while CharInSet(Chr(Ord(Buff[aux])), ['0'..'9', #0]) do begin Target:= Target + Chr(Ord(Buff[aux])); inc(aux); end; for i := 1 to Length(str) do if not CharInSet(str[i]

我正在从内存中读取一些数据,这个内存区域是Unicode格式的。因此,要制作一个ansi字符串,我需要如下内容:

  while CharInSet(Chr(Ord(Buff[aux])), ['0'..'9', #0]) do
    begin
      Target:= Target + Chr(Ord(Buff[aux]));
      inc(aux);
    end;
for i := 1 to Length(str) do
  if not CharInSet(str[i], ['0'..'9']) then
  begin
    SetLength(str, i-1);
    break;
  end;

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

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

var
  str: string;
....
SetString(str, PChar(Buff), Length(Buff) div SizeOf(Char));
这样做,您的循环可以如下所示:

  while CharInSet(Chr(Ord(Buff[aux])), ['0'..'9', #0]) do
    begin
      Target:= Target + Chr(Ord(Buff[aux]));
      inc(aux);
    end;
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
呼叫实现的目标


如果您想适应其他数字字符,则可以使用
字符
单元,并使用
TCharacter.IsDigit()

进行测试。如果您的数据是Unicode,则我假设编码是UTF-16。在这种情况下,您无法逐字节处理它。字符单位为2字节宽。首先将数据放入Delphi字符串中,然后对其进行解析:

var
  str: string;
....
SetString(str, PChar(Buff), Length(Buff) div SizeOf(Char));
这样做,您的循环可以如下所示:

  while CharInSet(Chr(Ord(Buff[aux])), ['0'..'9', #0]) do
    begin
      Target:= Target + Chr(Ord(Buff[aux]));
      inc(aux);
    end;
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
呼叫实现的目标


如果您想适应其他数字字符,那么您可以使用
字符
单元,并使用
TCharacter.IsDigit()
进行测试,因为您处理的是字节而不是字符,所以我甚至不想麻烦使用
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; 
var
b:字节;
而aux<长度(Buff)可以
开始
b:=Buff[aux];

如果((b>=Ord('0'))和(b我甚至不会为
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; 
var
b:字节;
而aux<长度(Buff)可以
开始
b:=Buff[aux];

如果((b>=Ord('0'))和(b),那么该代码相当于问题中的代码,显然不起作用。也就是说,问题是什么还不清楚。我的代码不依赖于编译器对
CharInSet()的实现
。但是,是的,它大致相当。我在XE2中测试了原始代码,它对我来说运行正常。
CharInSet()
处理
#0
很好。因此问题很可能在于如何首先准备
Buff
。我很高兴您同意我的观点,问题中的代码与此答案中的代码具有相同的含义,模块化缓冲区溢出保护。@HwTrap另外,为什么要在stri的中间添加#0个字符NG?我就是不能这么做。因为他使用D2012,假设目标< /代码>是<代码> UnoDeSooS,为了保持适当的UTF16编码,需要在中间放置0个字符。该代码相当于问题中的代码,显然这不起作用。y代码不依赖于编译器对
CharInSet()
的实现。但是,是的,它大致相当。我在XE2中测试了原始代码,它对我来说运行正常。
CharInSet()
处理
#0
很好。因此问题很可能在于如何首先准备
Buff
。我很高兴您同意我的观点,问题中的代码与此答案中的代码具有相同的含义,模块化缓冲区溢出保护。@HwTrap另外,为什么要在stri的中间添加#0个字符NG?我不能做这个。因为他使用D2012,假设代码>目标<代码>是一个<代码> UnoDeSoops,为了保持正确的UTF16编码,需要把0个字符放在中间。谢谢你的关注和评论。给你1点,但是第一个答案只是简单地解决了我的问题。增益!!我不明白雷米的答案是如何解决这个问题的。除了避免代码中的缓冲区溢出外,它的作用与您的代码完全相同。您声明buff中的数据是Unicode。如果这是真的,您为什么要逐字节处理它?!我想知道您是否真的理解这里发生的事情。感谢您的关注和通信ent.给你+1分,但第一个答案只是以简单的形式解决了我的问题。无论如何,再次感谢你!!我不明白雷米的答案是如何解决这个问题的。除了避免代码中的缓冲区溢出外,它与你的代码完全一样。你说buff中的数据是Unicode。如果这是真的,你为什么要用byt处理它我不知道你是否真的明白这里发生了什么。-1.问题不清楚,接受答案的代码等同于问题的代码。-1.问题不清楚,接受答案的代码等同于问题的代码。