// 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;
|