![]() |
Nummernangaben parsen
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:
Falls ihr Fehlerberichte oder Verbesserungsvorschläge habt, bin ich dankbbar.
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; 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 :angle: :angle2: |
Dein Code sieht schon ein bisschen umfangreich aus.
Der folgende Code erledigt genau dasselbe. Nur ist er etwas kompakter.
Code:
[b]type[/b]
TWordList = [b]Array[/b] [b]of[/b] Word; TCharArray = [b]Array[/b] [b]of[/b] Char; [b]function[/b] ParseList([b]const[/b] PortList: [b]String[/b]): TWordList; [b]var[/b] F, P, Sep: PChar; s: [b]string[/b]; i, Len, LoRange, HiRange: Integer; [b]begin[/b] SetLength(Result, 0); F := PChar(PortList); P := F; [b]while[/b] P^ <> #0 [b]do[/b] [b]begin[/b] [b]while[/b] (P^ <> #0) [b]and[/b] ([b]not[/b] (P^ [b]in[/b] ['-', ',', ';'])) [b]do[/b] Inc(P); [b]if[/b] P^ = '-' [b]then[/b] [b]begin[/b] Sep := P; [color=#000080][i]// Ende suchen[/i][/color] [b]while[/b] (P^ <> #0) [b]and[/b] ([b]not[/b] (P^ [b]in[/b] [',', ';'])) [b]do[/b] Inc(P); SetString(s, F, Sep - F); LoRange := StrToIntDef(s, -1); Inc(Sep); SetString(s, Sep, P - Sep); HiRange := StrToIntDef(s, -1); [b]end[/b] [b]else[/b] [b]begin[/b] SetString(s, F, P - F); LoRange := StrToIntDef(s, -1); HiRange := LoRange; [b]end[/b]; [b]if[/b] (LoRange = -1) [b]or[/b] (HiRange = -1) [b]or[/b] (LoRange > HiRange) [b]or[/b] (HiRange > High(Word))[b]then[/b] [b]raise[/b] Exception.Create('Ungültige Port Liste'); Len := Length(Result); SetLength(Result, Len + HiRange - LoRange + 1); [b]for[/b] i := LoRange [b]to[/b] HiRange [b]do[/b] Result[Len + i - LoRange] := i; [b]if[/b] P^ <> #0 [b]then[/b] Inc(P); [color=#000080][i]// ';', '-' überspringen[/i][/color] F := P; [b]end[/b]; [b]end[/b]; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz