Kalkulator ONP - błędy/pusty stos

0

Nie jestem pewien czy chodzi o to, że jest pusty stos, a jeśli mam rację to dlaczego jest pusty ?

package giecmarcin;

import java.util.Stack;
import java.util.StringTokenizer;

public class Calculator {
	private String expression = "";
	private String expressionRNP;
	private String notNumbers = "+-*/^()";

	public Calculator() {

	}

	public Calculator(String expression) {
		this.expression = expression;
		expressionRNP = "";
		toRNP();
	}

	public String getExpression() {
		return expression;
	}

	public void setExpression(String expression) {
		this.expression += expression;
	}

	public String getExpressionRNP() {
		// calculate();
		return expressionRNP;
	}

	private static int priorityOfSigns(String oper) {
		if (oper.equals("+") || oper.equals("-")) {
			return 1;
		} else if (oper.equals("*") || oper.equals("/")) {
			return 2;
		} else if (oper.equals("^")) {
			return 3;
		} else {
			return 0;
		}

	}

	// zamiana wyrazenia na ONP
	private void toRNP() {
		Stack<String> stack = new Stack<String>();
		StringTokenizer st = new StringTokenizer(expression, "+-*/^()", true);
		while (st.hasMoreTokens()) {
			String s = st.nextToken();
			if (s.equals("+") || s.equals("-") || s.equals("*")
					|| s.equals("/") || s.equals("^")) {
				while (!stack.empty()
						&& priorityOfSigns(stack.peek()) >= priorityOfSigns(s)) {
					expressionRNP += stack.pop();
				}
				stack.push(s);
			} else if (s.equals("(")) {
				stack.push(s);
			} else if (s.equals(")")) {
				while (!stack.peek().equals("(")) {
					expressionRNP += stack.pop() + " ";
				}
				stack.pop();
			} else {
				expressionRNP += s + " ";
			}
			while (!stack.empty()) {
				expressionRNP += stack.pop() + " ";
			}
		}
	}

	public double Calculate() {
		String input = expressionRNP + " =";
		Stack<Double> stack = new Stack<Double>();// przechowuje wyniki pośrednie
		double a = 0;// przechowuje dane ze stosu
		double b = 0;// przechowuje dane ze stosu
		double result = 0;// wynik operacji arytmetycznej
		String build = "";
		String space = " ";
		char sp = ' ';
		int count = 0;
		do {// Krok 1: Czytaj el z we
			char czar = input.charAt(count);
			if (czar == '+' || czar == '-' || czar == '*' || czar == '/'
					|| czar == '^')// Krok 2: Jeśli el nie jest liczbą, to idź
									// do kroku 5
			{
				if (!stack.empty()) {
					b = stack.pop();// Krok 6: Pobierz ze stosu dwie liczby a i b
					a = stack.pop();
					if (czar == '+') {
						result = a + b;
					}// Krok 7: Wykonaj nad liczbami a i b operację określoną
						// przez el i umieść wynik w w
					else if (czar == '-') {
						result = a - b;
					} else if (czar == '*') {
						result = a * b;
					} else if (czar == '/') {
						result = a / b;
					} else if (czar == '^') {
						if (b == 0) {
							result = 1;
						} else {
							result = a;
							int licz = 1;
							while (licz < (int) b) {
								result *= result;
								licz++;
							}
						}
					}
					stack.push(result);// Krok 8: Umieść w na stosie
				}
			} else if (czar == sp)// Krok 3: Umieść el na stosie
			{
				if (build.compareTo("") != 0) {
					double tmp = Double.parseDouble(build);
					stack.push(tmp);
					build = "";
				}
			} else if (czar == '=')// Krok 5: Jeśli el jest znakiem '=', to idź
									// do kroku 10
			{
				if (!stack.empty()) {
					result = stack.pop();// Krok 10: Prześlij na wyjście zawartość
									// wierzchołka stosu
					break;
				}
			} else if (czar >= '0' && czar <= '9')// buduj liczbe
			{
				build += czar;
			}
			count++;
		} while (count < input.length());// Krok 4: Idź do kroku 1
		return result;
	}
}

<code/>

package giecmarcin;

import java.awt.;
import java.awt.event.
;
import java.util.ArrayList;

import javax.swing.*;

public class CalGui implements ActionListener {
//JTextArea jTAField;
JTextField jtfField;
JLabel jlabResult;
String line="";
CalGui(){
JFrame jfrm = new JFrame("Kalkulator");
jfrm.setLayout(new FlowLayout(FlowLayout.CENTER));
jfrm.setSize(250, 300);
jfrm.setResizable(false); //blokowanie rozmiaru okna
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panelNumbers = new JPanel(new GridLayout(3, 2));
JPanel panelOfSigns = new JPanel(new GridLayout(2,2));
JPanel panelOfResult = new JPanel(new GridLayout(1,2));

	jlabResult = new JLabel("Wynik");
	jtfField = new JTextField(20);
	//jTAField = new JTextArea(2,3);
	JButton btnCalc = new JButton("Oblicz");
	JButton[] tabBtnNumbers = new JButton[10]; 
	//tablica przyciskow
	ArrayList<JButton> tabBtnSigns = new ArrayList<JButton>();
	tabBtnSigns.add(new JButton("+"));
	tabBtnSigns.add(new JButton("-"));
	tabBtnSigns.add(new JButton("*"));
	tabBtnSigns.add(new JButton("/"));
	tabBtnSigns.add(new JButton("^"));
	tabBtnSigns.add(new JButton("."));
	tabBtnSigns.add(new JButton("("));
	tabBtnSigns.add(new JButton(")"));
	
	for(int i=0; i<tabBtnNumbers.length; i++){ 
		tabBtnNumbers[i] = new JButton(Integer.toString(i)); //Tworzenie przyciskow
		tabBtnNumbers[i].addActionListener(this); 	//Sluchacze dla przyciskow
	}
	//Sluchacz jfielda
	jtfField.addActionListener(this);
	btnCalc.addActionListener(this);
	//identyfikacja jtfField
	jtfField.setActionCommand("myJTFField");

	//Dodawanie do kontenera
	//jfrm.add(jTAField);
	jfrm.add(jtfField);
	//dodawanie przyciskow numerycznych do panelu
	for(int i=0; i<tabBtnNumbers.length; i++){
		panelNumbers.add(tabBtnNumbers[i]);
	}
	//Dodanie znakow do panelu
	for(int i=0; i<tabBtnSigns.size();i++){
		panelOfSigns.add(tabBtnSigns.get(i));
		tabBtnSigns.get(i).addActionListener(this);
	}
	panelOfResult.add(btnCalc);
	panelOfResult.add(jlabResult);
	
	jfrm.add(panelNumbers); //dodanie panelu z cyframi do ramki
	jfrm.add(panelOfSigns);
	jfrm.add(panelOfResult);
	//Wyswietlanie
	jfrm.setVisible(true);
}
//Obsluga zdarzen
@Override
public void actionPerformed(ActionEvent e) {
	Calculator calc = new Calculator(jtfField.getText());
	calc.setExpression(e.getActionCommand());
	jtfField.setText(calc.getExpression());	
	
	if(e.getActionCommand().equals("Oblicz")){
		calc.setExpression(calc.getExpression());
		jlabResult.setText(Double.toString(calc.Calculate()));
	}
}

public void keyReleased(KeyEvent e){
	int key = e.getKeyCode();
	if(e.getSource()==jtfField){
		if(key == KeyEvent.VK_ENTER){
			//jlabResult.setText(calc.getResult());
		}
	}
}

public static void main(String[] args){
	SwingUtilities.invokeLater(new Runnable() {
		@Override
		public void run() {
			new CalGui();
		}
	});
}

}


Błędy

Exception in thread "AWT-EventQueue-0" java.util.EmptyStackException
at java.util.Stack.peek(Stack.java:102)
at java.util.Stack.pop(Stack.java:84)
at giecmarcin.Calculator.Calculate(Calculator.java:94)
at giecmarcin.CalGui.actionPerformed(CalGui.java:80)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6505)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3312)
at java.awt.Component.processEvent(Component.java:6270)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:708)
at java.awt.EventQueue$4.run(EventQueue.java:706)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

0

Na szybko: sprawdzasz co prawda czy stos nie jest pusty ale potem ściągasz z niego 2 elementy. Skąd wiesz że na stosie nie ma tylko jednego elementu?

0

Próbuję to zrobić tak jak jest opisane tutaj: http://edu.i-lo.tarnow.pl/inf/alg/001_search/0102.php
Dla sprawdzenia czy działa po prostu chce wypisać wyrażenie w ONP, niestety nic się pojawia.
Lista kroków:
K01: Utwórz pusty stos S
K02: Czytaj c ; odczytujemy znak z wejścia
K03: Jeśli c ≠ '=', to idź do K08 ; sprawdzamy, czy koniec wyrażenia
K04: Dopóki S.empty() = false, wykonuj K05...K06
K05: Pisz S.top() ; na wyjście przesyłamy operatory ze stosu
K06: S.pop() ; przesłany operator usuwamy ze stosu
K07: Zakończ
K08: Jeśli c ≠ '(', to idź do K11 ; sprawdzamy, czy mamy nawias otwierający
K09: S.push('(') ; nawias otwierający umieszczamy na stosie
K10: Idź do K02 ; i kontynuujemy przetwarzanie wyrażenia
K11: Jeśli c ≠ ')', to idź do K17 ; sprawdzamy, czy mamy nawias zamykający
K12: Dopóki S.top() ≠ '(', wykonuj K13...K14
K13: Pisz S.top() ; ze stosu przesyłamy na wyjście operatory
K14: S.pop() ; aż do napotkania nawiasu otwierającego
K15: S.pop() ; usuwamy ze stosu nawias otwierający
K16: Idź do K02 ; i kontynuujemy przetwarzanie wyrażenia
K17: Jeśli c ≠ operator, to idź do K23 ; sprawdzamy, czy mamy operator
K18: Dopóki S.empty() = false p(S.top()) > p(c), wykonuj K19...K20
K19: Pisz S.top() ; na wyjście przesyłamy ze stosu operatory
K20: S.pop() ; o wyższych priorytetach
K21: S.push(c) ; operator umieszczamy na stosie
K22: Idź do K02 ; i kontynuujemy przetwarzanie wyrażenia
K23: Pisz c ; z przesyłamy na wyjście
K24: Idź do K02 ; i kontynuujemy przetwarzanie wyrażenia

Kod C++:

// Przekształcanie wyrażenia na ONP
// Data: 19.08.2012
// (C)2012 mgr Jerzy Wałaszek
//------------------------------

#include <iostream>

using namespace std;

const int S_MAX = 100; // rozmiar stosu operatorów

// Zwraca priorytet operatora
//---------------------------

int p(char c)
{
  switch(c)
  {
    case '+'     : ;
    case '-'     : return 1;
    case '*'     : ;
    case '/'     : return 2;
    case '^'     : return 3;
  }
  return 0;
}

//------------------------------------
// Tutaj rozpoczyna się program główny
//------------------------------------

int main()
{
  char S[S_MAX];                             // stos operatorów
  int sptr = 0;                              // wskaźnik stosu
  char c;                                    // kolejny znak wyrażenia

  while(true)
  {
    cin >> c;                                // czytamy znak z wejścia

    if(c == '=')                             // koniec wyrażenia?
    {
      while(sptr) cout << S[--sptr] << ' ';  // jeśli tak, na wyjście przesyłamy
                                             // wszystkie operatory ze stosu
      break;                                 // i przerywamy pętlę
    }

    switch(c)                                // analizujemy odczytany znak
    {
      case ' ' : break;                      // spację ignorujemy
      case '(' : S[sptr++] = '(';            // nawias otwierający zawsze na stos
                 break;
      case ')' : while(S[sptr-1] != '(')     // nawias zamykający
                 cout << S[--sptr] << ' ';   // ze stosu przesyłamy na wyjście
                                             // wszystkie operatory aż do nawiasu otw.
                 sptr--;                     // usuwamy ze stosu nawias otwierający
                 break;
      case '+' : ;                           // operator
      case '-' : ;
      case '*' : ;
      case '/' : ;
      case '^' : while(sptr && p(S[sptr-1]) > p(c))
                   cout << S[--sptr] << ' '; // na wyjście przesyłamy ze stosu wszystkie
                                             // operatory o wyższych priorytetach
                 S[sptr++] = c;              // operator umieszczamy na stosie
                 break;
      default:   cout << c << ' ';           // inaczej znak przesyłamy na wyjście
                 break;
    }
  }

  cout << endl;

  return 0;
} 

Mój kod w Javie:

package giecmarcin;

import java.util.Stack;
import java.util.StringTokenizer;

public class Notation {
	private String expression;
	private String expressionRNP;
	
	public Notation(String expression){
		this.expression = expression;
		toRNP();
	}
	private int priority(String oper){
		switch(oper){
		case "+": return 1;
		case "-": return 1;
		case "*": return 2;
		case "/": return 2;
		case "^": return 3;
		}
		return 0;
	}
	private void toRNP(){
		
		StringTokenizer st = new StringTokenizer(expression, "+-*/()", true);
		//Tworzymy stos na operatory
		Stack stack = new Stack();
		String input = ""; //wyjscie
		while(st.hasMoreTokens()){
			String ch = st.nextToken(); //czytamy pierwszy znak
			if(!ch.equals("=")){ //jeśli znak różny od =
				break;
			}
			
			switch(ch){
			case " ": break;
			case "(":
				stack.push("(");
				break;
			case ")": //nawias zamykajacy
				while(!stack.equals("(")){
					input += stack.peek(); //przesylamy na wyjscie wszystkie operatory az do nawiasu otwierajacego
					stack.removeElement("("); //usuwamy ze stosu nawias otwierajacy
				}
				break;
			case "+":;
			case "-":;
			case "*":;
			case "/":;
			case "^":
				//dodac pozniej
			default: 
				input += ch;
				break;
			}
		}
		expressionRNP = input;
	}
	public String getExpressionRNP(){
		return expressionRNP;
	}
}
			Notation nat = new Notation("(3+5)*2");
			System.out.println(nat.getExpressionRNP());
0

No i co? Odpal to pod debugerem, wykonuj krok po kroku i zobacz co sie kaszani. Nikt tego za ciebie nie zrobi.

0
String ch = st.nextToken(); //czytamy pierwszy znak
			if(!ch.equals("=")){ //jeśli znak różny od =
				break;

Wczytuję nawias (, przechodzi do if potem break i przeskakuję od razu do expressionRNP = input; i jak już dojdę na koniec metody to znika z debuggera całkiem zmienna ch. Jak jej deklarację przeniosłem na sam początek metody to też nic nie pomogło.

1

A czego się spodziewałeś niby? o_O break przerywa pętle while więc logiczne że skaczesz na jej koniec. Zmienna jest widziana tylko w zasięgu, więc jak deklarujesz ją wewnątrz pętli to za pętlą jej nie ma. Zresztą cały ten warunek jest bez sensu. Cokolwiek nie wpiszesz to przerywa pętlę. Na pewno nie mialo tam być ch.equals("=")? że przerywasz pętlę jak dostałeś =?

1 użytkowników online, w tym zalogowanych: 0, gości: 1