Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   FreePascal for-Schleife -Abbruch (https://www.delphipraxis.net/164489-schleife-abbruch.html)

thomasschaf 15. Nov 2011 13:29

for-Schleife -Abbruch
 
Hallo,

ich möchte in einer for-Schleife gewisse Durchläufe überspringen:

Das könnte ich so machen:
Delphi-Quellcode:
for x:=a to b do begin
  if f(x)>100 then begin
    ...
  end;
end;
Allerdings habe ich viele if-Abfragen, die ineinander verschachtelt sind, doch ich kann sie nicht mit einem AND verknüpfen, da gewisse innere nicht abgefragt werden dürfen, wenn die äußere(n) FALSE liefert.

Ich möchte soetwas wie:
Delphi-Quellcode:
for x:=a to b do begin
  if not (f(x)>100) then Exit;
  ...
end;
Das wäre besser, doch bei mir wird die komplette Schleife beendet. Ich möchte aber nur gewisse Durchläufe überspringen.

Bitte um Hilfe,

Thomas

ChrisE 15. Nov 2011 13:32

AW: for-Schleife -Abbruch
 
Zitat:

Zitat von thomasschaf (Beitrag 1136297)
Ich möchte aber nur gewisse Durchläufe überspringen.

Hi Thomas,

Delphi-Quellcode:
for x:=a to b do begin
  if not (f(x)>100) then continue;
  ...
end;
Gruß, Chris

himitsu 15. Nov 2011 13:51

AW: for-Schleife -Abbruch
 
Delphi-Referenz durchsuchenExit ist eigentlich nicht zum Beenden/Abbrechen von Schleifen gedacht, sondern zum Verlassen ganzer Prozeduren/Funktionen.

Delphi-Referenz durchsuchenBreak für Schleifen und dann eben noch das Delphi-Referenz durchsuchenContinue zum Überspringen.


PS: Ich würde eher den Vergleichsoperator umdrehen und auf das Not verzichten. :angle:

TiGü 15. Nov 2011 14:27

AW: for-Schleife -Abbruch
 
Zitat:

Zitat von thomasschaf (Beitrag 1136297)
Allerdings habe ich viele if-Abfragen, die ineinander verschachtelt sind, doch ich kann sie nicht mit einem AND verknüpfen, da gewisse innere nicht abgefragt werden dürfen, wenn die äußere(n) FALSE liefert.

Anmerkung:
Sobald eine Bedingungen in der if-Abfrage fehlschlägt, werden alle folgenden nicht mehr geprüft. Kannst also schon Schachteln!

Beispiel:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
   if GetAFalseBooleanValue and GetATrueBooleanValue then
    OutputDebugString(PWideChar('Wird niemals erreicht'));
end;

function TForm1.GetAFalseBooleanValue: Boolean;
begin
  Result := False;
  OutputDebugString(PWideChar('False - Siehtste mich???'));
end;

function TForm1.GetATrueBooleanValue: Boolean;
begin
  Result := True;
  OutputDebugString(PWideChar('True - Siehtste mich???'));
end;

thomasschaf 15. Nov 2011 14:37

AW: for-Schleife -Abbruch
 
Ach, so einfach :-D

Ich wusste doch, dass es einen Befehl dafür gibt ^^

Vielen Dank - so sieht mein Programm viel ordentlicher aus !

Thomas


Edit:
Zum "Schachteln" habe ich mich nicht so deutlich ausgedrückt, ich meinte soetwas:

Delphi-Quellcode:
if (a<>'') and (isnumeric(a)) and qx(a) then begin
  s:= a...
end;
Allerdings benütigt die Funktion "qx" schon einen numerischen nichtleeren String "a", ansonsten Fehler.
Daher muss ich machen:

Delphi-Quellcode:
if (a<>'') and isnumeric(a) then begin
  if qx(a) then s:=...
end;
so in der Art...

TiGü 15. Nov 2011 15:18

AW: for-Schleife -Abbruch
 
Zitat:

Zitat von thomasschaf (Beitrag 1136316)
Edit:
Zum "Schachteln" habe ich mich nicht so deutlich ausgedrückt, ich meinte soetwas:

Delphi-Quellcode:
if (a<>'') and (isnumeric(a)) and qx(a) then begin
  s:= a...
end;
Allerdings benütigt die Funktion "qx" schon einen numerischen nichtleeren String "a", ansonsten Fehler.

Nein, musst du nicht.
Bitte mein Beispiel mal ausprobieren!

Für dein Beispiel:
Sobald (a<>'') gleich false liefert, werden alle anderen Bedingungen die zwischen if und then stehen nicht abgefragt!

EDIT:

Würde die Prüfung sowieso in die IsNumeric() Funktion implementieren!

ChrisE 15. Nov 2011 15:32

AW: for-Schleife -Abbruch
 
Zitat:

Zitat von TiGü (Beitrag 1136322)
Nein, musst du nicht.
Bitte mein Beispiel mal ausprobieren!

BTW: Das stimmt nur, solange bei den Compiler-Option nicht die vollständige boolesche Prüfung aktiviert ist.

Gruß, Chris

leddl 15. Nov 2011 15:36

AW: for-Schleife -Abbruch
 
Zitat:

Zitat von thomasschaf (Beitrag 1136316)
Allerdings benütigt die Funktion "qx" schon einen numerischen nichtleeren String "a", ansonsten Fehler.

Dann würde ich an deiner Stelle diese Prüfung allerdings in der Funktion selbst einbauen.

Iwo Asnet 15. Nov 2011 17:02

AW: for-Schleife -Abbruch
 
Warum das Ganze nicht übersichtlich verpacken?

Delphi-Quellcode:
Function OperationIstLegal(KandidatenIndex : Integer) : Boolean;
Begin
  Result := False;
  If KandidatIstLeer(KandidatenIndex) Then Exit;
  If Not KandidatIstNumerisch(KandidatenIndex) Then Exit;
  If KandidatHatRoteHaare(KandidatenIndex) And HeuteIstDienstag() Then Exit;
 // Hier beliebig viele Prüfungen einfügen, anfügen, erklären usw.
 //
 // Und zum Schluss
  Result := True;
End;

Procedure DieEigentlicheSchleife;
Var
  i : Integer;
Begin
  For i:=1 to VerdammtHoheZahl do
    If OperationIstLegal(i) then
      FuehreOperationAus(i);
End;

jaenicke 15. Nov 2011 17:17

AW: for-Schleife -Abbruch
 
Erst schreibst du übersichtlich und dann widersprichst du dir indem du Exit in dieser Art und Weise benutzt... ;-)

thomasschaf 15. Nov 2011 18:27

AW: for-Schleife -Abbruch
 
Hallo und danke für die vielen Antworten :)

Am Beispiel habe ich ausprobiert, dass "A AND B" einen Fehler ergibt.

Weiß vielleicht jemand, wo ich das umstellen kann ?
Müsste ja irgendwo in "Compilereinstellungen" sein...
(In meiner Signatur steht, was ich benutze.)

Die Idee, die Überprüfung in der Funktion selbst einzubauen, ist aber wohl die beste (leddls Beitrag) !

Furtbichler 15. Nov 2011 19:21

AW: for-Schleife -Abbruch
 
Zitat:

Zitat von jaenicke (Beitrag 1136345)
Erst schreibst du übersichtlich und dann widersprichst du dir indem du Exit in dieser Art und Weise benutzt... ;-)

Ach Gott, noch so ein Methusalem aus den Tiefen der Uraltprogrammierung.

Ich finde es sehr übersichtlich. Und lesbar. Und kompakt.

Wie würdest Du das denn umsetzen, das es ebenso lesbar und kompakt und nicht redundant ist?

Lutex 15. Nov 2011 22:36

AW: for-Schleife -Abbruch
 
Genau. Ich persönlich finde es außerordentlich übersichtlich, wenn am Anfang einer Funktion die Bedingungen aufgelistet sind, unter denen sie nicht abgearbeitet werden soll (Objekt noch nicht komplett initialisiert, falsche Parameter, ungültige Zeiger...). Wo kann es eine sinnvollere Verwendung für das "exit" geben als hier?

himitsu 15. Nov 2011 23:05

AW: for-Schleife -Abbruch
 
Bei dem genannten Beispiel ist das halt kürzer und ein Exit ist unnötig, da vor/nach den Exit's nur das booleanische Result gesetzt wird ... also kann man die Ifbedingungen auch direkt an das Result weitergeben.
Delphi-Quellcode:
// man schreibt ja auch
Result := irgendwas;

// und nicht
if irgendwas then
  Result := True
else
  Result := False;

// oder
Result := False;
if irgendwas then
  Result := True;

// oder eben das genannte
Result := False;
if not irgendwas then
  Exit;
Result := True;
also demnach so
Delphi-Quellcode:
function OperationIstLegal(KandidatenIndex: Integer): Boolean;
begin
  Result := not KandidatIstLeer(KandidatenIndex)
    and KandidatIstNumerisch(KandidatenIndex)
    and not (KandidatHatRoteHaare(KandidatenIndex) and HeuteIstDienstag);
end;

Furtbichler 16. Nov 2011 06:43

AW: for-Schleife -Abbruch
 
himitsu, ein Widerspruch ist das ja nicht, nur Geschmackssache.

Egal wie: Eine Entscheidungsfunktion hat den großen Vorteil, das sie direkt lesbar, einfach wartbar und noch einfacher erweiterbar ist, und darum geht es doch in erster Linie bei der Programmierung.

Die Entscheidung findet an einer zentralen (EINE), benannten (KOMMENTIERTE) und ausgelagerten (FUNKTION) Stelle statt.

Die Bedingungen sind untereinander von der Aussage her äquivalent, denn sie benennen immer genau eine Bedingung, weshalb die Operation illegal ist.

Solange Du deine Entscheidungsfunktion auslagerst, und ordentlich refaktorisierst, kannst Du das natürlich auch mit einer AND/OR-Verknüpfung machen. Einen fundamentalen Unterschied sehe ich hier aber nicht.
Für mich ist meine Version meistens leichter zu lesen, das kann aber auch am Alter liegen.

Übrigens: Um A AND B so kompilieren zu lassen, das B nur dann evaluiert wird, wenn A TRUE ergibt, geht man in die Kompileroptionen und sucht nach etwas wie "komplette bool'sche Ausdrücke' oder ähnlich. Bei mir war das in den Optionen unten links, aber ich habe gerade kein Delphi.

jaenicke 16. Nov 2011 07:52

AW: for-Schleife -Abbruch
 
Das dort umzuschalten ist aber keine so gute Idee. Besser ist es das an der Stelle zu schreiben, die eine bestimmte Einstellung voraussetzt.
Sprich:
Delphi-Quellcode:
function OperationIstLegal(KandidatenIndex: Integer): Boolean;
begin
  {$BOOLEVAL OFF}
  Result := not KandidatIstLeer(KandidatenIndex)
    and KandidatIstNumerisch(KandidatenIndex)
    and not (KandidatHatRoteHaare(KandidatenIndex) and HeuteIstDienstag);
end;
Denn wenn man das in den Projektoptionen einstellt (wobei das aus Optimierungsgründen auch die Voreinstellung ist), verlässt man sich darauf, dass es dort korrekt eingestellt ist. Wenn aber jemand anderes das dort umstellt, kann er sich über die Folgen nicht bewusst sein, da dort ja keinerlei Bezug zu dem Quelltext besteht, wo die Einstellung ggf. anders benötigt wird.

Zitat:

Zitat von Furtbichler (Beitrag 1136409)
Einen fundamentalen Unterschied sehe ich hier aber nicht.
Für mich ist meine Version meistens leichter zu lesen, das kann aber auch am Alter liegen.

Fundamental ist der Unterschied auch nicht, aber es ist deutlich schneller zu sehen, wenn man als Unbeteiligter auf den Code schaut, wie das Result zugewiesen wird, wenn man nicht erst jede Zeile auf ein Exit durchschauen muss.
In diesem Fall ist das noch akzeptabel, aber ich habe schon Quelltexte gesehen wo ich große Mühe hatte den Quelltext genau nachzuvollziehen warum wo rausgesprungen wird und warum wo der Rückgabewert vorher gesetzt wurde...

Nebenbei gilt für mich der Grundsatz: Ein Befehl pro Zeile. Das Exit irgendwo hinten in der Zeile zu verstecken (statt es in eine neue Zeile zu schreiben) ist zusätzlich... suboptimal.

JamesTKirk 16. Nov 2011 09:43

AW: for-Schleife -Abbruch
 
Zitat:

Zitat von thomasschaf (Beitrag 1136352)
Am Beispiel habe ich ausprobiert, dass "A AND B" einen Fehler ergibt.

Weiß vielleicht jemand, wo ich das umstellen kann ?
Müsste ja irgendwo in "Compilereinstellungen" sein...
(In meiner Signatur steht, was ich benutze.)

Die Standardeinstellung von Free Pascal ist es boolsche Ausdrücke abzukürzen, wenn möglich. Da er keine Kommandozeilenoption hierfür kennt, bietet Lazarus auch keine Option dafür an. Die einzige Möglichkeit dies zu beeinflussen ist innerhalb des Quellcodes:

Delphi-Quellcode:
// Shortcuts einschalten
{$B-}
// oder
{$BOOLEVAL OFF}

// Shortcuts ausschalten
{$B+}
// oder
{$BOOLEVAL ON}
Siehe auch hier.

Ich glaube auch, dass es eine lokale Einstellung ist, das heißt, dass du dies für einzelne Bedingungen ändern kannst (müsste das jedoch nachprüfen).

Zur Semantik (vielleicht hattest du ja was vertauscht):

Bei einem AND wird abgebrochen, wenn die erste Bedingung FALSE ergibt (die gesamte Bedingung kann eh nicht mehr TRUE ergeben).
Bei einem OR wird abgebrochen, wenn die erste Bedingung TRUE ergibt (die gesamte Bedingung kann eh nicht mehr FALSE ergeben).

Gruß,
Sven

PS: Die aktuelle Version von Lazarus ist mittlerweile 0.9.30 mit Free Pascal 2.4.2. Wenn du noch etwas wartest sollte auch bald 0.9.30.2 (mit Free Pascal 2.4.4) veröffentlicht werden.

thomasschaf 18. Nov 2011 19:04

AW: for-Schleife -Abbruch
 
Danke, für die Antworten.
Jetzt ist es mir sehr klar geworden.

Die neue Version habe ich vor kurzem schon bereits probiert zu installieren, habe es nach einiger Zeit wegen zu vielen mir unbekannten Fehlern aufgegeben. Zusätzlich müsste ich die IDE dann noch neu kompilieren, weil ich sehr viel daran geändert habe (Komponenten hinzugefügt).


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz