0
votes

I'm reading some data from memory, and this area of memory is in Unicode. So to make one ansi string I need something like this:

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

Where Buff is array of Bytes and Target is string. I just want keep getting Buff and adding in Target while it's 0..9, but when it finds NULL memory char (00), it just stops. How can I keep adding data in Target until first letter or non-numeric character?? The #0 has no effect.

2
-1. Question is not clear, and accepted answer's code is equivalent to the question's.Rob Kennedy

2 Answers

3
votes

I would not even bother with CharInSet() since you are dealing with bytes and not characters:

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; 
3
votes

If your data is Unicode, then I am assuming that the encoding is UTF-16. In which case you cannot process it byte by byte. A character unit is 2 bytes wide. Put the data into a Delphi string first, and then parse it:

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

Do it this way and your loop can look like this:

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

I believe that your confusion was caused by processing byte by byte. With UTF-16 encoded text, ASCII characters are encoded as a pair of bytes, the most significant of which is zero. I suspect that explains what you were trying to achieve with your CharInSet call.

If you want to cater for other digit characters then you can use the Character unit and test with TCharacter.IsDigit().