Taschenrechner Punkt vor Strich



  • Hallo,
    ich mache gerade ein Schulprojekt über den Ferien, indem ich einen Taschenrechner, in einer Windowsoberfläche(Forms), Programmieren soll.
    Es klappt alles Wunderbar. man Kann mehrere Zahlen zusammenrechnen usw.
    Mein Probelm ist, ich hab keine Ahnung wie ich Punkt vor Strichrechnung realiesieren soll.

    Hier ist der Code den ich benutzer.

    String^ ganzeZahl;		//Speicherung der Eingegebenen Zahl
    String^ Ausgabe;		//Ausgabe aller gewählten Sachen in dem Unteren Textfeld
    double summe;			//Speicherung des Endsumme/Zwischensumme		
    char Operator;			//Speicherung des Operators
    String^ Operand;		//Speicherung des Operators für die Ausgabe
    int anzahl;			//lückenhalter
    String^ zahl;			//wert des Buttons
    
    #pragma endregion
    
    //Button "1"
    private: System::Void btn_1_Click(System::Object^  sender, System::EventArgs^  e) 
    		 {
    				zahl="1";					//zuweisen vom wert 1
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		 }
    
    //Button "2"
    private: System::Void btn_2_Click(System::Object^  sender, System::EventArgs^  e) 
    		 {
    				zahl="2";					//zuweisen vom wert 2
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		 }
    
    //Button "3"
    private: System::Void btn_3_Click(System::Object^  sender, System::EventArgs^  e) 
    		 {
    				zahl="3";					//zuweisen vom wert 3
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		 }
    
    //Button "4"
    private: System::Void btn_4_Click(System::Object^  sender, System::EventArgs^  e) 
    		 {
    				zahl="4";					//zuweisen vom wert 4
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		 }
    
    //Button "5"
    private: System::Void btn_5_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				zahl="5";					//zuweisen vom wert 5
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		}
    
    //Button "6"
    private: System::Void btn_6_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				zahl="6";					//zuweisen vom wert 6
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		}
    
    //Button "7"
    private: System::Void btn_7_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				zahl="7";					//zuweisen vom wert 7
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		}
    
    //Button "8"
    private: System::Void btn_8_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				zahl="8";					//zuweisen vom wert 8
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		}
    
    //Button "9"
    private: System::Void btn_9_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				zahl="9";					//zuweisen vom wert 9
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		}
    
    //Button "0"
    private: System::Void btn_0_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				zahl="0";					//zuweisen vom wert 0
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		}
    
    //Button ","
    private: System::Void btn_punkt_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				zahl=",";					//zuweisen vom Zeichen ,
    				ganzeZahl +=  zahl;			//Zahl in ganzeZahl Speichern mit += String anhängen
    				Ausgabe += zahl;			//Zahl in Ausgabe Speichern mit += String anhängen
    				txb_ausgabe->Text=ganzeZahl;	//Ausgabe ins obere Textfeld
    				lbl_ausgabe->Text=Ausgabe;	//Ausgabe ins untere Textfeld
    		}
    
    //Button "+"
    private: System::Void btn_plus_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				Operator='+';					//setze Operator auf "+" im Char
    				Operand ="+";					//setze Operator auf "+" im String
    				zuweisen(Operator, Operand);	//Funktion Zuweisen aufrufen und beide Variablentypen übergeben
    		}
    
    //Button "-"
    private: System::Void btn_minus_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				Operator='-';					//setze Operator auf "-" im Char
    				Operand="-";					//setze Operator auf "-" im String
    				zuweisen(Operator, Operand);	//Funktion Zuweisen aufrufen und beide Variablentypen übergeben
    		}
    
    //Button "*"
    private: System::Void btn_mal_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				Operator='*';					//setze Operator auf "*" im Char
    				Operand="*";					//setze Operator auf "*" im String
    				zuweisen(Operator, Operand);	//Funktion Zuweisen aufrufen und beide Variablentypen übergeben
    		}
    
    //Button "/"
    private: System::Void btn_geteilt_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				Operator='/';					//setze Operator auf "/" im Char
    				Operand="/";					//setze Operator auf "/" im String
    				zuweisen(Operator, Operand);	//Funktion Zuweisen aufrufen und beide Variablentypen übergeben
    		}
    
    //Button "="
    private: System::Void btn_erg_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				rechnen(Operator);					//Funktion rechnen aufrufen und Operator als Char übergeben
    				ganzeZahl="";							//ganzeZahl auf leer setzen für die nächste eingabe
    				anzahl=3;								//auf 3 setzen um überschreiben der Summe zu verhindfern beim nächsten Operator druck
    				Ausgabe += " = "+summe;					//in Ausgabe den Wert der Summe Speichern
    				txb_ausgabe->Text=Convert::ToString(summe);	//im oberen Textfeld die Summe Ausgeben
    				lbl_ausgabe->Text=Ausgabe;				//Im unteren Textfeld die Rechnung ausgeben
    		}
    
    //Button "C"
    private: System::Void btn_clear_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				//beim Klicken auf den C Button alles auf leer oder 0 setzen
    				ganzeZahl="";	
    				Ausgabe="";
    				summe=0;
    				anzahl=0;
    				//Zur Aktualliesierung der Textfelder die leeren Strings ausgeben
    				txb_ausgabe->Text=ganzeZahl;
    				lbl_ausgabe->Text=Ausgabe;
    		}
    
    //Button "end"
    private: System::Void btn_beenden_Click(System::Object^  sender, System::EventArgs^  e) 
    		{
    				//Befehl zum Schliessen des Programms
    				Close();
    		}
    
    void zuweisen(char Oper2, String^ OperatorA)
    {
    	//geschieht nach dem Drücken von "=" und dem nächsten Operator (5+5= 10	   " + "  5)
    	//wenn anzahl gleich 3 ist soll er die Summe erstmal so lassen und der Operator ist gesetzt
    	if(anzahl==3)
    	{
    		anzahl=2;	// setzt anzahl auf 2, fals noch ein Operator gedrückt wird um die nächste if Abfrage Korrekt auszuführen
    	}
    	else if(anzahl==2)	// wenn anzahl 2 setze anzahl auf 1 um die nächste abfrage zu starten
    	{
    		anzahl=1;
    	}
    
    	//wenn anzahl keinen Wert trägt(am Anfang)
    	if(!anzahl)
    	{
    		summe=System::Convert::ToDouble(ganzeZahl);	//eingegebene Zahl wird nur in Summe gespeichert
    		anzahl=1;					//anzahl wird auf 1 gesetzt um beim nächsten Operator druck die zwischenrechnung durchzuführen
    	}
    	else if(anzahl==1)	//wenn anzahl gesetzt und 1 ist dann die rechnung bzw zwischenrechnung ausführen
    	{	
    		rechnen(Oper2);	//Operator wird mit übergeben
    	}
    	ganzeZahl ="";		//setze eingegebene Zahl auf leer
    	Ausgabe += OperatorA;	//Operator in Ausgabe hinzufühen0
    	lbl_ausgabe->Text=Ausgabe;	//Ausgabe im unteren Textfeld
    }
    
    //durchführen der Endrechnung und Zwischenrechnung
    void rechnen(char Oper)
    {
    	switch(Oper)
    	{
    		case '+':
    			summe=summe + System::Convert::ToDouble(ganzeZahl);	//ganzeZahl wird beim Rechnen ins Double umgewandelt und summe wird gespeichert in sich selbst
    			break;
    		case '-':
    			summe=summe - System::Convert::ToDouble(ganzeZahl);	//ganzeZahl wird beim Rechnen ins Double umgewandelt und summe wird gespeichert in sich selbst
    			break;
    		case '*':
    			summe=summe * System::Convert::ToDouble(ganzeZahl);	//ganzeZahl wird beim Rechnen ins Double umgewandelt und summe wird gespeichert in sich selbst
    			break;
    		case '/':
    			summe=summe / System::Convert::ToDouble(ganzeZahl);	//ganzeZahl wird beim Rechnen ins Double umgewandelt und summe wird gespeichert in sich selbst
    			break;
    	}
    }
    private: System::Void txb_ausgabe_TextChanged(System::Object^  sender, System::EventArgs^  e) {
    		 }
    };
    
    }
    

    Ich habe noch nicht wirklich viel Ahnung, der Code is vieleicht sogar ein bissl Kompliziert aber es funktioniert.
    Nur ich habe keine Plan wie ich das machen soll mit Punkt vor Strich rechnung.

    Ich wäre euch sehr dankbar für Tips.
    Fals ihr mir noch Tips geben könnt wie ich mein Quelltext übersichtlicher bzw. einfacher machen kann, wäre ich auch sehr dankbar. 🙂

    mfg Kayamoto



  • Ich habe damals in der Schule auch mal einen Taschenrechner programmiert und hatte ähnliche Schwierigkeiten. Ich kann dir so auf die Schnelle nix genaues sagen (ist schon ewig her), aber eine große Hilfe war es, den Term in Prä- bzw. Postfix-Notation umzuwandeln (also '1+2' ist dann '+12' bzw. '12+'). Mit dieser Notation fallen übrigens auch alle Klammern weg! Vielleicht hilft dir dieser Tipp ein wenig...



  • also darunter verstehe ich mal jetz gar nichts^^.
    also ich habe keine Probelme mehrstellige Zahlen zu berechnen. allet keine ding.
    Aber das mit den Postfix nationen verstehe ich überhaupt nicht wie ich das einsetzen soll.



  • Du kannst dir ja mal das zur Erklärung ansehen:
    http://de.wikipedia.org/wiki/Polnische_Notation

    Wie man das Programmiertechnisch umsetzt kann ich dir auch nicht sagen, damit habe ich mich nie beschäftigt.



  • Sollte auch nur ein kleiner Tipp sein, keine direkte Lösung für dein Problem. Wenn es dich interessiert, dann google bitte danach. Deinen Riesen-Code kann ich mir momentan aus zeitlichen Gründen wirklich nicht ansehen (muss arbeiten), außerdem beherrsche ich kein C++/CLI (du bist im falschen Forum!).



  • Danke für den.
    Das hab ich nun verstanden, aber ich glaube es würde nicht viel bringen dies einzubinden, im gegenteil es würde den Quelltext warscheinlich noch viel schlimmer machen, glaub ich. 🙂

    Ich habe mir das so überlegt.

    der Anwender gibt jetzt das ein.
    5+5*2

    so jetz müsste ich ja zuerst 5 * 2 rechnen.

    Dies würde ich so rausfiltern und danach +5 rechnen.

    Hört sich leicht an, aber ich krieg das einfach nicht hin.

    Problem ist:

    Der Anwender drückt den Button 5. Noch alles schön
    Dann drückt er den + Button. auch noch ok.
    Jetzt drück er nochman den Button 5. Jetzt machter nix weiter. Wenn der = Button gedrückt wird rechnet er es zusammen. Aber wenn er jetzt den * Button drückt würde er 5*5 rechnen und nach drücken von Button 2 unde dem = Button druck, würde er dann auch * 2 rechnen.
    Das heißt ergebnis = 50 anstatt 15.
    Er Rechnet sozusagen alles nacheinnander und das ist beschissen.^^



  • Dafür benötigst du einen Stack, auf dem du die Zwischenergebnisse speicherst:

    5+5*2=
    
    5    5     15
    +    +
    5    10
    *
    2
    = ->    ->
    
    aber
    
    5*5+2=
    
    5    25   27
    *    +
    5
    + ->
    2    2
    =      ->
    

    Du mußt also bei jeder Operation schauen, welche Priorität der aktuelle im Vergleich zu den vorherigen (auf dem Stack) hat und dann Zwischenergebnisse berechnen.



  • hm ok, Ich hab kein plan über Stacks 😕.
    Toll, naja kann ich ja in nem Toturial kugen. Aber Trodzdem muss ich ja Überprüfen welcher Operator dran ist und wann er dran ist. Kann es sein das ich meine Struktur völlig umstellen muss? Da bei jedem Operatordruck(außer dem ersten)die ersten werte zusammengrechnet werden.

    Nur ich habe keine Ahnung wie ich mit Stacks arbeiten muss. Bin halt noch nicht so weit beim Programmieren.

    Aber danke für die Antwort.

    PS: Heißt Stack sogesehen auf dem Speicher?
    bzw auf dem Speicher bleiben bis das Program beendet wird?



  • Stack ist eine spezielle Datenstruktur:

    http://de.wikipedia.org/wiki/Stapelspeicher



  • da es bei dir nicht auf Effizienz ankommt, hätte ich einfach die Aufgabe als std::string gespeichert, um dann nach einem * (oder auch /) zu suchen, die Werte links und rechts ebenfalls rauszuparsen, diese (Neben)rechnung zu lösen und das Ergebniss mittels Insert wieder an die Stelle im string einzufügen.

    Das gleiche Prinzip lässt sich auch auf Klammerausdrücke anwenden:
    - Klammerausdruck raussuchen
    - ausrechnen
    - Ergebisse wieder einfügen
    - sind keine Klammerausrücke, oder Punktrechnungen mehr enthalten, sind die Additionen und Subtraktionen dran

    Lässt sich sehr gut Rekursiv machen. (Hab ich früher mal in pascal geschrieben, sollte in C++ einfacher sein (hatte damals keine so gut Bibliothek wie std.:string 😉 )

    Bei mir war das damals so eine Funktion wo man die Funktion als String und den einzusetzenden Wert X als real (float) übergeben konnte um beliebige Funktionen grafisch darstellen zu können.

    Also wenn du das nicht jetzt sofort brauchst, kümmer ich mich mal drum wenn ich nachher Feierabend hab. (hätte nämlich Bock sowas auch mal wieder zu coden ^^)



  • Die ganzen Geschichten mit Operatorpräzedenz und Stack und so zielen letzten Endes auf eine Aussage ab: du darfst eine Eingabe nur auswerten, wenn keine darauf folgenden Zeichen das korrekte Ergebnis noch beeinflussen können. Das macht es aber nötig, dass du die Auswertung von (A, Operator, 😎 nicht sofort auf dem button click auswertest, sondern erstmal alle Eingaben speicherst, zum Beispiel in einen String wie oben vorgeschlagen, oder eine Liste, oder was weiß ich.

    Beispiel 1:
    Eingabe: "1 + 1 + 1 ="
    Schritt für Schritt wird dies ausgewertet zu 2+1 und schließlich 3. Dies ist aber NUR zulässig, weil nach dem "1+1" ein weiteres "+" kommt, was gleiche oder niedrigere Priorität wie das erste "+" hat (ist ja beides plus, also gilt in diesem Fall Assoziativität, d.h. a+b+c = (a+b)+c = a+(b+c) ).

    Beispiel 2:
    Eingabe: "2 + 5 * 5 ="
    Wenn du mit parsen (also einlesen) deines Eingabestrings bei "2+5" angekommen bist, darfst du diese erst auswerten, wenn hintenan keine "stärker bindender" (punkt vor strich, potenz vor produkt, klammer vor allem anderen, etc.) Operator mehr steht.

    Du musst also bis hierhin parsen "2 + 5 * ". An diesem Punkt merkst du "oha, punkt hat höhere prezedenz als plus". An dieser Stelle merkst du dir das "2 +" erstmal und parst weiter, um den enger bindenden Ausdruck zuerst zu berechnen. Wenn dieser fertig ist (kein NOCH enger bindender Operator hinter dem 5*5, wie es zum Beispiel bei 5*5^2 der Fall wäre), wertest du ihn aus. Wenn du das 5*5 = 25 ausgewertet hast, gehst du zurück zu dem Ausdruck 2 + (Ergebnis von 5*5) und wertest diesen aus.

    Taschenrechner mit Punkt vor Strich ist kompliziert genug, dass man so Sachen machen muss. Einfach nur "klick - auswert - klick - auswert" geht auf jeden Fall schief, weil es keine Operatorpräzedenz berücksichtigen kann.



  • Ich meine es so:

    1. Formel komplett einlesen -> std::string

    Rekursive Funktion
    {
    Finde alle Potenzierungen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Multiplikationen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Klammerausdrücke im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Subtraktionen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Additionen im String -> Ausrechnen & Ergebniss einfügen

    }

    damit müsstest du auf der sicheren seite sein, da du die wichtigen Dinge zuerst auswertest.


  • Mod

    Kann mir einer erklären, warum das hier im falschen Forum ist bzw. noch niemand darauf hingewiesen hat?



  • _matze schrieb:

    ...außerdem beherrsche ich kein C++/CLI (du bist im falschen Forum!).



  • hab mich schon gewundert warum der Quelltext so komisch aussieht 🕶



  • Finde ich in dem Fall aber gar nicht schlimm, da die Diskussion ja eher sprachenunabhängig verläuft.



  • It0101 schrieb:

    Rekursive Funktion
    {
    Finde alle Potenzierungen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Multiplikationen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Klammerausdrücke im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Subtraktionen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Additionen im String -> Ausrechnen & Ergebniss einfügen

    }

    Moin,

    wiso hast du eigentlich die Multiplikation/Division vor die Klammernbearbeitung gesetzt?
    Wenn man z.B. solch einen Ausdruck "2*(5+5)" vorzuliegen hat und du dann als erstest die Multiplikation auflösen willst, soll das Programm 2*( ausrechnen, aber das geht schlecht, dann müsste man das ganze abfangen und dann zunächst einmal die Klammer auflösen. Ergo wäre es doch eigentlich unkomplizierter, wenn man erst die Klammern auflöst "5+5=10" und dann die Multiplikation durchführt "10*2=20".



  • ups sry, my fault ^^ Hatte da in dem Moment nicht so genau drüber nachgedacht 😉

    Der ganze Klammerkram muss natürlich nach oben.



  • ahhh ich hab aber auch nicht aufgepasst 🤡
    Klammernbehandlung muss ja an die erste Stelle, z.B. 2^(5-2)

    Rekursive Funktion
    {
    Finde alle Klammerausdrücke im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Potenzierungen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Multiplikationen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Subtraktionen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Additionen im String -> Ausrechnen & Ergebniss einfügen
    }
    


  • da hast du wohl recht, auch wenn es in dem Fall egal ist, da der Threadersteller ja nur Grundrechenarten benötigt 😉


Anmelden zum Antworten