Die folgende Funktion bietet die Möglichkeit, aus einem String, in dem Zahlen stehen, ein Array mit diesen Zahlen zu erstellen.
Die Zahlen können sowohl einzeln mit Komma oder Strichpunkt getrennt stehen oder man kann einen Bereich angeben. Die Bereichs-Grenzen werden mit einem Bindestrich verknüpft.
Ein solcher String könnte z. B. so aussehen:
1-100,3306,8000,35000-36000
Alles klar? Mit dieser Funktion sollte das gehen:
Delphi-Quellcode:
type
TWordList = Array of Word;
TCharArray = Array of Char;
function ParseList(PortList: String): TWordList;
function MakeWordNumber(List: TCharArray; size: Integer): Integer;
var
a: Integer;
buf: String;
begin
buf := '';
for a := 0 to size - 1 do
begin
buf := buf + List[a];
end;
Result := StrToIntDef(buf, -1);
end;
var
a, b, c, ResLen, PortListLen: Integer;
CharSet: set of '0'..'9';
buf: TCharArray;
RangeOperator: Boolean;
loRange, hiRange, Single: Integer;
const
MaxNumber = 65535;
begin
if PortList = '' then
begin
Result := nil;
Exit;
end;
Result := nil;
a := 1;
b := 0;
CharSet := ['0'..'9'];
RangeOperator := False;
PortListLen := Length(PortList);
//Falls erstes Zeichen eine Ziffer -> Los gehts
if PortList[a] in CharSet then
begin
//Verknüpfungs-Operatoren werden vereinheitlicht
PortList := StringReplace(PortList, ';', ',', [rfReplaceAll]);
if PortList[PortListLen] <> ',' then Portlist := PortList + ',';
SetLength(buf, PortListLen);
buf[b] := PortList[a];
Inc(b);
Inc(a);
//Diese Schleife parst den String
while PortList[a] <> #0 do
begin
//falls Zeichen eine Ziffer ist...
if PortList[a] in CharSet then
begin
{wird sie in einen Puffer geschrieben}
buf[b] := PortList[a];
Inc(b);
end
else
begin
//falls Bereichs-Operator
if PortList[a] = '-' then
begin
//falls Bereichs-Operator nicht vorher gesetzt war
if not RangeOperator then
begin
//Bereichs-Operator wird gesetzt, eine Zahl wird aus den vorherigen Zeichen gebildet
//und der Puffer wird geleert
RangeOperator := True;
loRange := MakeWordNumber(buf, b + 1);
ZeroMemory(@buf, SizeOf(buf));
SetLength(buf, PortListLen);
b := 0;
//falls keine Zahl gebildet werden kann -> Abbruch
if loRange = -1 then
begin
Exit;
end;
end
//falls Bereichs-Operator zweimal hintereinander vorkommt -> Abbruch
else
begin
Exit;
end;
end
//falls Verknüpfungs-Operator
else if PortList[a] = ',' then
begin
//falls Bereichs-Operator vorher gesetzt war
if RangeOperator then
begin
//Bereichs-Operator wird zurückgesetzt, Zahl wird aus den vorherigen Ziffern gebildet
RangeOperator := False;
hiRange := MakeWordNumber(buf, b + 1);
ZeroMemory(@buf, SizeOf(buf));
SetLength(buf, PortListLen);
b := 0;
//Falls Zahl nicht gebildet werden konnte -> Abbruch
if hiRange = -1 then
begin
Exit;
end
else
//Falls Zahl gebildet werden konnte
begin
//Falls untere Zahl größer als obere -> Abbruch
if loRange >= HiRange then Exit;
//falls Nummer größer als 65535 -> Abbruch
if hiRange > MaxNumber then Exit;
//Ergebnis-Array auf neue Länge setzen
ResLen := Length(result);
SetLength(Result, ResLen + hiRange - loRange + 1);
{Ergebnis-Array mit Zahlen füllen}
for c := ResLen to Length(Result) - 1 do
begin
Result[c] := loRange;
Inc(loRange);
end;
//Bereichs-Grenzen zurücksetzen
hiRange := 0;
loRange := 0;
end;
end
//falls Bereichs-Operator nicht gesetzt war
else
begin
Single := MakeWordnumber(buf, b + 1);
ZeroMemory(@buf, SizeOf(buf));
SetLength(buf, PortListLen);
b := 0;
//falls Nummer größer als 65535 -> Abbruch
if Single > MaxNumber then Exit;
//falls keine gültige Zahl -> Abbruch
if Single = -1 then
begin
Exit;
end
//Falls gültige Zahl
else
begin
//Wert wird dem Array hinzugefügt
SetLength(Result, Length(Result) + 1);
Result[Length(Result) - 1] := Single;
Single := 0;
end;
end;
end
//falls unbekannter Operator -> Abbruch
else
begin
Exit;
end;
end;
Inc(a);
end;
end
else begin
Exit;
end;
end;
//Aufruf:
var
WordList: TWordList;
begin
WordList := ParseList('1-100,3306,5000-5100');
end;
Falls ihr Fehlerberichte oder Verbesserungsvorschläge habt, bin ich dankbbar.
Auch wenn ihr mir sagt, dass ich das ganze mit Routinen, die mir Delphi liefert, viel einfacher hätte machen können, werde ich nicht böse