Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Taschenrechner mit Zwischenergebnis programmieren (https://www.delphipraxis.net/23923-taschenrechner-mit-zwischenergebnis-programmieren.html)

Wuaegner 12. Jun 2004 08:55


Taschenrechner mit Zwischenergebnis programmieren
 
Servus ! Hab mir vorgenommen einen TR zu programmieren, als Vorbild den Windwos TR. Habe einen Stack erstellet auf den ich mit Pop Push usw zugreifen kann. Einen Num Stack für die Zahlen und einen Operatorstack. Habe in einer Hirarchie festgelegt welcher Operator am stärksten bindet , am zweistärksten usw. 0 bekommen die stärksten mit auf den Stack , 1 die zweitstärksten usw. So wollte ich dann vergleichen ob das Object von der Operatorzahl auf dem Stack höhe rist als das neue usw, um Punkt- vor- Strich-Rechnung zu realisieren. Habe aber ein Problem: wenn man 1+ eingibt und dann wieder eine Zahl, dann wird das Editfeld gelöscht und die neue Zahl steht da, alles richtig, solange bis er das erste Zwischenregebnis anzeigt, dann muss man jedoch zweimal auf den Plus button klicken damit er mit dem Zwischenregebnis weiterrechnet. Bei einem Klick bleibt es stehen und es passiert nichts. Hier mal der Code:
Code:
procedure TForm1.EAusgabeKeyPress(Sender: TObject; var Key: Char);
var
  OpPosition: integer;
  OpAltPosition: integer;
  Zahl,ZahlAlt: extended;
 
  OpAlt : String;
begin
   inc(anz);

   if (Op <> '') and (anz = 1) then
      EAusgabe.Text := '';

   if Key in [',','0','1','2','3','4','5','6','7','8','9'] then exit;

   if OpPos(Key,OpPosition)= true then       {Wenn key ein Operator ist}
     begin
     Label1.Caption:= Key;
     Zahl:= StrToFloat(EAusgabe.Text);

       if OpStack.IsEmpty= false then
             begin
               OpStack.PopObject(TObject(OpAltPosition));
               if OpAltPosition <= OpPosition then
                   begin
                   ZahlAlt:= StrToFloat(NumStack.Pop);
                   OpAlt:= OpStack.Pop;
                   case OpAlt[1] of
                    '+':
                      begin
                       ZahlAlt:= ZahlAlt + Zahl;
                       EAusgabe.Text:= FloatToStr(ZahlAlt);
                       NumStack.Push(FloatToStr(ZahlAlt));

                       Anz:= 0;
                      end;
                    '-':
                      begin
                      ZahlAlt:= ZahlAlt - Zahl;
                      EAusgabe.Text:= FloatToStr(ZahlAlt);
                      NumStack.Push(FloatToStr(ZahlAlt));

                      Anz:= 0;
                      end;

                   end;

                  end;
               end
                else
                  begin
                   Op := Key;
                   Anz:= 0;
                   OpStack.Push(key);
                   OpStack.PushObject(key,TObject(OpPosition));
                   NumStack.Push(FloatToStr(Zahl));
                   exit;

                  end;

    end;

  Key:= #0;
end;
Vielleicht sieht jemand wo mein Fehler liegt.
Gruß Flo

Wuaegner 13. Jun 2004 11:02

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Kann mir da niemand weiterhelfen?

MrKnogge 13. Jun 2004 11:39

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Servus !

Was sind OpStack und NumStack für Typen ?

Wuaegner 13. Jun 2004 13:42

Re: Taschenrechner mit Zwischenergebnis programmieren
 
OpStack und NumStack sind vom Typ Stringlist.
Gruß Flo

Wuaegner 14. Jun 2004 18:59

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Isses zu wenig Code oder hat niemand ne Idee?
Gruß Flo

Nicodius 14. Jun 2004 19:44

Re: Taschenrechner mit Zwischenergebnis programmieren
 
warum exit wenn key zahlen etc sind?

Wuaegner 14. Jun 2004 21:29

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Weil nur bei Eingabe eines Operators eine Aktion durchgeführt werden soll. Bei Eingabe einer Zahl soll sie lediglich zur Zeichenkette im Eingabefeld hinzugefügt werden.
Gruß Flo

MrSpock 15. Jun 2004 20:47

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo Flo,

auf den ersten Blick glaube ich, dass es an folgendem liegt:

im else-Fall (wenn also der Stack am Anfang leer ist), schreibst du Key zweimal auf den Stack!


Delphi-Quellcode:
Anz:= 0;
       OpStack.Push(key);
       OpStack.PushObject(key,TObject(OpPosition))
Push(Key) schreibt den Operator auf den Stack.
Anschließend schreibt PushObject noch einmal Key auf den Stack und merkt sich zusätzlich die Stufe des Operators.
Damit steht aber der Operator zweimal auf dem Stack. Lösche einmal den ersten Push Call. Wenn es dann noch nicht funktioniert, guck ich mir den Rest auch noch an.

Übrigens gefällt mir der Code schon ganz gut! :zwinker:

Wuaegner 16. Jun 2004 13:37

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hi MrSpock,
Wenn ich die Zeile lösche, kommt nun die exception 'Stack is empty', woran das liegt finde ich aber noch raus.
Danke für die schnelle Antwort.
Gruß Flo

MrSpock 16. Jun 2004 20:11

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo Flo,

das liegt daran, dass du in dem anderen Teil der if Anweisung auch zweimla pop aufrufst. Pop löscht ja das obere Element vom Stack. Ich hatte deshalb damals neben pop und popObjects ja auch noch die Funktionen:

Delphi-Quellcode:
function ShowTop: String;
     function ShowTopObject(var obj: TObject): String;
implementiert, die wie Pop arbeiten, aber ohne das Element zu löschen! Damit kannst du das obere Element prüfen.

Wuaegner 16. Jun 2004 20:28

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hi MrSpock!
Ah gut das werd ich gleich ändern. Gab noch einen Fehler... habe ihn gerade gefunden jetzt geht es ohne Probleme. Versuche jetzt mal Mal- und Bruchrechnen einzubauen.

Grüße Flo

Wuaegner 17. Jun 2004 19:22

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Da ich nun wieder weitermachen kann mit meinem TR werde ich dieses Thema nun schließen.
Gruß Flo

Wuaegner 23. Jun 2004 11:03

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Servus! Hab jetzt mal Multiplikation und Division eingeführt bei meinem TR , auch die Punkt-Vor-Strich-Regel , jedoch weiß ich nicht wie ich es anstelle, dass nachdem er die MalRechnung ausgeführt hat den restlichen Stack auch noch abarbeitet.
Delphi-Quellcode:
procedure TForm1.EAusgabeKeyPress(Sender: TObject; var Key: Char);
var
  OpPosition: integer;
  OpAltPosition: integer;
  Zahl,ZahlAlt: extended;
  OpAlt : String;

begin
   inc(anz);
   if (Op <> '') and (anz = 1) then
      EAusgabe.Text := '';

  if Key in [',','0','1','2','3','4','5','6','7','8','9'] then exit;

   if OpPos(Key,OpPosition)= true then       {Wenn key ein Operator ist}
     begin
     Label1.Caption:= Key;
     Zahl:= StrToFloat(EAusgabe.Text);

       if OpStack.IsEmpty= false then
             begin
               Opstack.ShowTopObject(TObject(OpAltPosition));

               if OpAltPosition <= OpPosition then
                    begin

                    ZahlAlt:= StrToFloat(NumStack.Pop);
                    OpAlt:= OpStack.ShowTopObject(TObject(OpAltPosition));

                       case OpAlt[1] of
                        '=','+':
                           begin
                           Zahl:= ZahlAlt + Zahl;
                           EAusgabe.Text:= FloatToStr(Zahl);
                           NumStack.Push(FloatToStr(Zahl));
                           OpStack.PushObject(key,TObject(2)); {+ hat Stärke 2}
                           Anz:= 0;
                           end;
                        '-':
                           begin
                           Zahl:= ZahlAlt - Zahl;
                           EAusgabe.Text:= FloatToStr(Zahl);
                           NumStack.Push(FloatToStr(Zahl));
                           OpStack.PushObject(key,TObject(2)); {- hat Stärke 2}
                           Anz:= 0;
                           end;
                        '*':
                           begin
                           Zahl:= ZahlAlt * Zahl;
                           EAusgabe.Text:= FloatToStr(Zahl);
                           NumStack.Push(FloatToStr(Zahl));
                           OpStack.PushObject(key,TObject(1));  {* hat Stärke 1}
                           Anz:= 0;
                           end;
                        '/':
                           begin
                           Zahl:= ZahlAlt / Zahl;
                           EAusgabe.Text:= FloatToStr(Zahl);
                           NumStack.Push(FloatToStr(Zahl));
                           OpStack.PushObject(key,TObject(1));  {/ hat Stärke 1}
                           Anz:= 0;
                           end;
                      end;

                 end

                   else If OpAltPosition > OpPosition then
                              begin
                              NumStack.Push(FloatToStr(Zahl));
                              OpStack.PushObject(key,TObject(OpPosition));
                              Anz:= 0;
                              exit;
                              end;


               end
                else {if IsEmpty = true}
                  begin
                   Op := Key;
                   Anz:= 0;
                   OpStack.PushObject(key,TObject(OpPosition));
                   NumStack.Push(FloatToStr(Zahl));
                   exit;
                  end;
   end;
   Key:= #0;
end;
Wäre sehr dankbar wenn mir jemand weiterhelfen kann!
Grüße Flo

MrSpock 23. Jun 2004 11:35

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo Flo,

der Taschenrechner darf ja den Rest des Stack gar nicht abarbeiten! Nur bei einer schließenden Klammer muss er den Stack abräumen, bis zur dazugehörigen öffnenden Klammer (die existieren muss!) oder bei einem Gleichheitszeichen, dann muss er den Stack komplett räumen, darf aber nicht mehr auf eine öffnende Klammer stoßen, sonst müsste es einen Fehler geben.

Wuaegner 23. Jun 2004 12:23

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo MrSpock,
Aber ich möchte ja, dass immer das Zwischenergebnis angezeigt wird. Wenn man nun eingibt:
2 + 3 * 4 + 4 dann soll er ja erst 3*4 rechnen und danach noch die 2 addieren und dann erst weiterrechnen. MIt "abarbeiten" meinte ich dass er in dem Fall dann die 2 noch addiert nach der Multiplikation. WIe stelle ich das am besten an? Bis jetzt rechnet er ja 3*4 und danach mit diesem Ergebnis, 12 weiter. Die 2 addiert er noch nicht.
Gruß Flo

MrSpock 24. Jun 2004 21:13

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo Flo,

du musst tatsächlich, wenn du einen Operator findest, der schwächer bindet, als der oberste auf dem Stack, diesen und alle weiteren (in einer Schleife) vom Stack abarbeiten, bis du auf einen Operator triffst, der wieder schwächer bindet.

Beispiel:

3+4*5^2* ergibt auf dem
NumStack:3 4 5 6
OpStack: + * ^
AktOp: *

* bindet schwächer als ^, also alte Operation ausführen und Zwischergebnis zurück auf den Stack.

NumStack 3 4 25
OpStack: + *

Der obere Operator bindet nicht schwächer als der aktuelle und kann auch noch abgearbeitet werden:

Num Stack 3 100
OpStack: +

Der obere Operator (+) bindet jetzt aber schwächer als der aktuelle * und darf noch nicht abgearbeitet werden.

Wuaegner 28. Jun 2004 09:15

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo MrSpock,
Genau nur wie mache ich diese Schleife? sie muss ja die fast die ganze keypressed- prozedur enthalten. Wie ich dieses Schleife geschickte erstelle ohne viel doppelten code zu haben.
Grüße FLo

MrSpock 18. Jul 2004 19:39

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo Flo,

zeig doch einmal deinen Versuch, die Abfrage in einer Schleife darzustellen. Wie es prinzipiell läuft hab ich ja schon beschrieben. Die Stufe der Bindung des Operators holst du dir im Code bereits mit OpAltPosition. Anstatt nur den obersten Eintrag zu betrachten nimmst du eine while Schleife, die immer dann ausgeführt wird, wenn OpAltPosition <= OpPosition ist. Dann führst du den Code aus, den du schon programiiert hast. Am Ende der Schleife prüft du einfach mit ShowTopObject, ob der nun oben liegende Operator immer noch schwächer bindet (und hast damit den neuen Wert für OpAltPosition für die nächste Schleifenbedingung) und holst in diesem Fall mit PopObjekt wieder das oberste Element vom Stack.

Versuche das einmal und poste das Ergebnis, dann können wir dir weiterhelfen.

Wuaegner 3. Okt 2004 19:30

Re: Taschenrechner mit Zwischenergebnis programmieren
 
Um diesen Beitrag abzuschließen, der fertige und funktionierende Taschenrechner steht in der OpenSource Sparte. :)

Kudle 30. Mai 2012 16:39

AW: Taschenrechner mit Zwischenergebnis programmieren
 
Ich würde mir gerne mal den fertigen Taschenrechner ansehen.

Da ich neu hier bin, würde ich gerne wissen, was mit "Open Source Sparte" gemeint ist?

Gruß :-)

DeddyH 30. Mai 2012 16:42

AW: Taschenrechner mit Zwischenergebnis programmieren
 
Die alte OpenSource-Sparte ist mittlerweile in Software-Projekte der Mitglieder aufgegangen.

Kudle 30. Mai 2012 16:44

AW: Taschenrechner mit Zwischenergebnis programmieren
 
Zitat:

Zitat von DeddyH (Beitrag 1168767)
Die alte OpenSource-Sparte ist mittlerweile in Software-Projekte der Mitglieder aufgegangen.

Vielen Dank!! :-)

himitsu 30. Mai 2012 16:47

AW: Taschenrechner mit Zwischenergebnis programmieren
 
Und notfalls einfach die Forensuche befragen.

Womöglich "Taschenrechner" als Suchwort und dazu auch noch den gewünschten Benutzernamen angeben.

MrSpock 30. Mai 2012 18:43

AW: Taschenrechner mit Zwischenergebnis programmieren
 
Hallo Kudle,

hier ist Flo's Taschenrechner zu finden.


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