![]() |
Zahlen aus String parsen
Hey,
also ich hab einen Text vorliegen, der eigentlich immer gleich ist. In diesem Text befinden sich verschiedene Zahlen, die event. der Optikhalber auch mit Punkten unterteilt sind (bsp 1.234.567) oder auch ganz kurz sein können (bsp 0). Die einzelnen Zahlen können auch nur durch ein Leerzeichen voneinander getrennt sein. Nun möchte ich also diese Zahlen extrahieren. Gibt es da irgendwas fertiges, oder muss ich Wort für Wort durch den String gehen und auf Zahl oder Buchstabe überprüfen? Oder hat jemand ne komplett andere/bessere Idee sowas vernünftig zu lösen? Es sei noch gesagt, das es komplett nonVCL ist. Also keine Units sprich SysUtils usw. Danke für Vorschläge im vorraus :) mfg Martin |
AW: Zahlen aus String parsen
Wie wäre es alle Buchstaben und nicht benötigte Sonderzeichen zu Blanks (Unterstreicher,Ausrufezeichen...) zu machen und diese dann aus dem Text zu entfernen?
Dann sollten nur noch gültige Zahlen zurück bleiben. Gruß K-H |
AW: Zahlen aus String parsen
Aber wie kann ich die dann danach effektiv voneinander trennen?
Die Zahlen dürfen sich ja nicht verändern dadurch oder gar zusammen geschmissen werden. Ich hatte als erste des Idee es mit zwei Schleifen zu machen. Also die erste geht nach und nach den String durch und die zweite kommt dann in Aktion, wenn die erste ne Zahl gefunden hat. Aber da kommt halt die Idee, ob man das nicht irgendwie "besser" lösen könnte. |
AW: Zahlen aus String parsen
.. ich würde die Trennzeichen vereinheitlichen und dann eine Funktion wie explode
nehmen um die Zahlen(Strings) in eine Liste zu bekommen. Die Liste kannst Du dann weiter auswerten. Grüße Klaus |
AW: Zahlen aus String parsen
Hier eine Funktion die eine Zahl ermittelt. Mit leichter Anpassung kann man auch alle Zahlen eines Strings ermitteln, bzw. um Tausender Zeichen erweitern.
Delphi-Quellcode:
//Prüft auf Zahl im Strings, wie "Neuer Text (2)". Bei vorhanden sein
//gibt StrB den Teil vor der Zahl, StrN die Zahl, StrE den Rest. function IsNumIn(Str: String; var StrB, StrNum, StrE: String): Boolean; var k: Integer; begin StrB := ''; // Text vor Zahl StrNum := ''; // Zahl StrE := ''; // Text nach Zahl k := 1; while k <= Length(Str) do if Pos(Str[k], '0123456789') = 0 then begin StrB := StrB + Str[k]; Inc(k); end else Break; while k <= Length(Str) do if Pos(Str[k], '0123456789') > 0 then begin StrNum := StrNum + Str[k]; Inc(k); end else Break; StrE := Copy(Str, k, Length(Str)); Result := StrNum <> ''; end; |
AW: Zahlen aus String parsen
hi,
[EDIT]Hatte das mit dem NON-VCL überlesen... Hier einmal überarbeitet ;)[/EDIT]
Delphi-Quellcode:
unit Unit2;
interface type TStringArray = array of string; procedure GetNums(AString: string; var AStrArray: TStringArray); implementation procedure GetNums(AString: string; var AStrArray: TStringArray); var ndx: Integer; sHelp: string; begin sHelp := ''; SetLength(AStrArray, 0); for ndx := 1 to Length(AString) do begin if (AString[ndx] in ['0'..'9']) then begin sHelp := sHelp + AString[ndx]; end else if (sHelp <> '') then begin SetLength(AStrArray, Length(AStrArray)+1); AStrArray[High(AStrArray)] := sHelp; sHelp := ''; end; end; // Edit Ihr habt ja recht. if (sHelp <> '') then begin SetLength(AStrArray, Length(AStrArray)+1); AStrArray[High(AStrArray)] := sHelp; sHelp := ''; end; end; end. |
AW: Zahlen aus String parsen
Was sind Zahlen?
z.B. inklusive Vorzeichen, Komma, Tausenderseparator und womöglich noch mit Exponent. TStringArray ... falls es im D7 das schon gibt, dann besser ![]() @angos: Wenn AString mit einer Zahl endet, dann wird diese vergessen. Also nach der Schleife dieses besser nochmals beachten.
Delphi-Quellcode:
Mit Vorzeichen:
if sHelp <> '' then
begin SetLength(AStrArray, Length(AStrArray)+1); AStrArray[High(AStrArray)] := sHelp; end;
Delphi-Quellcode:
ohne Vorzeichen
function GetNums(const Text: string): TIntegerDynArray;
var L, i: Integer; begin SetLength(Result, 1); Result[0] := ''; L := 0; for i := 1 to Length(Text) do if (Text[i] in ['0'..'9']) or ((Result[L] = '') and (Text[i] in ['+', '-']) and (i < Length(Text)) and (Text[i + 1] in ['0'..'9'])) then Insert(Text[i], Result[L], Length(Result[L]) + 1) // Result[L] := Result[L] + Text[i] else if Result[L] <> '' then begin Inc(L); SetLength(Result, L + 1); end; if Result[L] = '' then SetLength(Result, L); end; // ab D2006/TDE function GetNums(const Text: string): TIntegerDynArray; var C, V: Char; L: Integer; begin SetLength(Result, 1); Result[0] := ''; L := 0; V := #0; for C in Text do begin if C in ['0'..'9'] then begin if V in ['+', '-'] then Result[L] := V; Insert(C, Result[L], Length(Result[L]) + 1); end else if Result[L] <> '' then begin Inc(L); SetLength(Result, L + 1); end; V := C; end; if Result[L] = '' then SetLength(Result, L); end;
Delphi-Quellcode:
function GetNums(const Text: string): TIntegerDynArray;
var L, i: Integer; begin SetLength(Result, 1); Result[0] := ''; L := 0; for i := 1 to Length(Text) do if Text[i] in ['0'..'9'] then Insert(Text[i], Result[L], Length(Result[L]) + 1) else if Result[L] <> '' then begin Inc(L); SetLength(Result, L + 1); end; if Result[L] = '' then SetLength(Result, L); end; // ab D2006/TDE function GetNums(const Text: string): TIntegerDynArray; var C: Char; L: Integer; begin SetLength(Result, 1); Result[0] := ''; L := 0; for C in Text do if C in ['0'..'9'] then Insert(C, Result[L], Length(Result[L]) + 1) else if Result[L] <> '' then begin Inc(L); SetLength(Result, L + 1); end; if Result[L] = '' then SetLength(Result, L); end; |
AW: Zahlen aus String parsen
Zitat:
Und da frage ich mich doch, wozu denn alle diese derartigen Codes eigentlich gut sein sollen, wenn mit denen bei einem String wie z.B. 'xxxx2.098yyyy' herauskommt, dass solch ein String angeblich die zwei Zahlen 2 und 098 enthalte, wobei doch tatsächlich darin nur die eine einzige Zahl 2.098 enthalten ist.... |
AW: Zahlen aus String parsen
Zitat:
Erst bei i = length(string) (letzter Durchlauf) wird sHelp gesetzt, das Speichern der Zahl geschieht aber nur, wenn es sich <beim nächsten Zeichen> nicht um eine Zahl handelt (hier gibt es kein nächstes Zeichen (letzter Schleifendurchlauf)) ;) |
AW: Zahlen aus String parsen
Vielleicht sollten wir keine weiteren Codes liefern bis der Threadersteller ganz genau mitteilt was er unter Zahl versteht, denn je komplexer die Zahl, desto komplexer der Code. Einfacher Integer ist kein Problem, aber wenn schon Tausender Zeichen beachtet werden müssen, dann gehe ich von Real Zahlen aus, dann vielleicht auch -1.23e45. Bevor also der Threadersteller nicht genauer wird, ist es Rätselraten.
|
AW: Zahlen aus String parsen
Es handelt sich in meinem Fall nur um Zahlen im positiven Bereich.
Allerdings haben die Zahlen keine genaue Art, wie schon geschrieben mit 1000ender Trennzeichen oder aber auch ohne. Und dann kommt noch dazu, das in dem Text Zahlen in Form von Zeiten und Datumsangaben hervorkommen die im üblichen Format sind sprich 08.05.2012 oder halt 09:30:45. Ich mach es im mom so, das ich jede Zeile für Zeile durch gehe. Mal sehen bis her komm ich da langsam ran :) |
AW: Zahlen aus String parsen
Hier habe ich meine obere Funktion um das Tausenderzeichen erweitert. Zusätzlich habe ich noch auf die Schnelle eine Funktion zur Prüfung auf Tausenderzeichen geschrieben und eingefügt. Wie du siehst, es kann einen unendlich langen Text durchsuchen und auf Fehler prüfen.
Delphi-Quellcode:
Bei der letzten Zahl kommt ein Fehler wegen falscher Schreibweise des Tausender Trenners.
//Prüft auf Zahl im Strings, wie "Neuer Text (2)". Bei vorhanden sein
//gibt StrB den Teil vor der Zahl, StrN die Zahl, StrE den Rest. function IsNumIn(Str: String; var StrB, StrNum, StrE: String): Boolean; var k: Integer; begin StrB := ''; // Text vor Zahl StrNum := ''; // Zahl StrE := ''; // Text nach Zahl k := 1; while k <= Length(Str) do if Pos(Str[k], '0123456789') = 0 then begin StrB := StrB + Str[k]; Inc(k); end else Break; while k <= Length(Str) do if Pos(Str[k], '0123456789.') > 0 then //Anpassung durch '.' Erweiterung begin StrNum := StrNum + Str[k]; Inc(k); end else Break; StrE := Copy(Str, k, Length(Str)); Result := StrNum <> ''; end; //Prüft den Zahl-String auf korrekte Schreibweise des Tausender Trenners function IsTSNumOk(Str: String): Boolean; begin Result := True; while Pos('.', Str) > 0 do if LastDelimiter('.', Str) = (Length(Str) - 3) then Delete(Str, Length(Str) - 3, MaxInt) else begin Result := False; Exit; end; end; //Ein Beispiel procedure TForm1.Button1Click(Sender: TObject); var Str, StrB, StrNum, StrE: String; begin Str := 'Ich verdiente mal 10000DM, dann 27.990 DM, dann mal 17.000 Euro, ' + 'aber auch mal 1.273.000Lira, jedoch nie 125.00 Euro'; while LastDelimiter('0123456789', Str) > 0 do begin if IsNumIn(Str, StrB, StrNum, StrE) then begin if IsTSNumOk(StrNum) then ShowMessage('Zahl ist ok, ' + StrNum) else ShowMessage('Fehler, ' + StrNum); Str := StrE; end; end; end; |
AW: Zahlen aus String parsen
Ich habe gerade mal die Versionen von himitsu durchprobiert.
Die funktionieren echt gut, mit nur einer Ausnahme, er schneidet die erste Zahl ab, und packt Sie ans Ende. Also aus zb. 1234567890 macht er 0123456789. Und das sowohl bei der Version ohne als auch mit Vorzeichen. Edit: +1 vergessen, so funktioniert es wie es soll Danke :) :
Delphi-Quellcode:
function GetNums(const Text: string): TIntegerDynArray;
var L, i: Integer; begin SetLength(Result, 1); Result[0] := ''; L := 0; for i := 1 to Length(Text) do if (Text[i] in ['0'..'9']) or ((Result[L] = '') and (Text[i] in ['+', '-']) and (i < Length(Text)) and (Text[i + 1] in ['0'..'9'])) then Insert(Text[i], Result[L], Length(Result[L])+1) // hier die +1 einfügen else if Result[L] <> '' then begin Inc(L); SetLength(Result, L + 1); end; if Result[L] = '' then SetLength(Result, L); end; |
AW: Zahlen aus String parsen
Ich verstehe nicht, und was ist mit den Tausender Trennzeichen? Spielen die jetzt doch keine Rolle?
|
AW: Zahlen aus String parsen
Doch aber ich habs jetzt nen bissel anders gelöst :)
Deine Funktion findet sich auch drin wieder. Da sich an meinem Text das Layout nicht ändert sondern eigentlich nur die Zahlen, bearbeite ich die Zeilen jetzt getrennt voneinander. Das funktioniert super... |
AW: Zahlen aus String parsen
Zitat:
( man könnte mal probieren, ob MaxInt auch ginge, also anstatt dieses Length(...)+1 ) In Verbindung mit FastMM, welches seit 'ner Weile im Delphi drin ist, würde das Insert eine Inpace-Verarbeitung der Strings unterstüzen, was beim Speichermanagement 'ne Menge einsparen täte. Es sei denn Emba hat es inzwischen geschafft bei
Delphi-Quellcode:
zu erkennen, daß man den String X direkt verändern kann, anstatt einen neuen String zu erstellen und diesen anschleißend zuzuweisen.
X := X + Y;
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:10 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