![]() |
Delphi-Version: XE2
POS findet was das ich nicht verstehe... ?
Warum ?
Delphi-Quellcode:
Als Ausgabe im Memo1 erhalte ich:
private
{ Private-Deklarationen } Nachrichtentext : String; procedure GetParameter(var Value : String; Suche : String); public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.GetParameter(var Value : String; Suche : String); var i, j : Integer; s : String; begin s := ''; j := POS(Suche, Nachrichtentext) + length(Suche); for i := j to length(Nachrichtentext) do if Nachrichtentext[i] <> ';' then s := s + Nachrichtentext[i] else break; Value := s; end; procedure TForm1.Button1Click(Sender: TObject); var s1, s2, s3 : String; begin Nachrichtentext := 'S;XY41380993;P=10000,1;M1=012324016940;M2=;F-18;'; GetParameter(s1,';M1='); GetParameter(s2,';M2='); GetParameter(s3,';W='); Memo1.Lines.Append(s1); Memo1.Lines.Append(s2); Memo1.Lines.Append(s3); end;
Code:
:?: XY41380993 dürfte nicht ausgegeben werden ?
012324016940
XY41380993 Grüße 0815 |
AW: POS findet was das ich nicht verstehe... ?
Hallo,
du setzt j auf einen Wert, unabhänging davon ob mit pos der SubString gefunden wurde. -1 +3 = 2 -> XY41380993 Grüße Klaus |
AW: POS findet was das ich nicht verstehe... ?
Ahhhh, manchmal hat man echt ein Brett vor´m Kopf.
Danke ! |
AW: POS findet was das ich nicht verstehe... ?
Weshalb so umständlich?
Delphi-Quellcode:
function GetValue(Suche : String) : String;
Var p : Integer; S : String; begin Result := ''; S := Nachrichtentext; p := Pos(Suche, S); // nach dem Suchstring suchen if p = 0 then exit; // wenn nichts gefunden, dann raus // wenn gefunden, dann ... Delete(S, 1 ,p + Length(S)-1); // ab gefundener Position die Länge des Suchstrings löschen p := Pos(';', S); // nach Delimiter suchen if p = 0 then exit; // wenn nichts gefunden, dann raus // wenn gefunden, dann Result zuweisen Result := Copy(S, 1, p-1); end; |
AW: POS findet was das ich nicht verstehe... ?
Wie wäre sowas:
Delphi-Quellcode:
Etwas OOP lastig, aber es funktioniert.
procedure GetParameter2(Nachrichtentext: String; var Value : String; Suche : String);
begin with TStringList.Create do try Delimiter := ';'; DelimitedText := Nachrichtentext; Value := Values[Suche]; finally Free; end; end; procedure TForm1.Button1Click(Sender: TObject); var s1, s2, s3 : String; Nachrichtentext: String; begin Nachrichtentext := 'S;XY41380993;P=10000,1;M1=012324016940;M2=;F-18;'; GetParameter2(Nachrichtentext, s1, 'M1'); GetParameter2(Nachrichtentext, s2, 'M2'); GetParameter2(Nachrichtentext, s3, 'W'); Memo1.Lines.Append(s1); Memo1.Lines.Append(s2); Memo1.Lines.Append(s3); end; |
AW: POS findet was das ich nicht verstehe... ?
obiges war nur verkürzter Beispielcode.
Zitat:
Nochmal Danke, das Thema hat sich erledigt. |
AW: POS findet was das ich nicht verstehe... ?
Zitat:
Via PosEx lässt sich das auch Ohne problemlos lösen. |
AW: POS findet was das ich nicht verstehe... ?
Jep. PosEx habe ich auch all zu lange ignoriert (vielleicht weil man einzig wegen der Funktion die sonst kaum genutzte Unit StrUtils einbinden muss). Auf jeden Fall kann man damit einen ganzen String ohne Delete zerlegen. Auf der anderen Seite stellt sich die Frage was optimaler ist, eine extra Unit oder mit Delete arbeiten.
|
AW: POS findet was das ich nicht verstehe... ?
Die StrUtils ist bei mir eh oftmals mit drin, da die noch andere nette Funktionen drin hat. :angel:
StartsText, ContainsText, EndsText, MatchText, IndexText (auch gut für ein CASE mit Strings) uvvm. In Math liegen zwar ein paar IfThen, aber die String-Version versteckt sich in der StrUtils. PS: Die StrUtils selber vergrößert die EXE selber praktisch garnicht. - ungenutzte Funktionen werden nicht in die Anwendung gelinkt - es gibt keinen "initialization"-Abschnitt oder globale Variablen - bis auf die SysUtils werden keine bösen Units eingebunden |
AW: POS findet was das ich nicht verstehe... ?
Hm, vielleicht sollte ich mir die Unit mal genauer angucken. Was ich bisher gesehen habe erinnert mich leicht an meinen alten TI-99/4A. Der hatte auch viele tolle String-Funktionen, die ich später beim C64 vermisst habe und nun hier wieder entdecke ;)
|
AW: POS findet was das ich nicht verstehe... ?
Und ich habe gelernt dass man nicht jede Delphi Funktion bei Google eingeben kann. Da ich PosEX auch noch nie benutzt habe, habe ich da mal bei Google nach gesucht.(Allerdings ohne das Schlagwort Delphi). Hat mit Programmierung nicht mehr viel zu tun
|
AW: POS findet was das ich nicht verstehe... ?
|
AW: POS findet was das ich nicht verstehe... ?
Also ganz allgemein sollte man Funktionen gegenüber Prozeduren mit einem Var-Parameter bevorzugen.
Perlsau hat das im Beitrag #4 schon ganz richtig gemacht. (man sollte aber auch den "Nachrichtentext" als weiteren Parameter übergeben) Insbesondere Funktionen die ausschlieslich von ihren Eingangsparameter(n) abhängen und keine Nebeneffekte haben (sog. pure functions) machen das Testen des Codes zum Kinderspiel. |
AW: POS findet was das ich nicht verstehe... ?
Die richtige Implementierung wäre:
Delphi-Quellcode:
und der Aufruf
function GetParamValue( const AText, AParamName : string; out Value : string ) : Boolean;
begin ... end;
Delphi-Quellcode:
Documentation by Design
var
Nachricht : string; S1, S2 : string; GetParamValue( Nachricht, 'M1', S1 ); if not GetParamValue( Nachricht, 'M2', S2 ) then raise Exception.Create( 'Parameter M2 wird zwingend benötigt!' );
|
AW: POS findet was das ich nicht verstehe... ?
richtig...
Man kann es auch wie bei StrToInt, TryStrToInt und StrToIntDef machen? Oder ParamStr, was beim Fehlen einen Leerstring liefert. |
AW: POS findet was das ich nicht verstehe... ?
Zitat:
Delphi-Quellcode:
TryStrToInt
Delphi-Quellcode:
function TryFoo( const AInput : TSomething; out AOutput : TDifferent ) : Boolean;
begin ... end; function Foo( const AInput : TSomething ) : TDifferent; begin if not TryFoo( AInput, Result ) then raise EFooException.Create( 'Please try something different' ); end; function FooDefault( const AInput, ADefault : TSomething ) : TDifferent; begin if not TryFoo( AInput, Result ) then Result := ADefault; end; |
AW: POS findet was das ich nicht verstehe... ?
Zitat:
|
AW: POS findet was das ich nicht verstehe... ?
Zitat:
|
AW: POS findet was das ich nicht verstehe... ?
Wenn du mehr brauchst, dann StrToInt64. (andersrum ist die 64 einfach nur überladen, da dort automatisch entschieden wird, anhand des Parameters)
|
AW: POS findet was das ich nicht verstehe... ?
Könnte ich machen. Aber die Werte in den Strings werden in LowPart und HighPart eines TULargeInteger eingetragen.
|
AW: POS findet was das ich nicht verstehe... ?
Zitat:
Wie wäre es (beim Ansatz 'self documenting code') mit drei Funktionen?
Delphi-Quellcode:
DAS wäre dann selbstdokumentierend. Finde ich.
Function HasParameter (const AText, AParamName : string) : Boolean;
Function GetOptionalParamValue (const AText, AParamName : string) : String; Function GetMandantoryParamValue (const AText, AParamName : string) : String; |
AW: POS findet was das ich nicht verstehe... ?
Zitat:
![]() Der Code-Wert wird aber dort nur auf
Delphi-Quellcode:
oder
= 0
Delphi-Quellcode:
ausgewertet, so dass man diese Teile auch problemlos so hätte deklarieren können:
<> 0
Delphi-Quellcode:
function TryStrToInt( const S: string; out Value: Integer ) : Boolean;
var E: Integer; begin Val(S, Value, E); Result := E = 0; end; function StrToInt(const S: string): Integer; begin if not TryStrToInt(S, Result) then ConvertErrorFmt(@System.SysConst.SInvalidInteger, [S]); end; function StrToIntDef(const S: string; Default: Integer): Integer; begin if not TryStrToInt(S, Result) then Result := Default; end; |
AW: POS findet was das ich nicht verstehe... ?
Gut. Damit verstehe ich Dich.
|
AW: POS findet was das ich nicht verstehe... ?
Zitat:
Delphi-Quellcode:
und als Basis für alle kann man dann diese Funktion nutzen
Function HasParameter (const AText, AParamName : string) : Boolean;
Function GetOptionalParamValue (const AText, AParamName, ADefault : string) : String; // ADefault fehlte Function GetMandantoryParamValue (const AText, AParamName : string) : String;
Delphi-Quellcode:
function TryGetParamValue(const AText, AParamName : string; out Value : string ) : Boolean;
begin ... end; |
AW: POS findet was das ich nicht verstehe... ?
Warte mal, dann braucht man doch nur zwei Funktionen: 'HasParameter' und 'GetParameter'. Fertig. 'GetParameter' wirft eine Exception, wenn der Parameter nicht zu finden ist und das Defaultzeugs kann man sich zusammenbauen:
Delphi-Quellcode:
So isses chön, ne?
Function GetOptionalParameter (const aText, aParam, aDefault : String) : String;
Begin if HasParameter (aParam, aText) then result := GetParameter (aText, aParam) else result := aDefault; End; |
AW: POS findet was das ich nicht verstehe... ?
Zitat:
Delphi-Quellcode:
raus :mrgreen:
TryGetParamValue
|
AW: POS findet was das ich nicht verstehe... ?
Darum geht es nicht. Ich kann auch alles in eine Methode packen, die hochredundant ist, alles in einem Abwasch durchläuft und spuperduperperformant ist. Leider widersprechen sich Lesbarkeit und Performance häufig.
'Richtig' implementiert ist auch so eine Sache: Entweder gehe ich auf Lesbarkeit, Clean Code o.ä, oder eben auf 'richtig flott'. Hier dachte ich, es geht um Lesbarkeit, Das man in der konkreten Implementierung u.U. eine Codezeile doppelt ausführt, ist dann eben so und kein Verstoß gegen DRY. By DRY geht es ja um die Vermydung von Codeblockduplikaten, nicht von einfachen Aufrufen.
Delphi-Quellcode:
Na, issok?
Function HasParameter (aText, aParam : String) : Boolean;
Begin Result := ParameterIndex (aText, aParam) > 0; End; Function GetParamValue(aText, aParam : String) : Boolean; Begin i := ParameterIndex(aText, aParam); if i=0 then Raise Exception.Create('Parameter gibbet nich'); Result := ReadValueStartingAtPos(aText, i); End; |
AW: POS findet was das ich nicht verstehe... ?
Nun ja,
um den ParameterIndex zu ermitteln, muss der Text durch einen "Parser" (wo fängt der Wert zum Parameter an). Um den ParameterWert zu ermitteln, muss der Text wieder durch einen "Parser" (wo hört der Wert zum Parameter auf). Da das nicht nur sehr ähnlich ist (des Einen Ende ist des Anderen Anfang) würde ich das in einer Funktion implementieren. Dann ist es der sogenannte DRY KISS ;) |
AW: POS findet was das ich nicht verstehe... ?
Zitat:
Hier wird genau einmal geparst.
Delphi-Quellcode:
PS: Was ist eigentlich das Gegenteil von DRY KISS? Der WET FART? :stupid:
Function ParameterIndex (aText, aParam : String) : Integer;
Begin if ParamDictionary.Contains(aParam) then result := ParamDictionary[aParam] else begin result := FindParam(aText,aParam); ParamDictionary.Add(aParam, Result); end end; Im Ernst: DRY ist ja ganz nett als Programmierparadigma. Aber wenn ich dann schlechter lesbaren Code produziere, dann muss ich mich entscheiden. Ich persönlich kann mit diesen kombinierten Sachen nichts anfangen. Und über den besten Code kann man vortrefflich streiten (oder ein Bier aufmachen). Es kommt auf die Implementierung an. Wichtig ist, das ich vorne ein einfaches und minimales Interface habe. Was ich damit anstelle ('TryGet' etc.) ist dann etwas anderes. Edit: Und natürlich ist der Ansatz, das ganze einmal zu parsen ('TryParse'), im Sinne von DRY optimal. Aber DRY ist nicht alles. Es gibt auch noch den 'Clean Code' Ansatz (dessen eine Facette DRY ist). Beides komplett unter einen Hut zu bekommen, ist manchmal nicht so leicht. Letztendlich würde man hier den Parameter in den Vordergrund stellen, eine entsprechend Klasse entwicklen, die sich aus dem Text einmalig die Position ermittelt. Und dann diesem Parameter die hier vorgestellten Methoden 'Exists' (aka 'HasParameter') und 'Value' spendieren. Hier haben wir ja aus einer einfachen Idee ('Richtig machen') auf prozeduraler Ebene versucht, moderne Konzepte anzuwenden. Das geht nicht ohne Weiteres. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:27 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