Autor Beitrag
delphi10
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 447
Erhaltene Danke: 2

W2K, XP, Vista64, Win7 64
RAD-Studio 2010
BeitragVerfasst: Sa 16.10.10 01:29 
Hallo
Warum erzeugt dieses For-Konstrukt
ausblenden Delphi-Quelltext
1:
2:
3:
  For x := 1 to length(ErrorText) do
  if ErrorText[x] = '&' then
  delete(ErrorText,Pos('&',ErrorText),1);

keine Fehlermeldung wenn im Text ein oder mehrere & vorkommen? Durch die Änderung der to-Varible würde ich einen Fehler erwarten, läuft aber einwandfrei.
Gruss Delphi10

_________________
Salus populi suprema lex esto
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Sa 16.10.10 01:35 
user profile icondelphi10 hat folgendes geschrieben Zum zitierten Posting springen:
Warum erzeugt dieses For-Konstrukt
ausblenden Delphi-Quelltext
1:
2:
3:
  For x := 1 to length(ErrorText) do
  if ErrorText[x] = '&' then
  delete(ErrorText,Pos('&',ErrorText),1);

keine Fehlermeldung wenn im Text ein oder mehrere & vorkommen? Durch die Änderung der to-Varible würde ich einen Fehler erwarten, läuft aber einwandfrei.
Gruss Delphi10
Siehe z. B. hier: www.delphipraxis.net...ife-rueckwaerts.html

Für diesen Beitrag haben gedankt: delphi10
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: Sa 16.10.10 01:56 
In dem Fall würde ich aber ne FOR-IN-Schleife verwenden, wenn du schon das RAD-Studio 2010 hast. Nur so zur Sicherheit. Weil da wird dann jedes Element genau einmal ausgewählt (Falls es überhaupt mit Strings geht, aber eigentlich sollte es).

_________________
This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.

Für diesen Beitrag haben gedankt: delphi10
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Sa 16.10.10 02:02 
user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
In dem Fall würde ich aber ne FOR-IN-Schleife verwenden, wenn du schon das RAD-Studio 2010 hast. Nur so zur Sicherheit. Weil da wird dann jedes Element genau einmal ausgewählt (Falls es überhaupt mit Strings geht, aber eigentlich sollte es).
Ich würde mich beim Programmieren nicht auf irgendwelche Schalterstellungen in der IDE verlassen. Richtig wäre, die Schleife runter zählen zu lassen, und das auch entsprechend zu coden.

Für diesen Beitrag haben gedankt: Hidden
delphi10 Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 447
Erhaltene Danke: 2

W2K, XP, Vista64, Win7 64
RAD-Studio 2010
BeitragVerfasst: Sa 16.10.10 02:03 
user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
In dem Fall würde ich aber ne FOR-IN-Schleife verwenden, wenn du schon das RAD-Studio 2010 hast. Nur so zur Sicherheit. Weil da wird dann jedes Element genau einmal ausgewählt (Falls es überhaupt mit Strings geht, aber eigentlich sollte es).

Das stammt noch aus einem alten Projekt mit Studio 2006 das ich gerade aufmöbele. Trotzdem Danke.
Der Hinweis von @Gerd Kayser hat meinem organischen Speicher wieder reorganisiert. Man(n) wird älter.

_________________
Salus populi suprema lex esto
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 16.10.10 07:18 
Zu deiner Ausgangsfrage: Wenn du die Bereichsüberprüfung nicht angeschaltet hast, merkt dein Programm ganz einfach nicht, dass es ggf. bereits hinter dem Ende des Strings liest. ;-)

Solange hinter dem Speicherbereich des Strings also keine nicht zugreifbaren Speicherbereiche liegen, kommt auch keine Zugriffsverletzung. Sollte da zufällig ein Zeichen gefunden werden, weil da diese Bytewerte liegen, passiert auch kein Schreibzugriff, da Delete nichts tut, da der Zugriff hinter dem Ende des Strings liegt.

Wenn du einen String versucht hättest, bei dem zwei der gesuchten Zeichen hintereinander liegen, hätte es nicht funktioniert, da das zweite Zeichen nach dem Delete aufgerückt ist und nicht mehr geprüft wird.

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
In dem Fall würde ich aber ne FOR-IN-Schleife verwenden, wenn du schon das RAD-Studio 2010 hast. Nur so zur Sicherheit. Weil da wird dann jedes Element genau einmal ausgewählt (Falls es überhaupt mit Strings geht, aber eigentlich sollte es).
Ja, es geht mit Strings. In diesem Fall aber nicht, denn es soll ja gerade der String verändert werden. Und das geht nicht, wenn for...in benutzt wird. Denn das funktioniert wie jede andere for-Schleife: Die Randbedingungen werden vorher ausgelesen.
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Sa 16.10.10 08:12 
Wahrscheinlich wäre hier ein While-Konstrukt besser. Möglicherweise ist der jedoch nicht so schnell, da jedesmal ein Pos(sub,s) abgefragt wird, aber er sollte alle Zeiche(folgen) erfassen:

ausblenden Delphi-Quelltext
1:
2:
while Pos('&',Errortext)>0 do 
  Delete(ErrorText,Pos('&',ErrorText),1);


Dies gilt natürlich nur, wenn nicht ausdrücklich eine FO-Schleife gefordert ist.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 16.10.10 08:15 
Das ist hier aber deutlich ungünstiger (noch verstärkt dadurch, dass du das Ergebnis von Pos nicht einmal zwischenspeicherst).

Der bereits genannte Weg mit der umgedrehten for-Schleife ist schon der richtige. Das funktioniert auch, ist aber deutlich schneller.
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Sa 16.10.10 08:19 
Sicher, für das Löschen einzelner Zeichen ist mein Konstrukt sicher langsamer als eine For-Schleife. Doch was ist mit dem Löschen einer Zeichenfolge? Z.B. statt '&' '###' oder ...? Dann wird ein For-Konstrukt deutlich komplizierter, oder? Außerdem, wenn das Zeichen in einem String als Platzhalter für andere Texte steht? Dann ist das in einer umgekehrten FOR-Schleife ebenfalls nicht so einfach machbar.

Flexibilität ist leider oft mit Geschwindigkeitsverlust verbunden.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 16.10.10 08:30 
Erstens gibt es dann noch StringReplace, das wahrscheinlich immer noch besser optimiert ist, zweitens ist das nicht so schwer. Mal so runtergeschrieben, sollte funktionieren:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
function DeleteFromString(const AFrom, ADelString: string): string;
var
  i, CurPos: Integer;
begin
  Result := AFrom;
  if (Length(AFrom) > 0and (Length(ADelString) > 0then
  begin
    CurPos := Length(ADelString);
    for i := Length(Result) downto 1 do
      if ADelString[CurPos] = AFrom[i] then
        if CurPos = 1 then
        begin
          Delete(Result, i, Length(ADelString));
          CurPos := Length(ADelString);
        end
        else
          Dec(CurPos)
      else
        CurPos := Length(ADelString);
  end;
end;
Mit Boyer-Moore könnte man noch ein bisschen mehr Geschwindigkeit herausholen. ;-)

Für diesen Beitrag haben gedankt: delphi10
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Sa 16.10.10 11:24 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Zu deiner Ausgangsfrage: Wenn du die Bereichsüberprüfung nicht angeschaltet hast, merkt dein Programm ganz einfach nicht, dass es ggf. bereits hinter dem Ende des Strings liest. ;-)
Nö, das ist nicht die eigentliche Ursache. Wenn die Delphi-Optimierung eingeschaltet ist, wird aus einer to-Scheife eine downto-Schleife. Bei einer downto-Schleife tritt der Effekt nicht auf, d. h. ein Lesen hinter dem String passiert nicht. Interessant wird es erst, wenn die Optimierung abgeschaltet wird, um vielleicht an einer anderen Stelle zu debuggen. Man sollte sich also nie auf die Compilerschalterchen verlassen und sich angewöhnen, gleich richtig eine downto-Schleife zu verwenden.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 16.10.10 11:27 
Die Optimierung passiert nur im Hintergrund. Diese hat aber keinen Effekt auf die tatsächlich angesprochenen Indizes des Strings...
Dass die Schleife in Wirklichkeit rückwärts läuft, hat also keinen Effekt. Wäre ja auch schlimm sonst.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Sa 16.10.10 12:34 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Die Optimierung passiert nur im Hintergrund. Diese hat aber keinen Effekt auf die tatsächlich angesprochenen Indizes des Strings...
Dass die Schleife in Wirklichkeit rückwärts läuft, hat also keinen Effekt. Wäre ja auch schlimm sonst.
Ich habe gerade versucht, dieses Verhalten nachzustellen. Leider ohne Erfolg. Entweder war ich da auf dem Holzweg oder meine Erinnerung trügt mich. Ich meine vor etwa einem Jahr eine Schleife programmiert zu haben, die sich anders als erwartet verhielt, und demzufolge Murks produzierte.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TMainform.Button1Click(Sender: TObject);
var
  EinString  : string;
  Schleife   : integer;
begin
  EinString := 'Hallo Welt';
  for Schleife := 1 to Length(EinString) do
    if EinString[Schleife] = 'l' then
      Delete(EinString,Pos('l',EinString),1);
  ShowMessage(EinString);
end;

procedure TMainform.Button2Click(Sender: TObject);
var
  EinString  : string;
  Schleife   : integer;
begin
  EinString := 'Hallo Welt';
  for Schleife := Length(EinString) downto 1 do
    if EinString[Schleife] = 'l' then
      Delete(EinString,Pos('l',EinString),1);
  ShowMessage(EinString);
end;

Wie dem auch sei: Beide Prozeduren liefern jedenfalls unterschiedliche Ergebnisse.
Prozedur 1: Hao Welt
Prozedur 2: Hao Wet
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 16.10.10 12:50 
Naja, ist ja logisch, du prüfst an der Stelle der Schleifenvariablen und löschst an der ersten Position des Zeichens... Dass es dann einen Unterschied zwischen den Laufrichtungen gibt, ist klar. ;-)
delphi10 Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 447
Erhaltene Danke: 2

W2K, XP, Vista64, Win7 64
RAD-Studio 2010
BeitragVerfasst: Sa 16.10.10 12:51 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Erstens gibt es dann noch StringReplace, das wahrscheinlich immer noch besser optimiert ist, zweitens ist das nicht so schwer. Mal so runtergeschrieben, sollte funktionieren:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
function DeleteFromString(const AFrom, ADelString: string): string;
var
  i, CurPos: Integer;
begin
  Result := AFrom;
  if (Length(AFrom) > 0and (Length(ADelString) > 0then
  begin
    CurPos := Length(ADelString);
    for i := Length(Result) downto 1 do
      if ADelString[CurPos] = AFrom[i] then
        if CurPos = 1 then
        begin
          Delete(Result, i, Length(ADelString));
          CurPos := Length(ADelString);
        end
        else
          Dec(CurPos)
      else
        CurPos := Length(ADelString);
  end;
end;
Mit Boyer-Moore könnte man noch ein bisschen mehr Geschwindigkeit herausholen. ;-)

Ich hab das mal eben implantiert. Läuft einwandfrei, wobei mir eine Optimierung nicht so wichtig ist. Hier werden Systemmeldungen für einen Mailbody zusammengestellt - da ist dann sowieso alles zu spät. Dummerweise verträgt Outlook im automatisch generierten Bodytext keine '&', daher der Aufwand.
Gruß Delphi10
edit: Die For-Schleife erwischt in der Tat nur einzelne '&', wenn mehrere hintereinander stehen versagt die Methode.

_________________
Salus populi suprema lex esto
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Sa 16.10.10 16:51 
1. Der ganz Obenstehende Code funktioniert bei mir nicht, voraussetzend dass er alle & in einem text löschen soll: aus "salbader&&&blubl&&ub&" wird "salbaderblubl&ub&"
2. Ich mache das immer so, wenn ich z.B. aus Listen lösche, und funktioniert einwandfrei:
ausblenden Delphi-Quelltext
1:
2:
3:
For x := length(ErrorText) downto 1 do
  if ErrorText[x] = '&' then
  delete(ErrorText,Pos('&',ErrorText),1);


Hier wird zwar die From-Klausel geändert, aber das aktuelle Element ist stets gültig, und ich hatte noch nie Probleme damit.

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 16.10.10 17:23 
user profile iconTilman hat folgendes geschrieben Zum zitierten Posting springen:
1. Der ganz Obenstehende Code funktioniert bei mir nicht
Das hatte ich ja schon geschrieben, ich hatte es zwar nicht ausprobiert, aber rein logisch war das klar.

user profile iconTilman hat folgendes geschrieben Zum zitierten Posting springen:
2. Ich mache das immer so, wenn ich z.B. aus Listen lösche, und funktioniert einwandfrei:
Das ist doch auch Unfug (außer die richtige Schleifenrichtung, aber die ist ja nun hinreichend schon erwähnt worden). Wie ich schon weiter oben geschrieben habe: Wozu prüfst du, ob das aktuelle Zeichen das passende ist, wenn du dann ein ganz anderes (das erste nämlich wegen Pos) löschst?!?
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Sa 16.10.10 17:28 
Jo jaenicke da hast du recht, hatte mir den Code nicht genau genug angesehen, muss natürlich
ausblenden Delphi-Quelltext
1:
2:
3:
For x := length(ErrorText) downto 1 do
  if ErrorText[x] = '&' then
  delete(ErrorText,x,1);
lauten

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Sa 16.10.10 17:49 
Was hindert euch jetzt eigentlich daran, die Perfomance zu ignorieren und
ausblenden Delphi-Quelltext
1:
StringReplace(ErrorText, '&','',[rfReplaceAll])					

zu verwenden?

Duct Tape Programming: funktionierender (und selbstdokumentierender) Code zuerst, optimieren kann man immer noch, wenn sich Probleme zeigen. Und das dürfte bei einer Funktion die Mails verschickt wohl nicht passieren...

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."

Für diesen Beitrag haben gedankt: delphi10
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 16.10.10 18:29 
Ja, die Funktion hatte ich ja auch schon erwähnt. Die eigene Funktion war vor allem ne Demo, dass es durchaus einfach ist. ;-)