2012-04-10 94 views
2

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

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) 

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

+0

您是否希望获得固定的整个应用程序或解决当前错误?如果您试图解决当前问题,请在从该堆栈弹出之前添加一行以检查操作数是否为空。 基本上更改处理程序为 “=” 为: '如果(ae.getActionCommand()等于( “=”)。){ 如果(operands.isEmpty()) \t回报;' – 2012-04-10 01:31:13

+0

我希望获得整个应用程序修复,你是说我有更多的错误? :/ – 2012-04-10 01:32:57

+0

没有错误本身,但计算器不会真的“计算” – 2012-04-10 01:34:11

回答

3

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

是的,你已经有了一个栈的问题,就如同例外告诉你:

at JCalculator.actionPerformed(JCalculator.java:152) 

在文本编辑器打开你的JCalculator,把行数显示,并转到行152这是你的问题在哪里。

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

+0

好吧谢谢我会看看在它并尝试你的建议,再次感谢 – 2012-04-10 01:46:11

1

actionPerformed()方法shadows一些类变量;请注意,您已重新声明char [] aint 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]被分配了错误的符号。一旦你修复了你的变量shadowing问题,这个将成为一个问题。尝试找出一种方法,用另一种单一功能取代这四个if块 - 再一次,当向计算器添加新操作符时,它会使这种错误变得更加困难,并且会修复运算符应用代码中的错误更容易,因为你只需要修复一个位置的错误。

我不能强调足够强调将代码分解成“最小合理”功能的有用程度。您可以测试小函数比大函数更容易,并且将来您的代码将更易于阅读。

+0

感谢您的有用的提示和想法,我一定会尝试修复我的代码。 – 2012-04-10 01:44:53

+0

我的荣幸,快乐的节目。 :) – sarnold 2012-04-10 01:46:38