# Taschenrechner mit Klammern



## Lenzen (26. Nov 2006)

Hallo!
Ich bin im Rahmen eines Projektes dabei einen Taschenrechner zu programmieren. Dieser ist auch so gut wie fertig. Leider gelingt es mir nicht die Klammern mit in die Benutzung einzubringen. Ich hab nun schon etliche Stunden versucht hier etwas zu finden.

Meine Lösung bisher:



Kann mir hier einer weiterhelfen??



```
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JTextField;


public class Taschenrechner extends Frame {

    private static final long serialVersionUID = 1L;
    
    // Instanzvariablen
    private JTextField eingabeFeld;
    private Panel nummernTasten, operationsTasten, clearTasten, klammerBack;    
    private Button b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,bPuM,bK,bPlus,bMinus,bMal,
                   bDurch,bGleich,bBack,bKla,bKlz,bCE,bC;    
    
    private boolean bEqual = true;
    private double Operand1 = 0;
    private String Operator1="";

    //Konstruktor
    public Taschenrechner() {    
        
        //Aufbau der Rechner GUI 
        RechnerGUI();         
        //Zusammensetzen der Komponenten         
        add(eingabeFeld);
        add(nummernTasten);
        add(operationsTasten);
        add(klammerBack);
        add(clearTasten);
        //zum schliessen des Fensters
        addWindowListener( new schliesseMeinFenster() );       
        
    } 

    
    public void RechnerGUI() {
        //Position und Größe(int x, int y, int width, int height)
        setBounds(300, 200, 245, 330);          // Größe des Rahmens
        setResizable(false);                    // kein Maximieren möglich
        setTitle(" Calc ");
        setBackground(Color.lightGray);
        setLayout(null);        
        
        eingabeFeld = new JTextField("Guten Tag !!");//JTextField() da hier rechtsbündig möglich
        eingabeFeld.setHorizontalAlignment(JTextField.RIGHT); // rechtsbündig
        eingabeFeld.setEditable(false);         // man kann etwas in Display schreiben
        eingabeFeld.requestFocus();             // hat im Rechner den Focus
        eingabeFeld.setForeground(Color.yellow);
        eingabeFeld.setFont(new Font("Serif", Font.BOLD, 20));
        eingabeFeld.setBackground(Color.black);        
        eingabeFeld.setBounds(15, 30, 213, 35);            
        
        nummernfeld(); // Methode zum Einfügen der Zahlentasten
    }
    
    public void nummernfeld() {
        nummernTasten = new Panel();
        nummernTasten.setForeground(Color.blue);
        nummernTasten.setBounds(15, 160, 160, 160);
        nummernTasten.setLayout(new GridLayout(4, 3, 7, 7));
        
        b7 = new Button("7"); nummernTasten.add(b7); b7.addActionListener(new Ereignis());
        b8 = new Button("8"); nummernTasten.add(b8); b8.addActionListener(new Ereignis());
        b9 = new Button("9"); nummernTasten.add(b9); b9.addActionListener(new Ereignis());
        b4 = new Button("4"); nummernTasten.add(b4); b4.addActionListener(new Ereignis());
        b5 = new Button("5"); nummernTasten.add(b5); b5.addActionListener(new Ereignis());
        b6 = new Button("6"); nummernTasten.add(b6); b6.addActionListener(new Ereignis());
        b1 = new Button("1"); nummernTasten.add(b1); b1.addActionListener(new Ereignis());
        b2 = new Button("2"); nummernTasten.add(b2); b2.addActionListener(new Ereignis());
        b3 = new Button("3"); nummernTasten.add(b3); b3.addActionListener(new Ereignis());
        b0 = new Button("0"); nummernTasten.add(b0); b0.addActionListener(new Ereignis());
        bPuM = new Button("+/-");nummernTasten.add(bPuM); bPuM.addActionListener(new Ereignis());
        bK = new Button("."); nummernTasten.add(bK);bK.addActionListener(new Ereignis()); 
               
        operationsfeld(); // Methode für Rechenoperationen        
    }

    public void operationsfeld() {
        operationsTasten = new Panel();
        operationsTasten.setForeground(Color.red);
        //x, y, Breite der Tasten, Höhe der Tasten
        operationsTasten.setBounds(180, 120, 48, 198);
        //Zeile, Spalte
        operationsTasten.setLayout(new GridLayout(5, 1, 7, 7));
       
        bPlus   = new Button("+"); operationsTasten.add(bPlus);  bPlus.addActionListener(new Ereignis());
        bMinus  = new Button("-"); operationsTasten.add(bMinus); bMinus.addActionListener(new Ereignis());
        bMal    = new Button("*"); operationsTasten.add(bMal);   bMal.addActionListener(new Ereignis());
        bDurch  = new Button("/"); operationsTasten.add(bDurch); bDurch.addActionListener(new Ereignis());
        bGleich = new Button("="); operationsTasten.add(bGleich);bGleich.addActionListener(new Ereignis());        
        
        KlammernUndZurueck(); //Methode für Klammern und Back
    }

    public void KlammernUndZurueck() {
        klammerBack = new Panel();
        klammerBack.setForeground(Color.red);
        klammerBack.setBounds(15, 120, 160, 34);
        klammerBack.setLayout(new GridLayout(1, 4, 7, 7));
        
        bBack = new Button("Back"); klammerBack.add(bBack); bBack.addActionListener(new Ereignis());
        bKla  = new Button("("); klammerBack.add(bKla); bKla.addActionListener(new Ereignis());
        bKlz  = new Button(")"); klammerBack.add(bKlz); bKlz.addActionListener(new Ereignis());   
        
        clearfeld(); //Methode für Löschtasten
    }

    public void clearfeld() {
        clearTasten = new Panel();
        clearTasten.setForeground(Color.red);
        clearTasten.setBounds(15, 75, 213, 35);
        clearTasten.setLayout(new GridLayout(1, 2, 7, 0));  
        
        bCE = new Button("CE"); clearTasten.add(bCE); bCE.addActionListener(new Ereignis());
        bC = new Button("C");   clearTasten.add(bC);  bC.addActionListener(new Ereignis());        
    }
    
    /**
     * Das ist ein passender WindowAdapter auf das Interface WindowListener.
     * Hier haben die Java Entwickler eine Arbeitserleichterung vorgesehen!!
     */
    class schliesseMeinFenster extends WindowAdapter{        
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    }
    
    public class Ereignis implements ActionListener{       

        public void actionPerformed(ActionEvent e) {    
            
            int h;            
            
            if( e.getActionCommand() == b0.getLabel()){            
                ziffer("0"); 
            }
            if( e.getActionCommand() == b1.getLabel()){               
                ziffer("1"); 
            } 
            if( e.getActionCommand() == b2.getLabel()){                
                ziffer("2"); 
            } 
            if( e.getActionCommand() == b3.getLabel()){                
                ziffer("3"); 
            } 
            if( e.getActionCommand() == b4.getLabel()){               
                ziffer("4"); 
            } 
            if( e.getActionCommand() == b5.getLabel()){                
                ziffer("5"); 
            } 
            if( e.getActionCommand() == b6.getLabel()){               
                ziffer("6");
            } 
            if( e.getActionCommand() == b7.getLabel()){                
                ziffer("7"); 
            } 
            if( e.getActionCommand() == b8.getLabel()){                
                ziffer("8"); 
            } 
            if( e.getActionCommand() == b9.getLabel()){                
                ziffer("9"); 
            }             
            //Addition
            if (e.getActionCommand() == bPlus.getLabel()) {
                operation("+");
            }
            //Subtraktion
            if (e.getActionCommand() == bMinus.getLabel()) { 
                operation("-");
            }
            //Multiplikation
            if (e.getActionCommand() == bMal.getLabel()) { 
                operation("*");
            }
            //Division
            if (e.getActionCommand() == bDurch.getLabel()) { 
                operation("/");
            }
            //Gleich (Ergebnis)
            if (e.getActionCommand() == bGleich.getLabel()) { 
                operation("");
            }    
            // Komma
            if (e.getActionCommand() == bK.getLabel()) {                
                if (bEqual) {
                    eingabeFeld.setText("0.");
                    bEqual = false;
                   }
                   else {                    
                       String sValue = new String(eingabeFeld.getText());                    
                       h = sValue.indexOf(".");                    
                       if (h < 0) {                        
                           eingabeFeld.setText(eingabeFeld.getText() + ".");                           
                       }                  
                   }
            }                
            // Vorzeichenwechsel
            if (e.getActionCommand() == bPuM.getLabel() && eingabeFeld.getText().length() > 0) {                    
                if (eingabeFeld.getText().charAt(0)=='-')                   
                    eingabeFeld.setText(eingabeFeld.getText().substring(1,eingabeFeld.getText().length()));                 
                else                    
                    eingabeFeld.setText('-'+eingabeFeld.getText());           
            }           
            // Backspace (löschen)                
            if (e.getActionCommand().equals("Back")){                
                if (eingabeFeld.getText().length() != 0)                   
                    eingabeFeld.setText(eingabeFeld.getText().substring(0, eingabeFeld.getText().length() - 1));          
            }           
            // Clear Entry: letzte Eingabe rückgängig machen              
            if (e.getActionCommand().equals("CE")&& eingabeFeld.getText().length() > 0){                     
                eingabeFeld.setText(null);
            }
            // Löschen                
            if (e.getActionCommand().equals("C")){                    
                eingabeFeld.setText("");                   
                Operand1=0;                    
                Operator1="";             
            }       
        }   
    }
    
    /**
     * Wird aufgerufen, wenn die Ereignisbehandlung eine Zifferntaste erkannt
     * hat.
     */     
    public void ziffer(String s) {        
        if (bEqual) {            
            eingabeFeld.setText(s);
            bEqual = false;        
        } else {
            eingabeFeld.setText(eingabeFeld.getText()+ s);
        }
    }

    /**
     * Wird aufgerufen, wenn die Ereignisbehandlung ein Opperationszeichen
     * erkannt hat.
     */    
    public void operation(String s) {
        Double d1;
        bEqual = true;
        try {
            if (Operator1 == "") {
                d1 = new Double(eingabeFeld.getText());
                Operand1 = d1.doubleValue();
                Operator1 = s;
            } else {
                d1 = new Double(eingabeFeld.getText());
                if (Operator1 == "+") {
                    Operand1 = Operand1 + d1.doubleValue();
                } else if (Operator1 == "-") {
                    Operand1 = Operand1 - d1.doubleValue();
                } else if (Operator1 == "*") {
                    Operand1 = Operand1 * d1.doubleValue();
                } else if (Operator1 == "/") {
                    Operand1 = Operand1 / d1.doubleValue();
                }
                Operator1 = s;
                eingabeFeld.setText(String.valueOf(Operand1));
            }
        } catch (ArithmeticException e) {
            eingabeFeld.setText("Error:" + e);
        } catch (Throwable e) {
            eingabeFeld.setText("Fehler:" + e);
        }    
    }

}
```


----------



## SlaterB (26. Nov 2006)

soll dein Taschenrechner 

5*(4+(5*(4+(7/8))))
ausrechen können?

dann musst du dein Programm komplett umbauen,
dann musst du dir ja mehr als einen Operand merken,
vielleicht einfach die ganze Eingabe, und diese erst beim = parsen und ausrechnen,

jedenfalls nix was man so mal eben an deinem Code ändern kann..


----------



## Lenzen (26. Nov 2006)

...genau so wie deinem Beispiel soll der Rechner funktionieren also sprich: es sollen Klammern unterstützt werden, die sich beliebig tief schachteln lassen...

Leider fehlt mir die Idee, wie ich das in den Code umsetzen kann. Hier bin ich leider auch im Netz nicht fündig geworden, wie man so etwas umsetzen kann.
Kannst du mir hier etwas auf die Sprünge helfen?   :?


----------



## SlaterB (26. Nov 2006)

siehe FAQ
http://www.java-forum.org/de/viewtopic.php?t=13378

was meicht dein Browser eigentlich wenn du ohne Klammern
6+4*5 eingibst, bisher kommt da doch bestimmt 50 raus?
soll das nun auch zum korrekten Ergebnis 26 hin geändert werden oder so bleiben?

wenn es so bleiben soll wäre das eine Besonderheit gegenüber den Standard-Matheparsern, da musst du aufpassen


----------



## EOB (27. Nov 2006)

koennte man mit nem stack machen, einen fuer die zahlen einen fuer die operatoren...

gruesse


----------



## Guest (27. Nov 2006)

Der Parser funktioniert super. Ist aber ein sehr viel Code. Vielleicht gibt das ganze etwas einfacher. 

wenn ich:

```
double a = 5*(4+(5*(4+(7/8)))) ;
System.out.println(a);
```
...kommt das richtige Ergebnis raus. 

Wie kann ich dies geschickt umsetzen?   :?


----------



## WieselAc (27. Nov 2006)

Viel einfacher /geschickter geht es nicht. Du musst halt leider soetwas wie einen kleinen "compiler" bauen. Und das läuft immer auf soetwas ähnlichs hinaus. Grundlegend solltest du aber wirklich zuerst einmal die GUI und das Programm trennen. Sonste wird das vieeeel zu unüberscihtlich!!


Also über den "GUI-Rechner" kann der benutzer einen String eingeben und wenn er gleich drückt, holst du dir den String und bestimmst das Ergebniss. Dadurch wird die Entwiklung auch stark vereinfacht, da du beides (GUI/Algorithmus) getrennt voneinander entwickeln kannst.

Um die eigentliche Berechnung durch zu führen kannst du dich ja ein wenig in Compilerbau einlesen, da bekommst du einen Einblick, wie man so einen Syntax-Heap oder vielleicht hier sogar besser einen Tree aufziehst. Das ist auf jeden Fall nichts für einen Nachmittag.


----------



## me1357 (27. Nov 2006)

Und wenn du faul bist, kannst du auch eine fertige Komponente nehmen.
Das hier dürfte deinen Anforderungen entsprechen: http://www.singularsys.com/jep/


----------



## Lenzen (4. Dez 2006)

Hallo, ich habe meinen Taschenrechner jetzt etwas anderes realisiert. Er funktioniert nun nach der umgekehrten Polnischen Notation! 
Ich habe aber immer noch ein kleines Problem mit folgender Eingabe: z.B 5*() oder 2 aufeinander folgende Operatoren z.B. -2*-2 -> mit Klammern geht das natürlich also -2*(-2) funktioniert
Wer kann helfen?? Gerne auch Fehler innerhalb des Codes fixen, ich bin für jeden gefundenen Fehler dankbar.


```
package UPN_Taschenrechner;

public class Start_Taschenrechner {

    public static void main(String[] args) {
        Taschenrechner ta = new Taschenrechner();
        ta.setVisible(true);

    }

}
```


```
package UPN_Taschenrechner;

import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JTextField;

public class Taschenrechner extends Frame {

    private static final long serialVersionUID = 1L;
    
    // Instanzvariablen
    private JTextField eingabeFeld;
    private Panel nummernTasten, operationsTasten, clearTasten, klammerBack;    
    private Button b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,bPuM,bK,bPlus,bMinus,bMal,
                   bDurch,bGleich,bBack,bKla,bKlz,bCE,bC;    
    
    private boolean bEqual = true;

    //Konstruktor
    public Taschenrechner() {    
        
        //Aufbau der Rechner GUI 
        RechnerGUI();         
        //Zusammensetzen der Komponenten         
        add(eingabeFeld);
        add(nummernTasten);
        add(operationsTasten);
        add(klammerBack);
        add(clearTasten);
        //zum schliessen des Fensters
        addWindowListener( new schliesseMeinFenster() );     
        
    } 
    
    public void RechnerGUI() {
        //Position und Größe(int x, int y, int width, int height)
        setBounds(300, 200, 245, 330);          // Größe des Rahmens
        setResizable(false);                    // kein Maximieren möglich
        setTitle("Calc by F & R Design");
        setBackground(Color.lightGray);
        setLayout(null);        
        
        eingabeFeld = new JTextField();//JTextField() da hier rechtsbündig möglich
        eingabeFeld.setHorizontalAlignment(JTextField.RIGHT); // rechtsbündig
        eingabeFeld.setEditable(false);         // man kann etwas in Display schreiben
        eingabeFeld.requestFocus();             // hat im Rechner den Focus
        eingabeFeld.setForeground(Color.yellow);
        eingabeFeld.setFont(new Font("Serif", Font.BOLD, 20));
        eingabeFeld.setBackground(Color.black);        
        eingabeFeld.setBounds(15, 30, 213, 35);            
        
        nummernfeld(); // Methode zum Einfügen der Zahlentasten
    }
    
    public void nummernfeld() {
        nummernTasten = new Panel();
        nummernTasten.setForeground(Color.blue);
        nummernTasten.setBounds(15, 160, 160, 160);
        nummernTasten.setLayout(new GridLayout(4, 3, 7, 7));
        
        b7 = new Button("7"); nummernTasten.add(b7); b7.addActionListener(new Ereignis());
        b8 = new Button("8"); nummernTasten.add(b8); b8.addActionListener(new Ereignis());
        b9 = new Button("9"); nummernTasten.add(b9); b9.addActionListener(new Ereignis());
        b4 = new Button("4"); nummernTasten.add(b4); b4.addActionListener(new Ereignis());
        b5 = new Button("5"); nummernTasten.add(b5); b5.addActionListener(new Ereignis());
        b6 = new Button("6"); nummernTasten.add(b6); b6.addActionListener(new Ereignis());
        b1 = new Button("1"); nummernTasten.add(b1); b1.addActionListener(new Ereignis());
        b2 = new Button("2"); nummernTasten.add(b2); b2.addActionListener(new Ereignis());
        b3 = new Button("3"); nummernTasten.add(b3); b3.addActionListener(new Ereignis());
        b0 = new Button("0"); nummernTasten.add(b0); b0.addActionListener(new Ereignis());
        bPuM = new Button("+/-");nummernTasten.add(bPuM); bPuM.addActionListener(new Ereignis());
        bK = new Button("."); nummernTasten.add(bK);bK.addActionListener(new Ereignis()); 
               
        operationsfeld(); // Methode für Rechenoperationen        
    }

    public void operationsfeld() {
        operationsTasten = new Panel();
        operationsTasten.setForeground(Color.red);
        //x, y, Breite der Tasten, Höhe der Tasten
        operationsTasten.setBounds(180, 120, 48, 198);
        //Zeile, Spalte
        operationsTasten.setLayout(new GridLayout(5, 1, 7, 7));
       
        bPlus   = new Button("+"); operationsTasten.add(bPlus);  bPlus.addActionListener(new Ereignis());
        bMinus  = new Button("-"); operationsTasten.add(bMinus); bMinus.addActionListener(new Ereignis());
        bMal    = new Button("*"); operationsTasten.add(bMal);   bMal.addActionListener(new Ereignis());
        bDurch  = new Button("/"); operationsTasten.add(bDurch); bDurch.addActionListener(new Ereignis());
        bGleich = new Button("="); operationsTasten.add(bGleich);bGleich.addActionListener(new Ereignis());        
        
        KlammernUndZurueck(); //Methode für Klammern und Back
    }

    public void KlammernUndZurueck() {
        klammerBack = new Panel();
        klammerBack.setForeground(Color.red);
        klammerBack.setBounds(15, 120, 160, 34);
        klammerBack.setLayout(new GridLayout(1, 4, 7, 7));
        
        bBack = new Button("Back"); klammerBack.add(bBack); bBack.addActionListener(new Ereignis());
        bKla  = new Button("("); klammerBack.add(bKla); bKla.addActionListener(new Ereignis());
        bKlz  = new Button(")"); klammerBack.add(bKlz); bKlz.addActionListener(new Ereignis());   
        
        clearfeld(); //Methode für Löschtasten
    }

    public void clearfeld() {
        clearTasten = new Panel();
        clearTasten.setForeground(Color.red);
        clearTasten.setBounds(15, 75, 213, 35);
        clearTasten.setLayout(new GridLayout(1, 2, 7, 0));  
        
        bCE = new Button("CE"); clearTasten.add(bCE); bCE.addActionListener(new Ereignis());
        bC = new Button("C");   clearTasten.add(bC);  bC.addActionListener(new Ereignis());        
    }
    
    /**
     * Das ist ein passender WindowAdapter auf das Interface WindowListener.
     * Hier haben die Java Entwickler eine Arbeitserleichterung vorgesehen!!
     */
    class schliesseMeinFenster extends WindowAdapter{        
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    }
    
    public class Ereignis implements ActionListener{       

        public void actionPerformed(ActionEvent e) {                 
            
            if( e.getActionCommand() == b0.getLabel()){            
                eingabeFeld.setText(eingabeFeld.getText()+ "0"); 
            
            }else if( e.getActionCommand() == b1.getLabel()){               
                eingabeFeld.setText(eingabeFeld.getText()+ "1");
                
            
            }else if( e.getActionCommand() == b2.getLabel()){                
                eingabeFeld.setText(eingabeFeld.getText()+ "2"); 
               
            }else if( e.getActionCommand() == b3.getLabel()){                
                eingabeFeld.setText(eingabeFeld.getText()+ "3"); 
                
            }else if( e.getActionCommand() == b4.getLabel()){               
                eingabeFeld.setText(eingabeFeld.getText()+ "4");
                
            }else if( e.getActionCommand() == b5.getLabel()){                
                eingabeFeld.setText(eingabeFeld.getText()+ "5");
               
            }else if( e.getActionCommand() == b6.getLabel()){               
                eingabeFeld.setText(eingabeFeld.getText()+ "6");
                
            }else if( e.getActionCommand() == b7.getLabel()){                
                eingabeFeld.setText(eingabeFeld.getText()+ "7"); 
                
            }else if( e.getActionCommand() == b8.getLabel()){                
                eingabeFeld.setText(eingabeFeld.getText()+ "8"); 
               
            }else if( e.getActionCommand() == b9.getLabel()){                
                eingabeFeld.setText(eingabeFeld.getText()+ "9");                
                        
            //Addition
            }else if (e.getActionCommand() == bPlus.getLabel()) {
                eingabeFeld.setText(eingabeFeld.getText()+ "+");                
            
            //Subtraktion
            }else if (e.getActionCommand() == bMinus.getLabel()) { 
                eingabeFeld.setText(eingabeFeld.getText()+ "-");                
            
            //Multiplikation
            }else if (e.getActionCommand() == bMal.getLabel()) { 
                eingabeFeld.setText(eingabeFeld.getText()+ "*");                
            
            //Division
            }else if (e.getActionCommand() == bDurch.getLabel()) { 
                eingabeFeld.setText(eingabeFeld.getText()+ "/");                
            
            //Klammer auf
            }else if (e.getActionCommand() == bKla.getLabel()) { 
                eingabeFeld.setText(eingabeFeld.getText()+ "(");                
            
            //Klammer zu
            }else if (e.getActionCommand() == bKlz.getLabel()) { 
                eingabeFeld.setText(eingabeFeld.getText()+ ")");               
                       
            // Komma
            }else if (e.getActionCommand() == bK.getLabel()) {                
                if (bEqual) {
                    eingabeFeld.setText("0.");
                    bEqual = false;
                   }
                   else {                    
                       String sValue = new String(eingabeFeld.getText());                    
                       int h = sValue.indexOf(".");                    
                       if (h < 0) {                        
                           eingabeFeld.setText(eingabeFeld.getText() + ".");                           
                       }                  
                   }                            
            // Vorzeichenwechsel
            }else if (e.getActionCommand() == bPuM.getLabel() && eingabeFeld.getText().length() > 0) {                    
                if (eingabeFeld.getText().charAt(0)=='-')                   
                    eingabeFeld.setText(eingabeFeld.getText().substring(1,eingabeFeld.getText().length()));                 
                else                    
                    eingabeFeld.setText('-'+eingabeFeld.getText());           
                       
            // Backspace (loeschen)                
            }else if (e.getActionCommand().equals("Back")){                
                if (eingabeFeld.getText().length() != 0)                   
                    eingabeFeld.setText(eingabeFeld.getText().substring(0, eingabeFeld.getText().length() - 1));          
                       
            // Clear Entry: letzte Eingabe rueckgaengig machen              
            }else if (e.getActionCommand().equals("CE")&& eingabeFeld.getText().length() > 0){                     
                if (eingabeFeld.getText().length() <= 0) { // tue nichts
                } else {
                    String s = eingabeFeld.getText();

                    for (int i = eingabeFeld.getText().length() - 1; i >= 0; i--) {
                        // pruefen, ob ein Operand im Display steht
                    	if (isOperand(s.charAt(i))) {
                    		// letzte Eingabe mit "(" Kalammer entfernen
                            if (((Character) s.charAt(i - 1)).equals('(')) {
                            	eingabeFeld.setText(eingabeFeld.getText().substring(0, i - 1));
                            } else // bis zum Operand alles entfernen                            	
                            	eingabeFeld.setText(eingabeFeld.getText().substring(0, i + 1));
                            i = -1;
                        }
                    }
                }
            
            // alles Loeschen                
            }else if (e.getActionCommand().equals("C")){                    
                eingabeFeld.setText("");       
            
            //Gleich (Ergebnis)
            }else if (e.getActionCommand() == bGleich.getLabel()) { 
                // Eingabe vom Display wird Klasse Calc übergeben
                String s = eingabeFeld.getText();                 
                Calc c = new Calc(s);  
                // Ergebnis wird auf dem Display ausgegeben 
                double result = c.calcString();
                eingabeFeld.setText(Double.toString(result));  
            }           
        }
        //Methode zum Pruefen, ob Operand vorliegt
        private boolean isOperand(Character arg) {
            if (arg.equals('*') || arg.equals('/') 
             || arg.equals('+') || arg.equals('-'))

                return true;
            else
                return false;
        }
    }
}
```


```
package UPN_Taschenrechner;

import java.util.*;

public class Calc {
    
    // Instanzvariablen
    private String infix;
    private Stack<String> operandenStack = new Stack<String>();
    private Stack<Double> calcStack = new Stack<Double>();    
    
    // Konstruktor
    public Calc(String infix) {
        this.infix = infix;
    }
    
    public double calcString() {
        String Postfix = InfixToPostfix();
        int PostfixLength = Postfix.length(); 
        //--------------------------------------------------------
    	if(checkString()){ // die Eingabe wird auf Fehler geprüft
        //--------------------------------------------------------
                    
            for (int i=0; PostfixLength > i;) {            	
                if (isDigit(Postfix.charAt(i))) {
                    StringBuffer digit = new StringBuffer();
                    digit.append(Postfix.charAt(i++));
                    while (i < PostfixLength && (isDigit(Postfix.charAt(i))
                    || isDot(Postfix.charAt(i)) || Postfix.charAt(i) == 'E')){
                        digit.append(Postfix.charAt(i++));
                    }
                    try {
                        if (Postfix.charAt(i) == 's') {
                            double temp = Double.parseDouble(digit.toString());
                            calcStack.push(temp * (-1));
                            ++i;
                        } else
                            calcStack.push(Double.parseDouble(digit.toString()));
                        
                    } catch (NumberFormatException e) {
                    	System.out.println("err:"+e);
                    }
                    if (isWhitespace(Postfix.charAt(i))) {
                        i++;
                    }
                } else if (isOperand(Postfix.charAt(i))) {
                    if (Postfix.charAt(i) == '*') {
                        i++;
                        double temp = calcStack.pop();
                        double temp1 = calcStack.pop();
                        calcStack.push(temp1 * temp);
                    } else if (Postfix.charAt(i) == '/') {
                        try {
                            double temp = calcStack.pop();
                            double temp1 = calcStack.pop();
                            calcStack.push(temp1 / temp);
                            
                            i++;
                        } catch (Exception e) {
                        	System.out.println("err:"+e);
                        }
                        
                    } else if (Postfix.charAt(i) == '+') {
                        i++;
                        double temp = calcStack.pop();
                        double temp1 = calcStack.pop();
                        calcStack.push(temp1 + temp);
                    } else if (Postfix.charAt(i) == '-') {
                        i++;
                        double temp = calcStack.pop();
                        double temp1 = calcStack.pop();
                        
                        calcStack.push(temp1 - temp);
                    }
                }
            }            
            return calcStack.pop();
        }
        return 0; // es muessen mind. 3 Zeichen sein
    }

    private String InfixToPostfix() {
        
        String Postfix = "";        
        boolean hasCharForInfix = true;
        /*
         * Solange bis versucht wird auf ein elem was nicht existiert
         * zuzugreifen
         */
        int i = 0;
        while (hasCharForInfix) {
            /* Ab hier begin für das Scannen des InfixAusdrucks */
            try {            	
                // prüfen auf negatives Vorzeichen
                if (((Character) infix.charAt(0)).equals('-')&& Postfix.length() == 0) {
                    ++i;
                    while ((isDigit(infix.charAt(i)) || isDot(infix.charAt(i)) || 
                                    infix.charAt(i) == 'E')) {
                        Postfix += infix.charAt(i) + "";
                        ++i;
                    }
                    Postfix += "s "; // vorzeichenbehaftet (signed)                                    
                }
                //prüfen, ob aktuelles Zeichen eine Zahl ist
                if (isDigit(infix.charAt(i))) {
                    Postfix += infix.charAt(i++); // mehr als eine Zahl vorhanden ####
                    while ((isDigit(infix.charAt(i)) || isDot(infix.charAt(i)) || infix.charAt(i) == 'E')) {
                        Postfix += infix.charAt(i) + "";
                        ++i;
                    }
                    Postfix += " ";
                    
                  // pruefen, ob aktuelles Zeichen eine oeffnende Klammer ist
                } else if (isOpenKlammer(infix.charAt(i))) {
                    operandenStack.push(infix.charAt(i++) + "");                    
                   
                    if (((Character) infix.charAt(i)).equals('-')) {
                        ++i;
                        while (i < this.infix.length() 
                        		&& (isDigit(infix.charAt(i))|| isDot(infix.charAt(i)) || infix.charAt(i) == 'E')) {
                            Postfix += infix.charAt(i++) + ""; // mehr als eine Klammer vorhanden ###
                        }
                        Postfix += "s "; // vorzeichenbehaftet (signed)
                        if (((Character) infix.charAt(i)).equals(')')) {
                            operandenStack.pop();
                            ++i;
                        }
                    }

                  // pruefen, ob aktuelles Zeichen eine schliessende Klammer ist
                } else if (isClosedKlammer(infix.charAt(i))) {

                    while (!operandenStack.isEmpty() && !operandenStack.peek().equals("(")) {

                        Postfix += operandenStack.pop();
                    }
                    if (!operandenStack.isEmpty())
                        operandenStack.pop();
                    i++;
                    
                  // pruefen, ob aktuelles Zeichen ein Operand ist
                } else if (isOperand(infix.charAt(i))) {
                    try {
                        while (prio(infix.charAt(i)) <= prio(operandenStack.peek().charAt(0))) {
                            Postfix += operandenStack.pop();
                        }

                    } catch (EmptyStackException e) {                    	
                    	
                    }
                    operandenStack.push(infix.charAt(i++) + "");
                }

            } catch (StringIndexOutOfBoundsException e) {
                // Ende des Strings erreicht boolean wird geaendert
                hasCharForInfix = false;
            }
        }
        while (!operandenStack.isEmpty()) {
            Postfix += operandenStack.pop();
        }
        return Postfix;
    }
    // String wird auf etwaige Eingabefehler getestet
    public boolean checkString() {
        int openKlammer = 0, closedKlammer = 0, digits = 0, operand = 0;
        for (int i = 0; i < infix.length(); i++) {
        	
        	// Anzahl der offenen Klammer ermitteln
        	if (isOpenKlammer(infix.charAt(i))) {
        		try {//test, folgendes Zeichen neg. Vorzeichen
                if (infix.charAt(i + 1) == '-')// signed oder nicht                	
                    i++; // zum nachfolgenden Wert springen
                
        		} catch (StringIndexOutOfBoundsException e) {
            		return false; //Bereich nach hinten ueberschritten !! 
            	}
        		openKlammer++; //Zaehler offene Klammer hochsetzen
        		
              // Anzahl der geschlossenen Klammer ermitteln
            } else if (isClosedKlammer(infix.charAt(i))) {
                closedKlammer++; //Zaehler geschlossene Klammer hochsetzen
            
                // Anzahl der Zahlen ermitteln
            } else if (isDigit(infix.charAt(i))) {
                try {
                    while (i < infix.length()&& (isDigit(infix.charAt(i + 1)) || 
                    		isDot(infix.charAt(i + 1)) || infix.charAt(i + 1) == 'E')) {
                        i++;
                    }
                } catch (StringIndexOutOfBoundsException e) {
                	
                }
                digits++;
              // Anzahl der Operanden ermitteln  
            } else if (isOperand(infix.charAt(i))) {
                operand++;
            } else
                return false;

        }// return true, wenn nachfolgende Bedingungen stimmen!
        return (openKlammer == closedKlammer) && (operand > 0); 
        //&&(digits - 1 == operand);
    }
//############################ Priorität vergeben ###############################
    private int prio(Character arg) {
        if (arg.equals("(".charAt(0)))
            return 0;
        else if (arg.equals("+".charAt(0)) || arg.equals("-".charAt(0)))
            return 1;
        else
            return 2;
    }
//############################## Test-Methoden  #################################  
    // auf Zahl pruefen
    private boolean isDigit(Character arg) {
        try {
            Integer.parseInt(arg + "");

        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }
    // auf offene Klammer pruefen
    private boolean isOpenKlammer(Character arg) {
        if (arg.equals('('))
            return true;
        else
            return false;
    }
    // auf geschlossene Klammer pruefen
    private boolean isClosedKlammer(Character arg) {
        if (arg.equals(')'))
            return true;
        else
            return false;
    }
    // auf Komma pruefen
    private boolean isDot(Character arg) {
        if (arg.equals('.'))
            return true;
        else
            return false;
    }
    // auf Operanden pruefen
    private boolean isOperand(Character arg) {
        if (arg.equals('*') || arg.equals('/') || 
        	arg.equals('+') || arg.equals('-'))
            return true;
        else
            return false;
    }
    // auf Leerzeichen pruefen
    private boolean isWhitespace(Character arg) {
        if (arg.equals(' '))
            return true;
        else
            return false;
    }
}
```

Ich denke das Problem liegt hier:


```
}// return true, wenn nachfolgende Bedingungen stimmen!
        return (openKlammer == closedKlammer) && (operand > 0); 
        //&&(digits - 1 == operand);
```


----------



## Leroy42 (5. Dez 2006)

Lenzen hat gesagt.:
			
		

> Hallo, ich habe meinen Taschenrechner jetzt etwas anderes realisiert. Er funktioniert nun nach der umgekehrten Polnischen Notation!
> Ich habe aber immer noch ein kleines Problem mit folgender Eingabe: z.B 5*() oder 2 aufeinander folgende Operatoren z.B. -2*-2 -> mit Klammern geht das natürlich also -2*(-2) funktioniert
> Wer kann helfen?? Gerne auch Fehler innerhalb des Codes fixen, ich bin für jeden gefundenen Fehler dankbar.



Seit wann gibt es bei UPN-Taschenrechnern denn Klammern?  :shock:  :autsch:


----------



## Lenzen (5. Dez 2006)

Vielleicht habe ich es etwas fasch beschrieben: -> das ganze funktioniert mit einer Umwandlung von Infix-in Postfixnotation und dann kann die UPN angewendet werden...
Beispiel: 4*(2 + 3 -5) + 1  -> 4 2 3 + 5 -* 1 +

Die Umsetzung des ganzen habe ich in Zügen von diesem Skript:
Umwandlung von Infix-in Postfixnotation

Hier geht es mir um die beseitigung dieser beschriebenen Fehler. Denn hier bekomm ich eine Exception das der String überschritten wurde.


----------



## Lenzen (11. Dez 2006)

Ich habe hier eine zusätzliche if Bedingung eingebracht um z.B. -2*-2 auch rechnen zu können. Für meine Zwecke macht der Rechner jetzt was er soll. 
Ich werde diesen Code nicht weiter entwickeln. Aber für eine Vorlage bei einem ähnlichen Problem, ist er sicher sehr hilfreich. -> Berechnungen wie: 5*(4+(5*(4+(7/8))+8)) stellen kein Problem für den Rechner mehr da.
Der Vollständigkeit halber hier meine Ergänzung in der Calc Klasse:


```
private String InfixToPostfix() {
        
        String Postfix = "";        
        boolean hasCharForInfix = true;
        /*
         * Solange bis versucht wird auf ein elem was nicht existiert
         * zuzugreifen
         */
        int i = 0;
        while (hasCharForInfix) {
            /* Ab hier begin für das Scannen des InfixAusdrucks */
            try {            	
                // pruefen auf negatives Vorzeichen
                if (((Character) infix.charAt(0)).equals('-')&& Postfix.length() == 0) {
                    ++i;
                    while ((isDigit(infix.charAt(i)) || isDot(infix.charAt(i)) || 
                                    infix.charAt(i) == 'E')) {
                        Postfix += infix.charAt(i) + "";
                        ++i;
                    }
                    Postfix += "s "; // vorzeichenbehaftet (signed)> s anhaengen           
                }
                if (isOperand(infix.charAt(i))&& // aendern des infixs: z.B. 3*-3 => 3*(-3)
                   (isOperand(infix.charAt(i+1)))&& infix.charAt(i+1) == '-'){                    
                    
                	//vorzeichenbehaftet und 2 Operatoren aufeinander
                	if(((Character) infix.charAt(0)).equals('-')){
                        String subs1[] = infix.split("\\-");
                	infix="-"+subs1[1]+"("+"-"+subs1[2]+")"; 
                    
                	}else{ //vorzeichenlos und 2 Operatoren aufeinander
                	String subs1[] = infix.split("\\-");
                	infix=subs1[0]+"("+"-"+subs1[1]+")";         
                    }
                }
                //pruefen, ob aktuelles Zeichen eine Zahl ist
                if (isDigit(infix.charAt(i))) {
                    Postfix += infix.charAt(i++); // mehr als eine Zahl vorhanden ####
                    while ((isDigit(infix.charAt(i)) || isDot(infix.charAt(i)) || infix.charAt(i) == 'E')) {
                        Postfix += infix.charAt(i) + "";
                        ++i;
                    }
                    Postfix += " ";
                    
                  // pruefen, ob aktuelles Zeichen eine oeffnende Klammer ist
                } else if (isOpenKlammer(infix.charAt(i))) {
                    operandenStack.push(infix.charAt(i++) + "");                    
                   
                    if (((Character) infix.charAt(i)).equals('-')) {
                        ++i;
                        while (i < this.infix.length() && (isDigit(infix.charAt(i))|| 
                        		isDot(infix.charAt(i)) || infix.charAt(i) == 'E')) {
                            Postfix += infix.charAt(i++) + ""; // mehr als eine Klammer vorhanden ###
                        }
                        Postfix += "s "; // vorzeichenbehaftet (signed)
                        if (((Character) infix.charAt(i)).equals(')')) {
                            operandenStack.pop();
                            ++i;
                        }
                    }

                  // pruefen, ob aktuelles Zeichen eine schliessende Klammer ist
                } else if (isClosedKlammer(infix.charAt(i))) {

                    while (!operandenStack.isEmpty() && !operandenStack.peek().equals("(")) {

                        Postfix += operandenStack.pop();
                    }
                    if (!operandenStack.isEmpty())
                        operandenStack.pop();
                    i++;
                    
                  // pruefen, ob aktuelles Zeichen ein Operand ist
                } else if (isOperand(infix.charAt(i))) {
                    try {
                        while (prio(infix.charAt(i)) <= prio(operandenStack.peek().charAt(0))) {
                            Postfix += operandenStack.pop();
                        }

                    } catch (EmptyStackException e) {                    	
                    	
                    }
                    operandenStack.push(infix.charAt(i++) + "");
                }

            } catch (StringIndexOutOfBoundsException e) {
                // Ende des Strings erreicht boolean wird geaendert
                hasCharForInfix = false;
            }
        }
        while (!operandenStack.isEmpty()) {
            Postfix += operandenStack.pop();
        }
        return Postfix;
    }
```

Ich danke hier allen die mir hier geholfen haben und hoffe, dass auch anderen durch diesen Beitrag etwas geholfen wird.


----------

