Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   wann wird eine If Abfrage verlassen (https://www.delphipraxis.net/183550-wann-wird-eine-if-abfrage-verlassen.html)

bernhard_LA 19. Jan 2015 08:52


wann wird eine If Abfrage verlassen
 
wir verwenden folgenden Code

Delphi-Quellcode:
  If (length(ValueA)=0) or (length(ValueA)> 0 and ValueA[0] < 1) then
     begin
        doA(...);
     end
     else
     begin
        doB(...)
     end;


Auf einem Arbeitsplatzsystem (Win7, DELPHI XE2) wird der gesamte Code fehlerfrei ausgeführt. Dh. Falls die Länge von ValueA = 0 dann verzichtet er auf eine Prüfung von (length(ValueA)> 0 and ValueA[0] < 1);

Auf einem zweiten System versucht sich aber immer auch noch an der Prüfung von (length(ValueA)> 0 and ValueA[0] < 1) und wirft eine AV wenn length(ValueA)=0.
Warum bricht Delphi die Abfrage nicht immer ab wenn die erste Bedingung erfüllt ist, die zweite bräuchte er ja nicht mehr zu prüfen ...

Mavarik 19. Jan 2015 08:54

AW: wann wird eine If Abfrage verlassen
 
{$B-}

Mavarik

Sherlock 19. Jan 2015 08:56

AW: wann wird eine If Abfrage verlassen
 
Das ist eine Compiler-Option. Die nennt sich vollständige boolsche Auswertung. Wenn das auf "False" steht, dann bricht die Auswertung ab, sobald das Ergebnis feststeht. Bei "verundeten" Ausdrücken, dann also beim ersten False - bei "veroderten" beim ersten True.

Sherlock

mkinzler 19. Jan 2015 08:57

AW: wann wird eine If Abfrage verlassen
 
Das kann man Einstellen. Bei ein und dem selben Kompilat sollte es sich aber auf allen Rechnern identisch verhalten

http://docwiki.embarcadero.com/RADSt...r-Direktive%29

himitsu 19. Jan 2015 09:20

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Delphi-Quellcode:
If (length(ValueA) = 0) or (length(ValueA) > 0 and ValueA[0] < 1) then

Und dann fehlen hier auch nich ein paar Klammen, denn es müsste ja eigentlich so aussehn
Delphi-Quellcode:
If (length(ValueA) = 0) or ((length(ValueA) > 0) and (ValueA[0] < 1)) then


Und da das Length>0 zwangsläufig True sein muß, wenn Length=0 nicht angeschlagen hat, könnte man es auch weglassen.
Delphi-Quellcode:
If (length(ValueA) = 0) or (ValueA[0] < 1) then



Standardmäßig sollte diese Option besser deaktiviert bleiben und ansonsten nur lokal dort aktiv, für die einen IF-Auswertung, bzw. für die eine Unit, wo es unbedingt aktiv sein muß.
Drum bringt es hier natürlich auch erstmal nichts, wenn man drüber nachdenken würde, was man wie ändern muß, wenn diese Option aktiv wäre. (in mehrere IFs aufteilen)
Also wenn in den Projektoptionen aktiv, dann dort abschalten.

Der schöne Günther 19. Jan 2015 09:43

AW: wann wird eine If Abfrage verlassen
 
Warum das in Delphi ein globaler (ziemlich auffälliger) Compilerschalter ist und nicht wie in so ziemlich allen Sprachen ein "&&" bzw "&" habe ich nie verstanden...

Jumpy 19. Jan 2015 09:44

AW: wann wird eine If Abfrage verlassen
 
Was ist denn eigentlich ValueA?

Ein String? Dann kann doch das nicht klappen: ValueA[0] < 1

Oder ist das ein Array of Integer oder sowas?

mkinzler 19. Jan 2015 09:56

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1287016)
Warum das in Delphi ein globaler (ziemlich auffälliger) Compilerschalter ist und nicht wie in so ziemlich allen Sprachen ein "&&" bzw "&" habe ich nie verstanden...

Du kannst ihn auch lokal setzen

himitsu 19. Jan 2015 10:01

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von Jumpy (Beitrag 1287017)
Was ist denn eigentlich ValueA?

Ein String kann es nicht sein, da sonst der Compiler gemecktert hätte ... vonwegen der Kompatibilität zwischen Char und Integer. :angel2:
Und die neuen Strings, in den mobilen Plattformen, sind nun standardmäßig auch 0-basierend.

p80286 19. Jan 2015 10:09

AW: wann wird eine If Abfrage verlassen
 
Und was ist mit dem allseits beliebten
Delphi-Quellcode:
if (length(a)>0) and (copy(a,1,1)='H') then
bei einem Leerstring würde die vollständige Auswertung nicht so doll sein
Bei einer ganzen Latte von ifs die sich mit einem String beschäftigen wäre eine Aufteilung natürlich sinnvoller (da gibts dann keine vollständige Auswertung mehr):
Delphi-Quellcode:
if length(a)>0 then begin
  if copy(a,1,1)='G' then..
  if a[length(a)]='\' then ...
end;
Gruß
K-H

uligerhardt 19. Jan 2015 10:45

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1287016)
Warum das in Delphi ein globaler (ziemlich auffälliger) Compilerschalter ist und nicht wie in so ziemlich allen Sprachen ein "&&" bzw "&" habe ich nie verstanden...

&/&& unterscheidet doch (zumindest in C und Konsorten) zwischen Bitarithmetik und boolescher Logik und hat nichts mit short circuit zu tun?

Der schöne Günther 19. Jan 2015 11:02

AW: wann wird eine If Abfrage verlassen
 
Ja und dementsprechend kürzt ein "||" doch auch ab während es ein "|" ja gar nicht tun kann?

Code:
#pragma hdrstop
#pragma argsused

#include <tchar.h>
#include <stdio.h>

#include <iostream>

bool someFunc1() {
   return true;
}

bool someFunc2() {
    std::cout << "Jemand rief someFunc2() auf" << std::endl;
   return true;
}


int _tmain(int argc, _TCHAR* argv[])
{
   std::cout
      << "Mit || ist das Ergebnis "
      << (someFunc1() || someFunc2())
      << std::endl;

   std::cout << std::endl;

   std::cout
      << "Mit | ist das Ergebnis "
      << (someFunc1() | someFunc2())
      << std::endl;

   getchar();
   return 0;
}

Ergibt
Code:
Mit || ist das Ergebnis 1

Jemand rief someFunc2() auf
Mit | ist das Ergebnis 1

Falls ich mich jetzt vertue brauche ich echt Urlaub...

uligerhardt 19. Jan 2015 11:09

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1287040)
Ja und dementsprechend kürzt ein "||" doch auch ab während es ein "|" ja gar nicht tun kann?

Ach so, kann sein. :mrgreen:

himitsu 19. Jan 2015 11:36

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von p80286 (Beitrag 1287026)
Und was ist mit dem allseits beliebten
Delphi-Quellcode:
if (length(a)>0) and (copy(a,1,1)='H') then
bei einem Leerstring würde die vollständige Auswertung nicht so doll sein

Nee, knallt natürlich nicht, da Copy die Stringlänge beachtet und weniger zurückgibt, wie verlangt wurde, wenn weniger drin ist.

Kann man also problemlos auf
Delphi-Quellcode:
if copy(a,1,1)='H' then
kürzen und ansonsten wäre es auch egal, ob vollständig ausgewertet wird oder nicht.

Hier gäbe es aber Probleme
Delphi-Quellcode:
if (length(a)>0) and (a[1]='H') then
,
aber da "standardmäßig" nicht vollsändig ausgewertet wird, ist der Code eigentlich optimaler, da nicht "sinnlos" ein neuer String erstellt und freigegeben wird.

p80286 19. Jan 2015 14:30

AW: wann wird eine If Abfrage verlassen
 
Das ein
Delphi-Quellcode:
copy(a,1,maxint)
funktioniert habe ich ja schon dankbar zur Kenntnis genommen, daß das auch für leere Strings gilt war mir neu.
Naja man lernt nicht aus.

Gruß
K-H

himitsu 19. Jan 2015 15:19

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Delphi-Quellcode:
copy(a,3,maxint)

Inzwischen geht auch
Delphi-Quellcode:
copy(a,3)
:angel:

Dejan Vu 20. Jan 2015 07:48

AW: wann wird eine If Abfrage verlassen
 
Wenn ich so etwas sehe:
Delphi-Quellcode:
If (length(ValueA)=0) or (length(ValueA)> 0 and ValueA[0] < 1) then
...
muss ich immer 2x hinschauen. Auch später, beim Lesen des Codes. Also überlege ich mir "Was bedeutet das eigentlich". Z.B. will ich sicherstellen, das 'ValueA' mindestens einen gültigen Wert enthält. Also schreibe ich
Delphi-Quellcode:
If HasAtLeastOneValidValue(ValueA) then
. *DAS* kann man lesen.
Nächster Schritt. Was bedeutet also 'HasAtLeastOneValidValue' ? :gruebel: Also ausformulieren
Delphi-Quellcode:
function HasAtLeastOneValidValue (aArray : TIntegerArray) : Boolean;
Begin
  if Length(aArray)=0 then exit(false);
  if aArray[0]<1 then exit(false);
  exit(true);
end;
Unit-Test für diese Idiotenfunktion schreiben, läuft, fertig. Kommentieren? Wieso? Ist sie doch schon. Falls mir das nicht reicht, mit dem Kommentar, mach ich Folgendes:
Delphi-Quellcode:
function HasAtLeastOneValidValue (aArray : TIntegerArray) : Boolean;
Begin
  if IsEmpty(aArray) then
     exit (false);

  result := ElementIsValid(aArray[0]);
end;

Function IsEmtpy (aArray : TIntegerArray) : Boolean;
begin
  result := Length(aArray) = 0;
end;

Function ElementIsValid(aElement : Integer) : Boolean;
begin
  result := aElement >= 1;
end;
Das versteht selbst Oma. Ich persönlich würde wirklich so weit gehen.

Aber irgendwann fällt meinem Kollegen (ein Performancefetischist) auf, das man die Funktion verkleinern kann. Kein Problem, wir haben ja den Unittest. Also macht er vielleicht später daraus einen Einzeiler. Oder auch nicht, vollkommen egal.

Ich komme durch dieses Refactoring bzw. Top-Down-Programmieren mit stufenweiser Verfeinerung bei etwas komplexeren boolschen Ausdrücken nie in die Verlegenheit, den Ausdruck in eine Zeile zu quetschen, sondern kann mich in der Funktion nach Herzenslust austoben. Das erhöht die Lesbarkeit enorm (gut, es ist etwas kleinlich), aber wenn ich nach 10 Jahren nochmal reinschaue, verstehe ich es immer noch. Und mir ist das sehr wichtig.

Zitat:

Zitat von Der schöne Günther (Beitrag 1287016)
Warum das in Delphi ein globaler (ziemlich auffälliger) Compilerschalter ist und nicht wie in so ziemlich allen Sprachen ein "&&" bzw "&" habe ich nie verstanden...

Das ist doch ganz einfach:

A and B ist ein Boolscher Ausdruck, bei dem selbstverständlich -rein mathematisch gesehen- A und B ausgerechnet bzw. ermittelt wird. Irgendwann, als die CPU noch langsam waren, kam jemand auf die Idee, das B (oder A?) gar nicht ausgerechnet werden muss, wenn FALSE beim ersten Element rauskommt. Wow. Optimierung war damals hoch im Kurs. Blöd für die Compiler, die einen Ausdruck von rechts nach links ausgewertet haben (C war früher so -glaube ich-). Da kommt man dann durcheinander, weswegen ich mich früher nie darauf verlassen habe, sondern immer 'If A then if B then' geschrieben habe.

Aber da Delphi ursprünglich aus Turbopascal entstanden und Turbopascal auch in Felsmalereien in Steinzeithöhlen zu finden ist, hat sich das bis heute so gehalten. Bei Delphi wird Tradition noch groß geschrieben.

Wie hättest Du es denn gerne?
Delphi-Quellcode:
If A andthen B then
Delphi will ja partout keine kurzen Operatoren... :stupid:

Der schöne Günther 20. Jan 2015 08:13

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von Dejan Vu (Beitrag 1287099)
und Turbopascal auch in Felsmalereien in Steinzeithöhlen zu finden ist, [...]

Klasse :-D Wer kann mit Photoshop umgehen und so etwas mal zaubern?

Alternativ könnten die nächsten Delphitage ja auch in irgendeiner archäologischen Grabungsstätte stattfinden.

uligerhardt 20. Jan 2015 08:19

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von Dejan Vu (Beitrag 1287099)
Wie hättest Du es denn gerne?
Delphi-Quellcode:
If A andthen B then
Delphi will ja partout keine kurzen Operatoren... :stupid:

Du meinst AndAlso? :mrgreen:

OlafSt 20. Jan 2015 10:19

AW: wann wird eine If Abfrage verlassen
 
Warum denn auch nicht ? So hat man die Wahl, ohne irgendwelche mysteriösen Compilerschalter setzen zu müssen.

BTW, neben AndAlso gibts auch noch OrElse als Shortcut-Bool-Or. Ich geb zu, muß mich da auch erst dran gewöhnen ;)

p80286 20. Jan 2015 11:21

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1287101)
Zitat:

Zitat von Dejan Vu (Beitrag 1287099)
und Turbopascal auch in Felsmalereien in Steinzeithöhlen zu finden ist, [...]

Klasse :-D Wer kann mit Photoshop umgehen und so etwas mal zaubern?

Alternativ könnten die nächsten Delphitage ja auch in irgendeiner archäologischen Grabungsstätte stattfinden.

Kein Problem, das >Essen mit Messer und Gabel wurde ja auch erst mit Delphi3 eingeführt.

Gruß
K-H

himitsu 20. Jan 2015 12:09

AW: wann wird eine If Abfrage verlassen
 
Zitat:

Zitat von OlafSt (Beitrag 1287116)
Ich geb zu, muß mich da auch erst dran gewöhnen ;)

Es wäre in der Delphi-Syntax nicht das Problem hierfür entweder ein neues
Delphi-Quellcode:
a andxxx b
oder
Delphi-Quellcode:
a orxxx b
oder
Delphi-Quellcode:
a xxx or b
einzuführen.

Problem wäre dann nur, wie man hier dem Compiler sagt, daß er dann nur diesen einen Operator so behandeln soll nicht nicht alles in dem IF. (das wäre dann aber eine Angelegenheit für den Compilerentwickler, bzw. ob man das ans LLVM übergeben kann und der das dann kann)


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:05 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