While Schleife

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Daniel_Berlin
Beiträge: 37
Registriert: So 31. Mai 2020, 21:13

While Schleife

Beitrag von Daniel_Berlin »

Hallo,

ich habe eine Schleife gebaut, die erste IF ELSE Bedingung in der Schleife wird auch erfolgreich durchgeführt, aber das Programm friert ein. Programm läuft auf 30 % CPU
ich geh mal davon aus, dass meine Abbruchbedingung nicht greift: die schleife soll von einem Preis x hochgehen bis <= stringPrice oder bis stringPrüfpunkt auf 1 (also bei 1 soll die Schleife nicht mehr durchgeführt werden). Ich habe das Programm mit verschiedenen Werten getestet und irgendwie hatte ich das gefühl, dass variablePrice := variablePrice + '2';
nicht hochzählt. Das würde aber im Widerspruch stehen mit meinen vorherigen Sätzen.
müssen noch zwei IF Else Bedingungen eingebaut werden,.
Wenn keine der drei Bedingungen greifen, dann soll der stringPrüfpunkt auf 1 (zur Begin ist der Wert 0) gesetzt werden. Vorher soll die Schleife alle variablePrice durchlaufen (wird immer aus der DB geholt).
Könnt ihr mal bitte rüberschauen??


unten ist der verbesserte Code.
Zuletzt geändert von Daniel_Berlin am Do 11. Jun 2020, 17:18, insgesamt 5-mal geändert.

Daniel_Berlin
Beiträge: 37
Registriert: So 31. Mai 2020, 21:13

Re: While Schleife

Beitrag von Daniel_Berlin »

Noch eine Anmerkung:

Wenn die erste Bedingung auf <= setze und einen höheren wert für stringPrice einsetze als variablePrice , dann wird die IF Else bedingung nicht durchgeführt. Das ist ja aber eigentlich falsch wenn ich <= einsetze.

IF ((variablePrice <= stringPrice) AND (p = '0') AND (stringNachname = tabelle2Nachname) AND (stringName= variableNachname))
THEN
BEGIN
Form2.SQLQuery1.SQL.Text := 'INSERT INTO tabelle3 (....) values (...)
P:= '1';
Form2.closeDB;
END

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: While Schleife

Beitrag von MacWomble »

Kann es sein, dass du versuchst mit string zu rechnen?

var
variableprice: real;

variableprice := Form2.SQLQuery1.FieldByName('price').AsFloat;

OffTopic:
Generell würde ich die DB-Zugriffe und die Übergab der DB-Werte über eine Klasse (je Tabelle) definieren.
Dann brauchst du im Programm nur noch mit den Objekten hantieren und machst dir das Leben einfacher.
Die Änderungsprüfung etc. kann dann auch deutlich vereinfacht werden und taucht nicht in der Programmlogik auf.

Dein

Code: Alles auswählen

IF ((variablePrice <= stringPrice) AND (p = '0') AND (stringNachname = tabelle2Nachname) AND (stringName= variableNachname))
THEN
BEGIN
Form2.SQLQuery1.SQL.Text := 'INSERT INTO tabelle3 (....) values (...)
P:= '1';
Form2.closeDB;
END
könnte dann z.B. so aussehen:

Code: Alles auswählen

Table3.WriteData;
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Daniel_Berlin
Beiträge: 37
Registriert: So 31. Mai 2020, 21:13

Re: While Schleife

Beitrag von Daniel_Berlin »

Ich bin jetzt schon etwas weitergekommen.
Ich rechne jetzt mit double. Irgendwie ist das Programm in einer Endlosschleife, da das Programm einfriert und der Prozess bei 30% liegt. Die Bedingungen in den IF Else habe ich erfolgreich durchgetestet. Das Verhalten in der IF Elese wird durchgeführt, wenn die Bedingungen stimmen. Jedoch nicht bei einen etwas höheren Preis. Aber da würde es theoretisch auch greifen, da der niedriste Preis ( unter stringCheck = '1') hat und ich das ja ausschließe mit (stringCheck = '0'). Also irgendwie geht zählt die Schleife ggf nicht hoch?!

Zudem habe ich festgestellt, dass ich nicht den richtigen Rückgabewert bekomme. ich bekomme nicht den niedrigsten Preis zurück. Hab das in mysql getestet.
SELECT * FROM sell WHERE price= (SELECT min(price) FROM sell);


Die Berechnung in der IF ELSE liefert irgendwie 0 zurück obwohl es mehr sein müssen.
floatTempVolume := floatBuyVolume - floatSellVolume;



Anbei der verbesserte Code:

Code: Alles auswählen

procedure TForm3.ButtonStartClick(Sender: TObject);                  
var
 
start : TDateTime;
stringCheck :string;
stringBuyPrice : string;
stringBuyVolume :: string;
buy_id : string;
 
sold : string;
 
sell_id : string;
name : string;
 
SellPrice : string;
floatBuyPrice : double;
floatSellPrice : double;
 
//for the calculation of the restvolume
floatBuyVolume : double;
floatSellVolume: double;
floatTempVolume : double;
stringTempVolume : string;  
sellVolume : string;
 
 
begin  
stringCheck := '0';
buy_id := EditBuy_ID.Text;
stringBuyPrice := Edit2_ID.Text;
stringBuyVolume := Edit3_ID.Text;
 
// here is an insert which enters every value for buy data
 
// now i am looking for the lowest sell price
   Form2.SQLQuery3.SQL.Text := 'SELECT price, start FROM sell WHERE price =  (SELECT min(price) FROM sell)';
   Form2.SQLQuery3.Open;
 
        SellPrice := Form2.SQLQuery3.FieldByName('price').AsString;
        floatSellPrice :=StrToFloat(SellPrice);
        floatBuyPrice := StrToFloat(stringBuyPrice);
 
        floatBuyVolume:= StrToFloat(stringBuyVolume);
 
 
 //   Start := Form2.SQLQuery1.FieldByName('start').AsString;
 
     // as long as Sell Price reaches Buy Price, can be the same
     
    While ((floatSellPrice <= floatBuyPrice ) OR (stringCheck < '1'))
     DO
      BEGIN
        // I collect the data which belongs to the lowest price, i have to do this every loop again, because the price is getting higher 0.1 after every loop
     Form2.SQLQuery1.SQL.Text := 'SELECT * from sell WHERE price ='''+SellPrice+''';';
     Form2.SQLQuery1.Open;
 
     SellPrice := Form2.SQLQuery1.FieldByName('price').AsString;
     floatSellPrice :=StrToFloat(SellPrice);
 
     sell_id := Form2.SQLQuery1.FieldByName('id').AsString;
     name := Form2.SQLQuery1.FieldByName('name').AsString;
     sellVolume := Form2.SQLQuery1.FieldByName('volume').AsString;
     floatSellVolume:= StrToFloat(sellVolume);
 
     sold := Form2.SQLQuery1.FieldByName('sold').AsString;
 
 
 
     // Buyprice is higher or the same than sell price and buy volume is higher than sell volume; sold a checkpoint for the sells, it has to be unequal 1
        IF ((floatSellPrice <= floatBuyPrice) AND (stringCheck = '0') AND (floatBuyVolume > floatSellVolume) (sold <>1))
        THEN
        BEGIN
        floatTempVolume := floatBuyVolume - floatSellVolume;
        stringTempVolume  :=FloatToStr(floatTempVolume);
        Form2.SQLQuery1.SQL.Text := 'INSERT INTO table 2 (id, price,volume) VALUE ('''+sell_id+''','''+name+''','''+stringTempVolume+''');';
        Form2.SQLQuery2.SQL.Text := 'Update buy SET check = "1", date = current_timestamp WHERE buy_id ='''+buy_ID+''';';
        Form2.SQLQuery3.SQL.Text := 'Update sell SET sold ="1", date = current_timestamp  WHERE  id = '''+sell_id+''';';
        stringCheck:= '1';
        Form2.SQLQuery1.ExecSQL;
        Form2.SQLQuery2.ExecSQL;
        Form2.SQLQuery3.ExecSQL;
        Form2.SQLTransaction1.Commit;
        END
 
 
   ELSE
   BEGIN
   floatSellPrice := floatSellPrice + 0.1;  
   SellPrice:=FloatToStr(floatSellPrice)
   END
 
       
 end;
 Form2.SQLQuery2.SQL.Text := 'Update buy SET check = "1" WHERE buy_id ='''buy_id+''';';
 stringCheck:= '1';
 Form2.SQLQuery2.ExecSQL;
 Form2.SQLTransaction1.Commit;
 Form2.SQLQuery1.Close;
 Form2.SQLQuery2.Close;
 Form2.SQLQuery3.Close;
 
   end
 end;

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: While Schleife

Beitrag von MacWomble »

Vermutlich macht das Programm genau das, was du ihm sagst. ;-)

Versuche doch generell KEIN string für die Preis-Variablen zu verwenden!
Wie sind eigentlich die Preis-Felder in der Datenbank definiert?
Des weiteren: wie ist die Datenbank kodiert? Passt dies zur Einstellung in deinem Programm (Dezimalkomma etc)?

Mir erschließt sich nicht wirklich, was du da machen möchtest.
Wäre das nicht auch mit SQL ohne Programm schon möglich ...
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Daniel_Berlin
Beiträge: 37
Registriert: So 31. Mai 2020, 21:13

Re: While Schleife

Beitrag von Daniel_Berlin »

in der DB und in meinem programm sind die Preise jetzt double.
Zuletzt geändert von Daniel_Berlin am Sa 13. Jun 2020, 17:49, insgesamt 1-mal geändert.

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: While Schleife

Beitrag von h-elsner »

In deinem Codebeispiel oben ist irgendwie ein 'end' zuviel drin. Ich verstehe nicht, wie das kompliliert werden kann. Wenn doch fehlt in einer anderen prozedur ein 'end' und die ganze Funktionalität wird kaputt gemacht.
Für StringCheck würde ich eine boolean Variable nehmen und nicht einen string. Das aber nur am Rande.

Am Ende wird StringCheck auf '1' gesetzt. Wozu? Es kann nie wieder benutzt werden, weil es eine lokale Variable ist. Wenn du den Zustand irgendwie weiter verwenden willst, geht das nicht.

Gruß HE

Daniel_Berlin
Beiträge: 37
Registriert: So 31. Mai 2020, 21:13

Re: While Schleife

Beitrag von Daniel_Berlin »

stringCheck will ich nicht weiterverwenden, das war nur als zweite Abbruchbedingung gedacht, aber an dieser eigentlich nicht mehr notwendig, da stringCHeck erst nach Ende der Schleife, wenn keine IF Else greifen auf 1 gesetzt wird.

Linkat
Lazarusforum e. V.
Beiträge: 530
Registriert: So 10. Sep 2006, 23:24
OS, Lazarus, FPC: Linux Mint 21.3; Lazarus 3.0 FPC 3.2.2; RaspiOS
CPU-Target: AMD 64, ARM 32
Wohnort: nr Stuttgart

Re: While Schleife

Beitrag von Linkat »

Mich beisst der doppelte Doppelpunkt:

Code: Alles auswählen

stringBuyVolume :: string;
Linux Mint 21; Lazarus 2.2.4 FPC 3.2.2; RaspiOS

shokwave
Beiträge: 470
Registriert: Do 15. Nov 2007, 16:58
OS, Lazarus, FPC: Win11/Ubuntu Budgie (L 3.0 FPC 3.2.2)
CPU-Target: i386, x64
Wohnort: Gera

Re: While Schleife

Beitrag von shokwave »

Hi,

wenn ich das richtig sehe, sind in dem Codbeispiel sogar 3 end zu viel. Bei einigen fehlt ein ";". Um so etwas zu finden empfiehlt es sich, sich strickt an die korrekte Einrückung zu halten. Nicht böse gemeint, sondern als Tipp.

Und statt der 3 Hochkommas würde ich QuotedStr() benutzen.

Code: Alles auswählen

Form2.SQLQuery2.SQL.Text := 'Update buy SET check = "1" WHERE buy_id =' + QuotedStr(buy_id) + ';';  
In der While-Schleife müssten die Bedingungen mit and statt or verbunden werden oder denke ich gerade falsch? Aber die 2.Bedingung wolltest du ja eh rausnehmen...
mfg Ingo

Antworten