2

所以我的任务是设计一个简单的 GUI 计算器,使用堆栈数据结构来执行加法、减法、乘法和除法。计算器窗口应至少有两个面板 - 一个用于显示,另一个用于按钮(0 - 9、. 、+、-、X、/、=、C)。输入表达式后,将显示其后缀或前缀,然后显示结果。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.Stack;

public class JCalculator implements ActionListener {
JFrame jfrm;
JFrame jfrm2;
JTextField txt;
JLabel results;
String str = "";
Stack operands = new Stack();
char[] a = new char[0];
int used = 0;



JCalculator(){
    jfrm = new JFrame("JCalc");
    jfrm.getContentPane().setLayout(new GridLayout(0,1));
    jfrm.setSize(210,210);

   results = new JLabel("",SwingConstants.RIGHT);
   jfrm.getContentPane().add(results);
   jfrm.setLocation(400,300);
   jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

   JButton[] calbut= new JButton[14];
   String []but = {"7","8","9","/","4","5","6","*","1","2","3","-","0","C"
   };
   JButton equal = new JButton("=");
   JButton add = new JButton("+");

   JPanel jbutton = new JPanel();
   jbutton.setLayout(new GridLayout(4,3));
   for(int i=0; i< but.length;i++){
       jbutton.add(calbut[i] = new JButton(but[i]));

       calbut[i].addActionListener(this);
   }
   jbutton.add(equal);
   jbutton.add(add);

   equal.addActionListener(this);
   add.addActionListener(this);

   jfrm.getContentPane().add(jbutton);


    jfrm.setVisible(true);
}
public void actionPerformed(ActionEvent ae){
    char[] a = new char[0];
    int used = 0;
    if(used == a.length){
        char[] newa= new char[a.length + 1];
        for(int i = 0; i <used; i++) newa[i]= a[i];
        a= newa;
    }

    if(ae.getActionCommand().equals("1")){
        str = results.getText();
        results.setText(str + "1");
        operands.push(1);
    }
    if(ae.getActionCommand().equals("2")){
        str = results.getText();
        results.setText(str + "2");
        operands.push(2);
    }
    if(ae.getActionCommand().equals("3")){
        str = results.getText();
        results.setText(str + "3");
        operands.push(3);
    }
    if(ae.getActionCommand().equals("4")){
        str = results.getText();
        results.setText(str + "4");
        operands.push(4);
    }
    if(ae.getActionCommand().equals("5")){
        str = results.getText();
        results.setText(str + "5");
        operands.push(5);
    }
    if(ae.getActionCommand().equals("6")){
        str = results.getText();
        results.setText(str + "6");
        operands.push(6);
    }
    if(ae.getActionCommand().equals("7")){
        str = results.getText();
        results.setText(str + "7");
        operands.push(7);
    }
    if(ae.getActionCommand().equals("8")){
        str = results.getText();
        results.setText(str + "8");
        operands.push(8);
    }
    if(ae.getActionCommand().equals("9")){
        str = results.getText();
        results.setText(str + "9");
        operands.push(9);
    }
    if (ae.getActionCommand().equals("0")) {
        str = results.getText();
        results.setText(str + "0");
        operands.push(0);
    }
    if(ae.getActionCommand().equals("+")){
        str = results.getText();
        double operand = Double.parseDouble(str);
        operands.push(operand);
        results.setText("");
        a[used]= '+';
        used++;

    }
    if(ae.getActionCommand().equals("-")){
        str = results.getText();
        double operand = Double.parseDouble(str);
        operands.push(operand);
        results.setText("");
        a[used]= '+';
        used++;
    }
    if(ae.getActionCommand().equals("/")){
        str = results.getText();
        double operand = Double.parseDouble(str);
        operands.push(operand);
        results.setText("");
        a[used]= '+';
        used++;
    }
    if(ae.getActionCommand().equals("*")){
        str = results.getText();
        double operand = Double.parseDouble(str);
        operands.push(operand);
        results.setText("");
        a[used]= '*';
        used++;
    }
    if(ae.getActionCommand().equals("=")){

        for(int i = 0; i< used; i++){
           performBinaryOp(a[i]);
        }

        str = String.valueOf(operands.pop());
        results.setText(str);
    }


}
 public void performBinaryOp(char nextOperation) {
     double leftOperand, rightOperand;
    Double result = new Double(0);
    rightOperand = (Double) operands.pop();
    leftOperand = (Double) operands.pop();
    switch (nextOperation) {
        case '+':
            result = new Double(leftOperand + rightOperand);
            break;
        case '-':
            result = new Double(leftOperand - rightOperand);
            break;
        case '*':
            result = new Double(leftOperand * rightOperand);
            break;
        case '/':
            result = new Double(leftOperand / rightOperand);
            break;
    }
    operands.push(result);
}

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

我遇到的错误是按下等号按钮时,例如按下 2+3= 它返回第一个值 2.0 然后我收到一条错误消息:

Exception in thread "AWT-EventQueue-0" java.util.EmptyStackException
at java.util.Stack.peek(Unknown Source)
at java.util.Stack.pop(Unknown Source)
at JCalculator.actionPerformed(JCalculator.java:152)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

我很确定我的问题是我有一个空堆栈,但我不确定代码哪里出错或如何修复它,所以任何帮助将不胜感激。

4

3 回答 3

3

我建议您将 Swing 和 UI 放在一边,直到您的计算器正常工作。创建一个单独的 Calculator 类,它可以接收文本字符串并对其进行评估。一旦你有这个工作,然后添加一个用户界面。

是的,您遇到了堆栈问题,正如异常告诉您的那样:

at JCalculator.actionPerformed(JCalculator.java:152)

在文本编辑器中打开您的 JCalculator,打开行号显示,然后转到第 152 行。这就是您的问题所在。

我不愿意通读您发布的代码,但我想说使用调试器快速旋转应该很快就能清除它。

于 2012-04-10T01:32:31.933 回答
1

您的actionPerformed()方法隐藏了一些类变量;请注意,您已经重新声明了char [] aand int used,因此您的代码几乎肯定不会像您预期的那样运行。我还没有按照这个得出合乎逻辑的结论。

public class JCalculator implements ActionListener {
JFrame jfrm;
JFrame jfrm2;
JTextField txt;
JLabel results;
String str = "";
Stack operands = new Stack();
char[] a = new char[0];
int used = 0;
/* ... */
public void actionPerformed(ActionEvent ae){
    char[] a = new char[0];
    int used = 0;
    if(used == a.length){
        char[] newa= new char[a.length + 1];
        for(int i = 0; i <used; i++) newa[i]= a[i];
        a= newa;
    }

这段代码让我觉得你不接受两位数:

if(ae.getActionCommand().equals("1")){
    str = results.getText();
    results.setText(str + "1");
    operands.push(1);
}

operands.push(1)可能需要推送正在构建的数字而不仅仅是最近的数字。(当然,如果您的意图是只支持一位数,这看起来没问题。)

我建议尝试if用一个函数替换这十个小语句。花时间在这里找出一个函数是非常值得的,它将大大简化将来对这段代码的维护,并且技能是至关重要的。(我想建议你JButton早点考虑一下你的整洁初始化——并尝试在你的替换函数中使用数组。这可能不是最好的,但应该没问题。)

if(ae.getActionCommand().equals("/")){
    str = results.getText();
    double operand = Double.parseDouble(str);
    operands.push(operand);
    results.setText("");
    a[used]= '+';
    used++;
}

你会注意到你a[used]被分配了错误的符号。一旦您解决了变量阴影问题,将是一个问题。尝试找出一种方法来if用另一个函数替换这四个块 - 同样,在向计算器添加新运算符时会更难犯这样的错误,并且会更容易修复运算符应用代码中的错误,因为您只需要修复一个位置的错误。

我不能过分强调将代码分解为“最小的合理”函数是多么有用。你可以比大函数更容易地测试小函数,而且你的代码将来会更容易阅读。

于 2012-04-10T01:37:43.773 回答
-1

以防万一您需要计算器方面的帮助,这是我在 Java 中的第一个项目之一

https://github.com/orefalo/ExpressionEvaluator

于 2012-04-10T01:36:57.830 回答