Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - If-Anfrage: OR greift nicht


JustusJonas - Di 03.02.09 19:37
Titel: If-Anfrage: OR greift nicht
Hallo Leute,

ich hoffe die Frage wurde nicht schon so häufig gestellt, ich habe zumindest in der Boardsuche nichts gefunden.

Ich habe folgenden Code:

Delphi-Quelltext
1:
2:
if ((DayOfNow(Date) < 3and (Datum >= LastDayOfMonth2(Datum) -3)) or (Datum > (Date -3)) then 
begin


Leider wird die Abfrage nach dem "OR" nicht ausgeführt, da die Abfrage vor dem "OR" wohl true ist.

Ich möchte also eine Abfrage, die beide Bedingungen abprüft und nur wenn beide wahr sind, soll er weitermachen. So wie es mir scheint überprüft er jedoch nur alles vor dem OR und lässt die zweite Abfrage außer Acht.

Habt ihr eine Idee, was ich hier falsch mache? Ich komme einfach nicht dahiner.

Wenn ich die Anweisung in

Delphi-Quelltext
1:
2:
if (Datum > (Date -3)) then 
begin


ändere passiert übrigens genau das, was ich möchte!

Greetz


GTA-Place - Di 03.02.09 19:44

Delphi kürzt ab, sofern der erste Teil der If-Abfrage zutrifft. Ändern kannst du das mit der Compile-Direktive {$B+}. Du kannst das entweder allgemein auf die ganze Unit, oder nur für bestimmte Bereiche anwenden:


Delphi-Quelltext
1:
2:
3:
4:
{$B+}   // komplette Auswertung an
if ABC then
  // ...
{$B-}   // komplette Auswertung aus


Yogu - Di 03.02.09 20:18
Titel: Re: If-Anfrage: OR greift nicht
user profile iconJustusJonas hat folgendes geschrieben Zum zitierten Posting springen:
Leider wird die Abfrage nach dem "OR" nicht ausgeführt, da die Abfrage vor dem "OR" wohl true ist.

Ich möchte also eine Abfrage, die beide Bedingungen abprüft und nur wenn beide wahr sind, soll er weitermachen. So wie es mir scheint überprüft er jedoch nur alles vor dem OR und lässt die zweite Abfrage außer Acht.

Äh, das ist doch genau der Sinn von or!? Wenn beide Ausdrücke wahr sein müssen, brauchst du and.

user profile iconGTA-Place: Ich denke mal nicht, dass user profile iconJustusJonas Delphi noch einen Vergleich zweier Variablen ausführen lassen will, der dann aber verworfen wird ;)

Ich hoffe mal, ich habe nichts falsch verstanden.

Grüße,
Yogu


Delete - Di 03.02.09 20:19
Titel: Re: If-Anfrage: OR greift nicht
user profile iconJustusJonas hat folgendes geschrieben Zum zitierten Posting springen:
Ich möchte also eine Abfrage, die beide Bedingungen abprüft und nur wenn beide wahr sind, soll er weitermachen.

Dann wäre AND aber angebrachter, oder?


Maweki - Di 03.02.09 20:19

Das passiert uebrigens auch bei AND, wenn der erste Teil der direktive False ist.

Der "Fachbegriff" ist "full boolean evaluation".


delfiphan - Di 03.02.09 20:34

Ich denke nicht, dass user profile iconJustusJonas auf der Suche nach {$B+} ist ;) Ich glaube er hat den Unterschied zwischen OR und AND noch nicht ganz verstanden.


JustusJonas - Mi 04.02.09 16:59

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Ich denke nicht, dass user profile iconJustusJonas auf der Suche nach {$B+} ist ;) Ich glaube er hat den Unterschied zwischen OR und AND noch nicht ganz verstanden.


Sorry, dass ich mich jetzt länger nicht gemeldet habe.
Ich hatte mich wohl leider wirklich falsch ausgedrückt. Die Anweisung soll natürlich nicht nur weitermachen, wenn beide Bedingungen erfüllt sind, sondern eine der beiden.

Im Grunde sind es ja quasi drei Bedingungen. Er soll also weitermachen, wenn die erste UND die zweite ODER die dritte wahr sind.

Ich hoffe ihr versteht, wie ich das meine!?

Greetz


Delete - Mi 04.02.09 17:04

Dann musst Du nur die OR-Bedingungen zusätzlich klammern.

Delphi-Quelltext
1:
if ((DayOfNow(Date) < 3and ((Datum >= LastDayOfMonth2(Datum) -3)) or (Datum > (Date -3))) then                    


JustusJonas - Mi 04.02.09 17:08

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:
Dann musst Du nur die OR-Bedingungen zusätzlich klammern.

Delphi-Quelltext
1:
if ((DayOfNow(Date) < 3and ((Datum >= LastDayOfMonth2(Datum) -3)) or (Datum > (Date -3))) then                    


Aber das würde ja bedeuten, dass erweitermacht, wenn die erste Bedignung UND die zweite ODER dritte wahr sind.

Ich möchte aber, dass er nur weitermacht, wenn die ersten beiden ODER die dritte wahr sind.

Greetz


Gausi - Mi 04.02.09 17:10

Machen denn die einzelnen Datums-Routinen wirklich das, was du von ihnen erwartest? Lass dir mal die Ergebnisse der einzelnen Tests ausgeben - vielleicht läuft da ja schonwas verkehrt.


Jakob_Ullmann - Mi 04.02.09 17:10

Mit ODER sollte man auch vorsichtig sein. Bist du sicher, dass du ODER (= und/oder) meinst? Oder vielleicht eher ENTWEDER ODER (--> xor)


Delete - Mi 04.02.09 17:10

Dann setz die Klammern um die AND-Bedingungen.

[edit] Wobei das eigentlich überflüssig sein sollte, da AND eine stärkere Bindung als OR hat. Evtl. stimmt einfach Deine Logik nicht? [/edit]


GTA-Place - Mi 04.02.09 17:12

Hab ich also doch alles richtig verstanden :cool: Haste mal {B+} probiert?

@DeddyH: Hat er doch schon von Anfang an.


Delete - Mi 04.02.09 17:21

Siehe mein Edit.


JustusJonas - Mi 04.02.09 17:27

Auch mit dem {B+} komme ich irgendwie nicht weiter.

Es kann natürlich wirklich sein, dass ich einen Logikfehler drin habe und es gar nicht unbedingt daran liegt... :(

Ich erklär euch jetzt einfach mal, was ich genau machen möchte und hoffe dies gelingt mir (ansatzweise).

Ich habe ein Edit-Feld, in dem ein Datum steht. Je nach Datum wird eine bestimmte Datei eingelesen. Man darf jedoch nicht mehr als zwei Tage zurückblättern. Die ganze Zeit funktionierte das auch und es funktioniert auch jetzt wieder, aber am 02. Februar gab es damit Probleme.

Ich habe meine Systemzeit jetzt gerade auf den zweiten Februar umgestellt, damit ich testen kann. Ich lass meine Variablen jetzt einfach vor der IF-Anweisung mal in ein Memo laufen, evtl. kann mir jemand von euch dann weiterhelfen. Ich komme nämlich einfach nicht drauf, was da schief läuft...


Delphi-Quelltext
1:
2:
3:
4:
5:
Memo1.Lines.Add('DayOfNow(Date): ' + IntToStr(DayOfNow(Date)));
Memo1.Lines.Add('Datum: ' + DateToStr(Datum));
Memo1.Lines.Add('LastDayOfMonth2(Datum) -3): ' + DateToStr(LastDayOfMonth2(Datum) -3));
Memo1.Lines.Add('Date: ' + DateToStr(Date -3));
Memo1.Lines.Add('----------------');




Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
DayOfNow(Date): 2
Datum: 01.02.2009
LastDayOfMonth2(Datum) -3): 25.02.2009
Date: 30.01.2009
----------------
DayOfNow(Date): 2
Datum: 31.01.2009
LastDayOfMonth2(Datum) -3): 28.01.2009
Date: 30.01.2009
----------------
DayOfNow(Date): 2
Datum: 30.01.2009
LastDayOfMonth2(Datum) -3): 28.01.2009
Date: 30.01.2009
----------------
DayOfNow(Date): 2
Datum: 29.01.2009
LastDayOfMonth2(Datum) -3): 28.01.2009
Date: 30.01.2009
----------------
DayOfNow(Date): 2
Datum: 28.01.2009
LastDayOfMonth2(Datum) -3): 28.01.2009
Date: 30.01.2009
----------------
DayOfNow(Date): 2
Datum: 27.01.2009
LastDayOfMonth2(Datum) -3): 28.01.2009
Date: 30.01.2009
----------------


Wenn ich auf den 27. zurückblättern möchte, bekomme ich dann endlich die Meldung, dass ich nicht weiter zurückblättern darf.

Ihr könnt euch gar nicht vorstellen, wie dankbar ich euch für eure Hilfe bin!!!

Greetz


GTA-Place - Mi 04.02.09 17:41

Da ist ein Denkfehler drin: Du ziehst vom letzten Tag des Monats immer 3 Tage ab, egal welcher Tag heute ist. Reicht denn nicht folgendes?


Delphi-Quelltext
1:
if (Datum >= Date - 2then                    

In deiner komplizierten Fassung müsste das so stimmen:


Delphi-Quelltext
1:
if ((DayOfNow(Date) < 3and (Datum >= LastDayOfMonth2(Datum) - (2 - DayOfNow(Date)))) or (Datum > (Date -3)) then                    


Delete - Mi 04.02.09 17:44

Deine Vorgehensweise erscheint mir ein bisschen kompliziert.

Delphi-Quelltext
1:
2:
3:
4:
5:
var Datum, heute: TDate;
begin
  Datum := trunc(StrToDate(Edit.Text));
  heute := trunc(date);
  if (Datum > heute) or (heute - Datum > 2then

Getippt und nicht getestet.

[edit] Andere Möglichkeit:if not ((heute - Datum) in [0..2]) then[/edit]


GTA-Place - Mi 04.02.09 17:51

Oder, wie gerade gesagt und noch einfacher (getestet):


Delphi-Quelltext
1:
if (Datum >= Date - 2then                    

Das hat JustusJonas schon im 1. Post hier erwähnt gehabt, ich weiß nur nicht, warum er es nicht nimmt :gruebel:.


Delete - Mi 04.02.09 17:53

Vielleicht, weil das nicht ausreicht? Was ist, wenn das Datum in der Zukunft liegt? :zwinker:


GTA-Place - Mi 04.02.09 17:55

Nagut, überzeugt:


Delphi-Quelltext
1:
if Abs(Date - Datum) <= 2 then                    

oder:


Delphi-Quelltext
1:
if DaysBetween(Datum, Date) <= 2 then                    

8)


Delete - Mi 04.02.09 17:58

Da hast Du immer noch das Problem mit Zukunftsdaten. Wieso abs?


JustusJonas - Mi 04.02.09 18:00

user profile iconGTA-Place hat folgendes geschrieben Zum zitierten Posting springen:
Oder, wie gerade gesagt und noch einfacher (getestet):


Delphi-Quelltext
1:
if (Datum >= Date - 2then                    

Das hat JustusJonas schon im 1. Post hier erwähnt gehabt, ich weiß nur nicht, warum er es nicht nimmt :gruebel:.


Oh man, es ist schon ziemlich lange her, dass ich dieses Programm geschrieben hatte. Wenns dann nach zig Monaten (oder sogar schon Jahren) dann wieder Änderungen gibt, bin ich immer ein wenig aufgeschmissen.

Die andere Abfrage hatte ich damals reingemacht, weil man nicht über Jahre hinweg darf, also am 01.01. darf man nicht zurück auf den 31.12.
Deshalb die Abfrage, ob die aktuelle Tageszahl größer als drei ist...

Ihr seid echt genial, ganz ehrlich! Vielen Dank bis dato schon mal!

Greetz


jaenicke - Mi 04.02.09 18:03

Dafür reicht doch der Vergleich ob YearOf (in Unit DateUtils) gleich ist. ;-)
Also DaysBetween <= 2 und YearOf identisch sollte reichen.


GTA-Place - Mi 04.02.09 18:06

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:
Da hast Du immer noch das Problem mit Zukunftsdaten. Wieso abs?


:gruebel:


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:
var
  Datum1, Datum2, Heute: TDate;
begin
  Heute  := Date;

  Datum1 := StrToDate('28.02.2009');
  Datum2 := StrToDate('15.01.2009');

  if Abs(Heute - Datum1) > 2 then
    ShowMessage('Ohjemine...');         // erscheint

  if Abs(Heute - Datum2) > 2 then
    ShowMessage('Ohjemine...');         // erscheint

  Datum1 := StrToDate('03.02.2009');    // -1 Tag
  Datum2 := StrToDate('05.02.2009');    // +1 Tag

  if Abs(Heute - Datum1) > 2 then
    ShowMessage('Ohjemine...');         // erscheint nicht

  if Abs(Heute - Datum2) > 2 then
    ShowMessage('Ohjemine...');         // erscheint nicht
end;

Funktioniert alles sehr gut :gruebel:


Delete - Mi 04.02.09 18:10

Meinst Du nicht, dass es ein Fehler sein sollte, in das Edit ein Datum in der Zukunft einzutragen?


GTA-Place - Mi 04.02.09 18:11

Achso, na das kommt auf den Verwendungszweck drauf an ;-)


JustusJonas - Do 05.02.09 01:15

Danke jaenicke, ich glaube das ist genau das, was ich gesucht habe. Werde ich Morgen auf jeden Fall direkt ausprobieren!

Vielen Dank an euch alle! Ich melde mich Morgen wieder!!

Greetz


JustusJonas - Fr 06.02.09 13:07

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Dafür reicht doch der Vergleich ob YearOf (in Unit DateUtils) gleich ist. ;-)
Also DaysBetween <= 2 und YearOf identisch sollte reichen.


Kann es sein, dass die Unit DateUtils erst in einer späteren Delphi-Version dabei ist?

Bei meiner Delphi 5 sagt er jedenfalls, dass er die DateUtils.dcu nicht finden kann... :(

Greetz


Delete - Fr 06.02.09 14:07

Richtig, DateUtils gibt es erst ab Delphi 7 (soweit ich weiß).


jaenicke - Fr 06.02.09 14:26

Eine Unit mit den Funktionen gibt es auch als JclDateUtils in der JEDI Code Library. ;-)


JustusJonas - Fr 06.02.09 14:44

Evtl. kann mir ja jemand mit Delphi 7 die Funktionen hier posten? Dann kann ich sie in meinem Programm ja einfach so verwenden.

Greetz


Delete - Fr 06.02.09 15:26

Ich glaube nicht, dass das erlaubt ist.


jaenicke - Fr 06.02.09 15:31

user profile iconJustusJonas hat folgendes geschrieben Zum zitierten Posting springen:
Evtl. kann mir ja jemand mit Delphi 7 die Funktionen hier posten? Dann kann ich sie in meinem Programm ja einfach so verwenden.
Was hat das für einen Sinn? Ich sagte doch wo du sie bekommst, und das geht dann auch unter Delphi 5. Mit einer Unit von Delphi 7 hast du vermutlich auch noch Inkompatibilitäten. :gruebel:
http://sourceforge.net/projects/jcl/

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:
Ich glaube nicht, dass das erlaubt ist.
Das außerdem was die Originalunit von Delphi 7 angeht.
Der Quelltext war ja nicht einmal bei allen Versionen von Delphi überhaupt dabei.


Delete - Fr 06.02.09 15:41

Ich habe gerade einen Blick in den Code geworfen. YearOf ist ein Einzeiler, in dem DecodeDate verwendet wird, lässt sich also leicht nachproggen.