// Um möglichst schnell zu prüfen, ob ein String (nur) eine Zahl
// enthält, habe ich
(trotz kaum Ahnung von Assembler)
den folgenden
// Code gebastelt, der außerdem die richtige Stelle von Tausender-Punkten
// sowie von Vorzeichen in Dezimalzahlen überprüft. Hexadezimal-Zahlen
// dürfen "$" oder "#" voranstehen, sie dürfen aber keinen Punkt, kein
// "+" und kein "-" enthalten. Zum besseren Verständnis hier eine kleine
// Tabelle (deutsch):

String Zahl?
123456789 True
1.23456789 False
.123456789 False
123.456.789 True
1234,56789 True
1234.567.890 False
123,456.789 False
12345,67e-4 True
#123456789 True
$123FFFFFF True
#12345ABe+2 False
$123CfDaEE True
-$12345ABC False
$3.FFF.FFF False
,123456789 False
123456789, False
123.456.789. False


// Getestet mit RS 10.4 unter W11
 

var 
  Komma, Punkt: Byte; 
 
procedure TForm1.FormCreate(Sender: TObject); 
begin 
  Komma := ord(FormatSettings.Decimalseparator); 
  Punkt := ord(FormatSettings.ThousandSeparator); 
end; 
 
function Testen(p: PWideChar): boolean; stdcall; 
asm 
  push ebx 
  push esi 
  push edi 
  xor ecx, ecx 
  xor esi, esi 
  mov edi, esi 
  mov edx, p 
  mov ebx, edx 
  mov al, [edx] 
  cmp al, Komma 
  je @false 
  cmp al, '$' 
  je @ishex 
  cmp al, '#' 
  jne @schleife 
@ishex: 
  mov ecx, $F00000 
  add edx, 2 
@schleife: 
  mov al, [edx] 
  cmp al, 0 
  jne @plus 
  cmp edx, ebx 
  je @false 
  mov al, [edx-2] 
  cmp al, Komma 
  je @false 
  jmp @true 
@plus: 
  cmp al, '+' 
  jne @minus 
@vorzeichen: 
  cmp ecx, $F00000 
  jge @false 
  cmp ch, 0 
  jne @false 
  mov ch, 1 
  cmp edx, ebx 
  je @eins 
  mov ah, [edx-2] 
  cmp ah, 'e' 
  je @weiter 
  cmp ah, 'E' 
  je @weiter 
@eins: 
  mov ah, [edx+2] 
  cmp ah, 0 
  je @false 
  cmp edx, ebx 
  jne @false 
  cmp ah, 'e' 
  je @false 
  cmp ah, 'E' 
  je @false 
  jmp @weiter 
@minus: 
  cmp al, '-' 
  jne @komm 
  jmp @vorzeichen 
@komm: 
  cmp al, Komma 
  jne @e 
  sub esi, edi 
  cmp esi, 4 
  jne @ohne 
  jmp @mit 
@ohne: 
  cmp edi, 0 
  jne @false 
@mit: 
  xor edi, edi 
  cmp cl, 0 
  jg @false 
  cmp ecx, $101 
  jg @false 
  mov cl, 1 
  jmp @weiter 
@e: 
  cmp al, 'e' 
  je @etest 
  cmp al, 'E' 
  jne @ziffer 
@etest: 
  cmp ecx, $101 
  jg @hex 
  cmp edx, ebx 
  je @false 
  or ecx, $10000 
  xor ch, ch 
  jmp @weiter 
@ziffer: 
  cmp al, Punkt 
  je @ish 
  cmp al, '0' 
  jl @hex 
  cmp al, '9' 
  jle @weiter 
@hex: 
  cmp ecx, $F00000 
  jl @false 
  cmp al, 'A' 
  jl @false 
  cmp al, 'F' 
  jle @weiter 
  cmp al, 'a' 
  jl @false 
  cmp al, 'f' 
  jg @false 
@weiter: 
  add edx, 2 
  inc esi 
  jmp @schleife 
@ish: 
  cmp ecx, $F00000 
  jge @false 
  cmp cl, 0 
  jg @false 
  cmp esi, 0 
  je @false 
  cmp edi, 0 
  je @anf 
  sub esi, edi 
  cmp esi, 4 
  jne @false; 
  jmp @first 
@anf: 
  cmp esi, 4 
  jge @false; 
@first: 
  mov edi, esi 
  jmp @weiter 
@false: 
  mov @result, 0 
  jmp @raus 
@true: 
  cmp edi, 0 
  je @kp 
  sub esi, edi 
  cmp esi, 4 
  jne @false 
@kp: 
  mov result, 1 
@raus: 
  pop edi 
  pop esi 
  pop ebx 
end; 
 
function isZahl(S: String): boolean; overload; 
begin 
  result := Testen(PWideChar(S)); 
end; 
 
function isZahl(S: AnsiString): boolean; overload; 
begin 
  result := Testen(PWideChar(String(S))); 
end; 
 
 
// Beispielaufrufe 
 
procedure TForm1.Button1Click(Sender: TObject); 
var 
  b: boolean; 
begin 
  b := isZahl('-8.143.526,2763e-2'); 
  if b then 
    Label1.Caption := 'OK' 
  else 
    Label1.Caption := 'Keine zugelassene Zahl'; 
end; 
 
procedure TForm1.Button2Click(Sender: TObject); 
var 
  S: AnsiString; 
begin 
  S := '#1AfBc0E5'; 
  if isZahl(S) then 
    showmessage('Das ist eine Zahl') 
  else 
    showmessage('Keine exakte Zahl') 
end;



Zugriffe seit 6.9.2001 auf Delphi-Ecke