# Taschenrechner mit mehreren Rechnungen



## niklas551 (9. Okt 2018)

Hallo zusammen,
ich hab mich hier mal angemeldet, da ich ein wenig Hilfe benötige und ich durch googeln nicht weiter kam.
Zu meiner Situation:
Ich verwende Eclipse Photon Release (4.8.0) und baue meine GUI mit WidowBuilder Pro Version 1.9.1 (Download Link:https://www.eclipse.org/windowbuilder/download.php)
So... ich bin dabei einen Taschenrechner zu programmieren, der in der letzten Version, 1 zu 1 wie der Windows 10 Taschenrechner aussehen und funktionieren soll. Natürlich ist das Aussehen jetzt erstmal komplett egal.
Bisher habe ich eine ausreichende GUI erstellt. Zu den Knöpfen, habe ich ein Label(labFront), indem alle aktiven Zahlen hineingeschrieben werden und ein weiteres Label(labBack), indem alle Rechnungen hineingeschrieben erden sollen, bis man "=" drückt. Funktioniert fast wie bei dem Win10 Taschenrechner. Ich habe es auch schon geschafft, 2 Zaheln richtig zu berechnen...
Jedoch jetzt will ich mehrere Zahlen und Operatoren eingeben zb.: 4+15-3*2. Und da kommt mein Problem.. ich weiss nicht wie.... Meine Idee war es im Hintergrund immer das Ergebnis zu speichern (4+15 = 19 --> im Hintergund speichern... -3 = 16 im Hintergrund usw.) Habe es schon mit Arrays, Variablen überschreiben,.. versucht aber nie zum gewünschten Ergebnis gekommen. Hoffe es war einigermaßen verständlich erklärt und jemand kann mir weiterhelfen. Mir reicht es auch zu wissen, wie es mit Zahl 1 und dem Operator Plus funktioniert, den Rest übertrage ich auf die andren Funktionen Im Endeffekt: Er soll das gleiche machen wie der Win10 Taschenrechner...
Zum Code: https://pastebin.com/zg8PTwjN

Falls ihr noch mehr Infos benötigt einfach Fragen. Vielen Dank schonmal im Vorraus!

P.S. hoffe die Frage wurde noch nicht gestellt, weil hatte sie niergens gefunden


----------



## mihe7 (9. Okt 2018)

niklas551 hat gesagt.:


> Meine Idee war es im Hintergrund immer das Ergebnis zu speichern (4+15 = 19 --> im Hintergund speichern... -3 = 16 im Hintergrund usw.)


Und schon hast Du ein Problem, denn wenn auf -3 noch *16 folgt, musst Du erst -3*16 ausrechnen.

Wenn Du das wirklich selbst implementieren willst, musst Du den Ausdruck parsen und in einen abstrakten Syntaxbaum überführen. 

https://de.wikipedia.org/wiki/Abstrakter_Syntaxbaum
https://courses.cs.washington.edu/courses/cse373/17au/project1/project1-2.html



niklas551 hat gesagt.:


> P.S. hoffe die Frage wurde noch nicht gestellt, weil hatte sie niergens gefunden


Hm.. auf die Idee, einen Taschenrechner zu programmieren, sind bestimmt schon zwei, drei andere gekommen


----------



## Robat (9. Okt 2018)

Oder man nimmt eine fertige Library wie exp4j


----------



## niklas551 (9. Okt 2018)

Okay, hier nochmal mein Code: 
	
	
	
	





```
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.lang.invoke.LambdaConversionException;
import java.util.regex.Pattern;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Font;
import java.awt.Window;
import java.awt.Window.Type;
import java.awt.SystemColor;
import javax.swing.UIManager;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.JComboBox;
import java.awt.Panel;
import javax.swing.JLabel;
import javax.swing.JEditorPane;
import javax.swing.DropMode;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.JFormattedTextField;
import javax.swing.SwingConstants;


public class Calculator {

   private JFrame frmRechner;
   private JButton btnMinus;
   private JButton btnMal;
   private JButton btnTeilen;
   private JButton btnErgebnis;
   private JButton btnEins;
   private JButton btnZwei;
   private JButton btnDrei;
   private JButton btnVier;
   private JButton btnFuenf;
   private JButton btnSechs;
   private JButton btnSieben;
   private JButton btnAcht;
   private JButton btnNeun;
   private JButton btnNull;
   private JButton btnBack;
   private JLabel labBack;

   //Variablen
   double num;
   String a;
   int calc;
   String strOp;
   private JLabel labFront;
   
   public Calculator() {
       initialize();
   }

   //Sollte letzten 2 Eingaben ausgeben, nicht wirklich im Gebrauch
   public void Rechnen() {
       double ergGleich;
       switch(calc) {
       case 1:
           ergGleich = num + Double.parseDouble(labFront.getText());
           labFront.setText(Double.toString(ergGleich));
           labBack.setText("");
           break;
       case 2:
           ergGleich = num - Double.parseDouble(labFront.getText());
           labFront.setText(Double.toString(ergGleich));
           labBack.setText("");
           break;
       case 3:
           ergGleich = num * Double.parseDouble(labFront.getText());
           labFront.setText(Double.toString(ergGleich));
           labBack.setText("");
           break;
       case 4:
           ergGleich = num / Double.parseDouble(labFront.getText());
           labFront.setText(Double.toString(ergGleich));
           labBack.setText("");
           break;
       }
       
   }
   
   //Wenn Zahl gedrückt
   public void NumberPressed(String i){
   
   labFront.setText(labFront.getText() + i);
   
   }
   
   
   //Wenn Operator gedrückt
   public void OperatorPressed(String op) {
       double numb1 = 0, numb2, erg;
       
       numb2 = Double.parseDouble(labFront.getText()); //speichert Eingabe in Variable num2
   
       
       if(labBack.getText().endsWith("+")) { //Prüft ob ein Operator schon eingegeben ist
           numb1 += numb2; //Wert soll, wenn Operator schon eingegeben ist, an numb1 gegeben werden
           numb2 = Double.parseDouble(labFront.getText()); //Hier sollte dann 2.Zahl eingelesen werden
           erg = numb1 + numb2; //hier sollen dann Zahlen (in dem Fall addiert werden)
           labFront.setText(Double.toString(erg)); //Ergebnis wird ausgegeben
           labBack.setText(labBack.getText() + numb2 + op); //Zahl mit Operator in Hintergrund geschrieben
       }
       else { //Soll passieren wenn noch noch kein Operator vorher eingeben wurde
           labBack.setText(labBack.getText() + numb2 + op);
           labFront.setText("");
       }
       
       }
       
       private void initialize() {
       frmRechner = new JFrame();
       frmRechner.getContentPane().setForeground(new Color(0, 0, 0));
       frmRechner.setBackground(SystemColor.controlHighlight);
       frmRechner.setForeground(Color.LIGHT_GRAY);
       frmRechner.setTitle("Rechner");
       frmRechner.getContentPane().setBackground(UIManager.getColor("menu"));
       frmRechner.setBounds(100, 100, 320, 510);
       frmRechner.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frmRechner.getContentPane().setLayout(null);
       
       //Knopf addieren (+)
       JButton btnAddieren = new JButton("+");
       btnAddieren.setFont(new Font("Tahoma", Font.PLAIN, 15));
       btnAddieren.setBackground(SystemColor.controlHighlight);
       btnAddieren.setForeground(Color.BLACK);
       btnAddieren.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent arg0) {
               calc = 1;
               OperatorPressed(btnAddieren.getText());
               
           }
       });
       btnAddieren.setBounds(220, 350, 70, 40);
       frmRechner.getContentPane().add(btnAddieren);
       
       //Knopf Subtrahieren (-)
       btnMinus = new JButton("-");
       btnMinus.setFont(new Font("Tahoma", Font.PLAIN, 15));
       btnMinus.setBackground(SystemColor.controlHighlight);
       btnMinus.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               calc = 2;
               OperatorPressed(btnMinus.getText());
           }
       });
       btnMinus.setBounds(220, 310, 70, 40);
       frmRechner.getContentPane().add(btnMinus);
       
       //Knopf Multiplizieren (*)
       btnMal = new JButton("*");
       btnMal.setFont(new Font("Tahoma", Font.PLAIN, 15));
       btnMal.setBackground(SystemColor.controlHighlight);
       btnMal.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               strOp = btnMal.getText();
               OperatorPressed(btnMal.getText());
           }
       });
       btnMal.setBounds(220, 270, 70, 40);
       frmRechner.getContentPane().add(btnMal);
       
       //Knopf Dividieren (/)
       btnTeilen = new JButton("/");
       btnTeilen.setFont(new Font("Tahoma", Font.PLAIN, 15));
       btnTeilen.setBackground(SystemColor.controlHighlight);
       btnTeilen.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               strOp = btnTeilen.getText();
               OperatorPressed(btnTeilen.getText());
           }
       });
       btnTeilen.setBounds(220, 230, 70, 40);
       frmRechner.getContentPane().add(btnTeilen);
       
       //Knopf Ergebnis (=)
       btnErgebnis = new JButton("=");
       btnErgebnis.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               Rechnen();
               
           }
       });
       btnErgebnis.setBackground(SystemColor.controlHighlight);
       btnErgebnis.setBounds(220, 390, 70, 40);
       frmRechner.getContentPane().add(btnErgebnis);
       
       //Knopf Eins (1)
       btnEins = new JButton("1");
       btnEins.setForeground(new Color(0, 0, 0));
       btnEins.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent arg0) {
               NumberPressed(btnEins.getText());
               
           }
       });
       btnEins.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnEins.setBackground(SystemColor.text);
       btnEins.setBounds(10, 350, 70, 40);
       frmRechner.getContentPane().add(btnEins);
       
       btnZwei = new JButton("2");
       btnZwei.setBounds(80, 350, 70, 40);
       frmRechner.getContentPane().add(btnZwei);
       btnZwei.setForeground(new Color(0, 0, 0));
       btnZwei.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent arg0) {
               NumberPressed(btnZwei.getText());
               
           }
       });
       btnZwei.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnZwei.setBackground(SystemColor.text);
       
       //Knopf Drei (3)
       btnDrei = new JButton("3");
       btnDrei.setForeground(new Color(0, 0, 0));
       btnDrei.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               NumberPressed(btnDrei.getText());
           
           }
       });
       btnDrei.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnDrei.setBackground(SystemColor.text);
       btnDrei.setBounds(150, 350, 70, 40);
       frmRechner.getContentPane().add(btnDrei);
       
       //Knopf Vier (4)
       btnVier = new JButton("4");
       btnVier.setForeground(new Color(0, 0, 0));
       btnVier.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               NumberPressed(btnVier.getText());
               
           }
       });
       btnVier.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnVier.setBackground(SystemColor.text);
       btnVier.setBounds(10, 310, 70, 40);
       frmRechner.getContentPane().add(btnVier);
       
       //Knopf Fünf (5)
       btnFuenf = new JButton("5");
       btnFuenf.setForeground(new Color(0, 0, 0));
       btnFuenf.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               NumberPressed(btnFuenf.getText());
               
           }
       });
       btnFuenf.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnFuenf.setBackground(SystemColor.text);
       btnFuenf.setBounds(80, 310, 70, 40);
       frmRechner.getContentPane().add(btnFuenf);
       
       //Knopf Sechs (6)
       btnSechs = new JButton("6");
       btnSechs.setForeground(new Color(0, 0, 0));
       btnSechs.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               NumberPressed(btnSechs.getText());
               
           }
       });
       btnSechs.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnSechs.setBackground(SystemColor.text);
       btnSechs.setBounds(150, 310, 70, 40);
       frmRechner.getContentPane().add(btnSechs);
       
       //Knopf Sieben
       btnSieben = new JButton("7");
       btnSieben.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               NumberPressed(btnSieben.getText());
               
           }
       });
       btnSieben.setForeground(new Color(0, 0, 0));
       btnSieben.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnSieben.setBackground(SystemColor.text);
       btnSieben.setBounds(10, 270, 70, 40);
       frmRechner.getContentPane().add(btnSieben);
       
       //Knopf Acht (8)
       btnAcht = new JButton("8");
       btnAcht.setForeground(new Color(0, 0, 0));
       btnAcht.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               NumberPressed(btnAcht.getText());
               
           }
       });
       btnAcht.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnAcht.setBackground(SystemColor.text);
       btnAcht.setBounds(80, 270, 70, 40);
       frmRechner.getContentPane().add(btnAcht);
       
       //Knopf Neun (9)
       btnNeun = new JButton("9");
       btnNeun.setForeground(new Color(0, 0, 0));
       btnNeun.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent arg0) {
               NumberPressed(btnNeun.getText());
               
           }
       });
       btnNeun.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnNeun.setBackground(SystemColor.text);
       btnNeun.setBounds(150, 270, 70, 40);
       frmRechner.getContentPane().add(btnNeun);
       
       //Knopf Null (0)
       btnNull = new JButton("0");
       btnNull.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent arg0) {
               NumberPressed(btnNull.getText());
               
           }
       });
       btnNull.setFont(new Font("Tahoma", Font.BOLD, 20));
       btnNull.setBackground(SystemColor.text);
       btnNull.setBounds(80, 390, 70, 40);
       frmRechner.getContentPane().add(btnNull);
       
       //Knopf Clear
       JButton btnClear = new JButton("C");
       btnClear.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               labBack.setText("");
               labFront.setText("");
           }
       });
       btnClear.setForeground(Color.BLACK);
       btnClear.setFont(new Font("Tahoma", Font.PLAIN, 15));
       btnClear.setBackground(SystemColor.controlHighlight);
       btnClear.setBounds(80, 230, 70, 40);
       frmRechner.getContentPane().add(btnClear);
       
       btnBack = new JButton("<--");
       btnBack.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               int lenght = labFront.getText().length();
               int number = labFront.getText().length() - 1;
               String store;
               
               if(lenght > 0) {
                   StringBuilder back = new StringBuilder(labFront.getText());
                   back.deleteCharAt(number); //Schrittweise -1
                   store = back.toString(); //,,back'' muss wieder in String gewandelt werden
                   labFront.setText(store); //gibt ,,store'' wieder in Text
               }
               
           }
       });
       btnBack.setForeground(Color.BLACK);
       btnBack.setFont(new Font("Tahoma", Font.PLAIN, 15));
       btnBack.setBackground(SystemColor.controlHighlight);
       btnBack.setBounds(150, 230, 70, 40);
       frmRechner.getContentPane().add(btnBack);
       
       
       
       
       //Knopf Vorzeichen ändern (+/-)
       JButton button = new JButton("+/-");
       button.setBackground(SystemColor.controlHighlight);
       button.setBounds(10, 390, 70, 40);
       frmRechner.getContentPane().add(button);
       
       //Knopf Komma setzten (,)
       JButton btnKomma = new JButton(",");
       btnKomma.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent arg0) {
               labFront.setText(labFront.getText() + ".");
           }
       });
       btnKomma.setForeground(Color.BLACK);
       btnKomma.setFont(new Font("Tahoma", Font.BOLD, 15));
       btnKomma.setBackground(SystemColor.controlHighlight);
       btnKomma.setBounds(150, 390, 70, 40);
       frmRechner.getContentPane().add(btnKomma);
       
       //Knopf ClearEntry löschen letzter Eingabe(CE)
       JButton btnClearEntry = new JButton("CE");
       btnClearEntry.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent arg0) {
               labFront.setText("");
           }
       });
       btnClearEntry.setForeground(Color.BLACK);
       btnClearEntry.setFont(new Font("Tahoma", Font.PLAIN, 15));
       btnClearEntry.setBackground(SystemColor.controlHighlight);
       btnClearEntry.setBounds(10, 230, 70, 40);
       frmRechner.getContentPane().add(btnClearEntry);
       
       labBack = new JLabel("");
       labBack.setFont(new Font("Tahoma", Font.PLAIN, 12));
       labBack.setVerticalAlignment(SwingConstants.TOP);
       labBack.setHorizontalAlignment(SwingConstants.RIGHT);
       labBack.setBounds(0, 54, 304, 67);
       frmRechner.getContentPane().add(labBack);
       
       labFront = new JLabel("");
       labFront.setFont(new Font("Tahoma", Font.PLAIN, 18));
       labFront.setBackground(SystemColor.info);
       labFront.setHorizontalAlignment(SwingConstants.RIGHT);
       labFront.setBounds(0, 70, 304, 104);
       frmRechner.getContentPane().add(labFront);
       
       
       
   }
   public static void main(String[] args) {
       
       EventQueue.invokeLater(new Runnable() {
           public void run() {
               try {
                   Calculator window = new Calculator();
                   window.frmRechner.setVisible(true);
               } catch (Exception e) {
                   e.printStackTrace();
               }
           }
       });
   }
   
}
```

Vielleicht hab ich vergessen zu sagen, das in der ersten Version nicht auf Punkt-Vor Strich geachtet werden muss. Heißt ein riesen Problem weniger.. Grundsätzlich bräuchte ich nur Hilfe im Zwischenspeichern der Variablen... Das alles erschwert durch die GUI (noch nie zuvor damit gearbeitet, heißt erstes Projekt)

Danke schonmal für die sehr schnellen Antworten, freut mich


----------



## Robat (9. Okt 2018)

niklas551 hat gesagt.:


> Das alles erschwert durch die GUI


Dem eigentlichen Rechenalgorithmus sollte eigentlich egal sein woher die Daten stammen bzw wo sie ausgegeben werden sollen. Du solltest Eingabe/Verarbeitung/Ausgabe strickt von einander trennen - macht sich auch für das Verständnis besser.



niklas551 hat gesagt.:


> Vielleicht hab ich vergessen zu sagen, das in der ersten Version nicht auf Punkt-Vor Strich geachtet werden muss


Dann würde ich dennoch den Weg über einen Parser gehen (siehe Beitrag von @mihe7 ). Warum würdest du jetzt ein Teilfeature implementieren wollen um es später noch mal anders implementieren zu müssen. Dann doch lieber gleich "richtig" machen und später den Parser nur um die Rechenregeln erweitern


----------



## mihe7 (9. Okt 2018)

niklas551 hat gesagt.:


> Das alles erschwert durch die GUI


Nicht nur deswegen trennt man Logik vom UI...

Das UI brauchst Du erstmal gar nicht. Für den Taschenrechner Version 1 reicht ein Modell, das einzelne "Eingaben" verarbeitet. Im ersten Schritt solltest Du mal davon ausgehen, dass Du wirklich Zahlen erhältst, das vereinfacht die Sache etwas. 

Das Modell speichert ein Ergebnis und einen Operator. Es hat zwei Invarianten:
1. es gibt immer ein Ergebnis, das den Stand der vergangenen Berechnungen darstellt.
2. es muss ein Operator existieren, bevor das Modell eine Zahl erhalten darf.

Um diese durchzusetzen, fängst Du mit einem Ergebnis 0 und dem "+"-Operator an. Wenn das Modell eine Zahl erhält, muss sichergestellt werden, dass der Operator im Modell gesetzt ist. Dann wird der Operator auf das bisherige Ergebnis und die neu erhaltene Zahl angewendet. Das Resultat stellt das neue Ergebnis des Modells dar. Der Operator wird hinterher entfernt.

Jetzt musst Du Dich halt Schritt für Schritt an das Ziel rantasten.


----------



## niklas551 (10. Okt 2018)

Das klingt alles nicht schlecht... und danke nochmal für die antworten!!
Habe das ganze jetzt mit einem Parser versucht 
	
	
	
	





```
public String Parsing(String input) {
       List<Integer> zahlen = new ArrayList<>();
       List<Character> operatoren = new ArrayList<>();
       //1.Liste für zahlen, 2.Liste für Operatoren zu speichern
       
       String kurzInput = input.replaceAll(" ", "");
       //Ersetzt im String alle Operatoren mit ";"
       
       kurzInput = input.replaceAll("\\+", ";");
       kurzInput = input.replaceAll("\\-", ";");
       kurzInput = input.replaceAll("\\*", ";");
       kurzInput = input.replaceAll("/", ";");
       try {
       //Erzeugt Array und splittet String input an allen ";"
       String[] zahlenArr = kurzInput.split(";");
       for(int i = 0; i < zahlenArr.length; i++) {   //liest einzelne Zahlen in Array ein
           zahlen.add(Integer.parseInt(zahlenArr[i]));
       }
       }
       catch(Exception ex) {
           labFront.setText("Fehler");
       }
       
       for(int i = 0; i < input.length(); i++) {
           char op = input.charAt(i);
           if(op == '+' || op == '-' || op == '*' || op == '/'){
               operatoren.add(op);
           }
       }
       
       double result = 0;
       
       for(char operator : operatoren) {
           int operatorIndex = operatoren.indexOf(operator);
           double num1 = zahlen.get(operatorIndex);
           double num2 = zahlen.get(operatorIndex + 1);
           
           if(operatorIndex == 0) {
               switch(operator) {
               case '+':
                   result = num1 + num2;
                   break;
               case '-':
                   result = num1 - num2;
                   break;
               case '*':
                   result = num1 * num2;
                   break;
               case '/':
                   result = num1 / num2;
                   break;
               default:
                   result = 0;
                   break;
               }
           }
           else {
               switch(operator) {
               case '+':
                   result += num2;
                   break;
               case '-':
                   result -= num2;
                   break;
               case '*':
                   result *= num2;
                   break;
               case '/':
                   result /= num2;
                   break;
               default:
                   result = 0;
                   break;
               }   
           }   
       }
       
       return Double.toString(result);
       
   }
```

Funktioniert noch nicht ganz, aber glaube bin auf dem richtigen Weg


----------



## MoxxiManagarm (10. Okt 2018)

```
String[] zahlenArr = kurzInput.split("[\\+\\-\\*/]");
```
split verwendet regular Expression. Das Ersetzen zuvor ist nicht sinnvoll. Muss - wirklich escaped werden? *grübel*


```
catch(NumberFormatException ex) {
```

Bitte fange die genaue Exception ab. In deinem Fall NumberFormatException.


```
double left = (operatorIndex != 0) ? result : zahlen.get(operatorIndex);
double right = zahlen.get(operatorIndex + 1);
switch(operator) {
case '+':
    result = left + right;
    break;
```

Spare dir die Codeverdopplung.


```
public String parse(String input) {
```

Bitte schreibe Methodennamen immer klein.


----------



## Robat (10. Okt 2018)

MoxxiManagarm hat gesagt.:


> Muss - wirklich escaped werden? *grübel*


Afaik: In einer "character class" (also zwischen [] ) muss man es escapen, wenn es nicht am Anfang oder Ende steht. Ansonsten muss man es nicht escapen.


----------



## niklas551 (10. Okt 2018)

WOW, funktioniert direkt besser also 2 Zahlen kann ich schon problemlos eingeben. Jetzt wird es natürlich bei mehreren aufeinanderfolgenden Rechnungen schon schwieriger.
Und ja, Methodenname groß hatte ich noch von C# im Kopf *huups*


----------



## mihe7 (10. Okt 2018)

niklas551 hat gesagt.:


> Jetzt wird es natürlich bei mehreren aufeinanderfolgenden Rechnungen schon schwieriger.


Wenn Du die Lösung von @MoxxiManagarm nimmst, sollte das bereits funktionieren. Schau Dir mal an, was bei ihm "left" ist.


----------



## niklas551 (10. Okt 2018)

Aaaalso, meine Überlegung jetzt:
String Eingabe: Bsp.: 10+35-6*3
Ich habe 2 Listen. 1.zList für die Zahlen und 2.oList für die Operatoren
Ich hole dann alle Zahlen und speicher sie in zList und alle Operatoren in oList...
Dann will ich auf die 1.Stelle von oList prüfen ob +-*/ und dementsprechend die 1.Stelle und 2.Stelle von zList miteinander verrechnen. Mit diesem Ergebnis dann weiterrechnen. Heißt prüft 2.Stelle von oList und verrechnet dementsprechend das Ergebnis mit der 3.Stelle von zList usw... So hab ich mir das jetzt mal gedacht, was nicht alzu komplex ist (denke ich/hoffe ich), aber ich tu mir da Codemäßig ein wenig schwer
Hier einmal mein Code bisher (natürlich funktioniert er nicht) 


Spoiler: parsingCode





```
public String parsing(String input) {
        List<Double> zahlen = new ArrayList<Double>();
        List<Character> operatoren = new ArrayList<Character>();
        //1.Liste für zahlen, 2.Liste für Operatoren zu speichern
       
        String kurzInput = input.replaceAll(" ", "");
       
        //Erzeugt Array und splittet String input an allen Operatoren
        String[] zahlenArr = kurzInput.split("[\\+\\-\\*/]");
        for(int i = 0; i < zahlenArr.length; i++) {    //liest einzelne Zahlen in Array ein
            zahlen.add(Double.parseDouble(zahlenArr[i]));
        }
       
        for(int i = 0; i < input.length(); i++) {
            char op = input.charAt(i);
            if(op == '+' || op == '-' || op == '*' || op == '/'){
                operatoren.add(op);

            }
        }
        double ergebnis = 0;
        for(int i= 0; i < zahlenArr.length; i++) {
        for(int j = 0; i <= input.length(); j++)   
            if(operatoren.indexOf(j) == '+') {
                ergebnis = zahlen.indexOf(i) + zahlen.indexOf(i + 1);
                labTest.setText(Double.toString(ergebnis));
            }
            else if(operatoren.indexOf(j) == '-') {
                ergebnis = zahlen.indexOf(i) - zahlen.indexOf(i + 1);
            }
            else if(operatoren.indexOf(j) == '*') {
                ergebnis = zahlen.indexOf(i) * zahlen.indexOf(i + 1);
            }
            else if(operatoren.indexOf(j) == '/') {
                ergebnis = zahlen.indexOf(i) / zahlen.indexOf(i + 1);
            }
       
        }
       
       
       
        return Double.toString(ergebnis);
```


----------



## MoxxiManagarm (10. Okt 2018)

@mihe7 Ich bin weiblich ^^


```
zahlen.add(Double.parseDouble(zahlenArr[i]));
```
Die NumberFormatException solltest du schon abfangen oder werfen.


```
if(op == '+' || op == '-' || op == '*' || op == '/')
```
Nichts verkehrt, aber in Hinblick auf spätere weitere Operatoren empfehle ich eher sowas:

```
Arrays.asList('+', '-', '*', '/').contains(op)
```
Deine oder-'Liste' könnte sonst ziemlich lang werden.


```
operatoren.indexOf(j)
```
Sollte das nicht ein List::get sein?

Ich bin noch verwirrt warum du auf einmal 2 Schleifen hast, erkenne das Ziel dahinter nicht und bezweifle, dass das richtig ist. Vorher sah es richtiger aus. Du rechnest nun auch immer mit 2 zahlen aus dem Array und nicht mehr mit dem Vorergebnis.


----------



## MoxxiManagarm (10. Okt 2018)

Kleines Beispiel wie es aussehen könnte. Allerdings ist das Beispiel nun auch quick&dirty. Bitte entsprechendes Fehlerhandling ergänzen:


```
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.DoubleBinaryOperator;
import java.util.stream.Collectors;

public class SimpleExpressionParser {
    private static final Map<Character, DoubleBinaryOperator> OPERATIONS = new HashMap<>();
    static {
        OPERATIONS.put('+', (o1, o2) -> o1 + o2);
        OPERATIONS.put('-', (o1, o2) -> o1 - o2);
        OPERATIONS.put('*', (o1, o2) -> o1 * o2);
        OPERATIONS.put('/', (o1, o2) -> o1 / o2);
    }
 
    public static void main(String... args) {
        String expression = "3+4-6*5";
     
        List<Double> operants = Arrays.stream(expression.split("[\\+\\*\\-/]")) // hier auch keySet verwenden
                .map(o -> Double.parseDouble(o))
                .collect(Collectors.toList());
     
        List<Character> operators = expression.chars()
                .mapToObj(c -> (char)c)
                .filter(c -> OPERATIONS.keySet().contains(c))
                .collect(Collectors.toList());
     
        double result = operants.get(0);
     
        for(int i = 0; i < operators.size(); i++) {
            double nextOperant = operants.get(i + 1);
            char operator = operators.get(i);
         
            result = OPERATIONS.get(operator).applyAsDouble(result, nextOperant);
        }
     
        System.out.println(expression + "=" + result);
    }
}
```


----------



## niklas551 (10. Okt 2018)

Okay, erstmal vielen Dank für deine Hilfe!!
Dein Code funktioniert auf alle Fälle schonmal, ich versuch diesen jetzt mal etwas ,,simpler'' umzuschreiben denn vieles habe ich noch nie davon gelesen
Aber auf jedenfall eine gute Hilfe auf dem Weg zum Erfolg


----------



## mihe7 (10. Okt 2018)

MoxxiManagarm hat gesagt.:


> Ich bin weiblich ^^


----------



## niklas551 (10. Okt 2018)

MoxxiManagarm hat gesagt.:


> ```
> import java.util.Arrays;
> import java.util.HashMap;
> import java.util.List;
> ...




Oke, also muss leider gestehen, das mir dein Code eeetwas zu kompliziert ist... Macht für viele sicher Sinn, bin jedoch eher noch ein blutiger Anfänger und versteh das wenig bis gar nichts


----------



## MoxxiManagarm (10. Okt 2018)

Habs umgeschrieben, aber das Beibehalten der Map empfehle ich weiterhin aufgrund der Erweiterbarkeit durch weitere Operatoren.


```
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.DoubleBinaryOperator;

public class SimpleExpressionParser {   
    private static SimpleExpressionParser instance;
       
    private final Map<Character, DoubleBinaryOperator> registeredOperations;
    private final String regex;
   
    private SimpleExpressionParser() {
        registeredOperations = new HashMap<>();
       
        // when adding operations, change here
        registeredOperations.put('+', (o1, o2) -> o1 + o2);
        registeredOperations.put('-', (o1, o2) -> o1 - o2);
        registeredOperations.put('*', (o1, o2) -> o1 * o2);
        registeredOperations.put('/', (o1, o2) -> o1 / o2);
       
        // build regular expression dynamically
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        registeredOperations.keySet().forEach(sb::append);
        sb.append("]");
        regex = sb.toString();
    }
   
    // singleton Pattern
    public static SimpleExpressionParser getInstance() {
        if(instance == null) {
            instance = new SimpleExpressionParser();
        }
       
        return instance;
    }
   
    // the parsing semantic
    public double evaluate(String expression) {
        // retrieve numbers of the expression
        List<Double> numbers = new ArrayList<>();
        for(String token : expression.split(regex)) {
            numbers.add(Double.parseDouble(token));
        }

        // retrieve operators of the expression
        List<Character> operators = new ArrayList<>();
        for(int i = 0; i < expression.length(); i++) {
            char c = expression.charAt(i);
            if(registeredOperations.keySet().contains(c)) {
                operators.add(c);
            }
        }
       
        // calculate
        double result = numbers.get(0);
        for(int i = 0; i < operators.size(); i++) {
            double nextNumber = numbers.get(i + 1);
            char operator = operators.get(i);
           
            result = registeredOperations.get(operator).applyAsDouble(result, nextNumber);
        }
       
        return result;
    }
   
    public static void main(String... args) {
        String expression = "3+4-6*8";
        double result = SimpleExpressionParser.getInstance().evaluate(expression);
       
        System.out.println(expression + "=" + result);
    }
}
```


----------



## niklas551 (11. Okt 2018)

okay, hast dein Text anscheinend nochmal geändert, weil er sieht auf jedenfall mehr komplexer aus als gestern. Aber habe jetzt dein vereinfachten Code von gestern und habe diesen mal genommen
Jetzt bin ich soweit durch und muss sagen, es läuft
Eine einzige Sache, welche mir fehl müsste jedoch noch implementiert werden und zwar, wenn ich 10 + 10 eingebe, dann kein Gleichheitszeichen drücke, sondern nochmal einen Operator um eine weitere Rechnung dazuzurechnen, sollte er jetzt schon das Ergebnis von 10 + 10 ausgeben... Siehe Win10 Taschenrechner.. Im Hintergunde steht die Rechnung, im Vordergrund die Teilergebnisse, sowie das gesame Ergebnis wenn man das Gleichheitszeichen betätigt
Gruß und nochmals ein dickes Dankeschön!


----------

