实现逆波兰表达式的java计算器

前言

        最近在利用java进行课程设计,需要实现一个逆波兰表达式操作的计算器。我的java是刚入门水平,通过看各种教程和视频,网上查阅等等途径,虽然过程曲折、代码书写不规范、面向对象的思想不够清晰,但终究还是完成了这次课程设计。

正文

      首先,根据课程要求,以MVC的概念对整个程序进行统筹,我将代码分成Interface,Controleur,Accumulateur和Pile四个大class。

       Interface主要是用来实现图形界面的编程,其中包括对awt包和swing包的使用,另外为了实现对键盘和按钮的监听,还需引入event包。Interface的整个界面如下:

实现逆波兰表达式的java计算器_第1张图片

上面五个文本框是用来显示栈内的前五个值(其实是四个,最低层是用来显示输入的),n键表示对栈顶元素取负,e表示enter。本界面共有三个JPanel,即jp1:12个JButton组成4*3的排列,jp2:右下方的五个JButton,以及jp3:五个文本框。对于JSplitpane,先让jp1和jp2进行分割形成一个jsp1,然后让jsp1和jp3进行分割,得到如上的界面图。

源代码如下

public class Interface extends JFrame {  //对JFrame进行扩展
	JPanel jp1, jp2,jp3;
	public JTextField[] jtf=new JTextField[5]; //显示的文本框
	JSplitPane jsp1, jsp2;
    
 public Interface()
 {
	  jp1= new JPanel();
	  jp2= new JPanel();
	  jp3= new JPanel();
	 for(int i=0;i<5;i++)
	 {
		jtf[i]=new JTextField();
		jtf[i].setHorizontalAlignment(JTextField.RIGHT);
		
	 }
	 
	 String s="0123456789.n/*-+e";
	//ajouter le button à le panel
	 for(int i=0;i"));  
			}*/
			if(i<12){
				jp1.add(b);
			}else if(i<17){
				jp2.add(b);
			}
			b.addActionListener(new Controleur(this));  //注册按钮监听
			b.addKeyListener(new Controleur(this));     //注册键盘监听
			b.setActionCommand(s.substring(i, i+1));    //按钮监听的command
		}
	 
	 for(int i=0;i<5;i++)
	 {
		 jp3.add(jtf[i]);
	 }
	 
	 jp1.setLayout(new GridLayout(4,3,2,2));//JButton放入JPanel
	 jp2.setLayout(new GridLayout(5,1));
	 jp3.setLayout(new GridLayout(5,1));
	 
	 
	 //ajouter le panel à le JFrame
	 	 
	 jsp1=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,jp1,jp2);
	 jsp1.setDividerSize(2);
	 jsp1.setEnabled(false);
	 jsp1.setDividerLocation(200);
	 jsp2=new JSplitPane(JSplitPane.VERTICAL_SPLIT,jp3,jsp1);
	 jsp2.setDividerLocation(170);
	 jsp2.setDividerSize(0); 
	 this.add(jsp2);
	 
	 this.setTitle("Calculatrice");//整个JFrame的属性设置
	 this.setIconImage(new ImageIcon("image/cc.jpg").getImage());
	 this.setSize(300, 350);
	 this.setLocation(520, 100);
	 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	 this.setVisible(true);
 }

}

       Pile是继承Stack实现一个栈,Accumulateur是用来对栈内元素进行加减乘除以及取负的操作,实现起来也比较简单,不作过多介绍,直接放码:

Accumulateur源码:

public class Accumulateur {
	
	static Pile p= new Pile(); //此处要设置为静态,不然运行起来会提示栈空指针异常

   public Float push(Float f){
	   return p.push(f);
   }
   public Float pop()
	  { 
		  return p.pop();
	  }
   public void drop()
   { 
		  p.pop();
   }
   public void clear()
   {
		  while(!p.empty()){p.pop();}	
   }
   public void Swap(){
	   float i,j;
	   i=p.pop();
	   j=p.pop();
	   p.push(i);
	   p.push(j);
	   }
   public float add(){
	   float i,j;
	   i=p.pop();
	   j=p.pop();
	   p.push(i+j);
       return i+j;
       }
   public float sub(){
	   float i,j;
	   i=p.pop();
	   j=p.pop();
	   p.push(i-j);
       return i-j;
       }
   public float mult(){
    	   float i,j;
    	   i=p.pop();
    	   j=p.pop();
    	   p.push(i*j);
           return i*j;
           }
   public float div(){
    	   float i,j;
    	   i=p.pop();
    	   j=p.pop();
    	   p.push(i/j);
           return i/j;
           }
   public float neg(){
	      return p.push(0-p.pop());      
   }

}
Pile源码:

import java.util.*;

public class Pile extends Stack{
	
	 	  public Float push(Float f) 
	 	  { 
	 		  return super.push(f); 
	 	  }
	 	  public Float pop()
	 	  { 
	 		  return super.pop();
	 	  }
	 	  public void drop()
	 	  { 
	 		  super.pop();
	 	  }
	 	  public void clear()
	 	  {
	 		  while(!super.empty()){super.pop();}	
	 	  }
}

然后是Controleur,整个操作的实现关键。


import java.awt.event.*;

import javax.swing.*;


public class Controleur implements ActionListener, KeyListener//此处要实现键盘和按钮的监听
{   
	JTextField []t; 用来从Interface传递参数
	Accumulateur ac=new Accumulateur();
	static Controleur ct;
	
	public static void main(String []args)
	{ 
		Interface itf=new Interface();
		ct=new Controleur(itf);
	}
	
	
	
	public Controleur(Interface it)//构造函数用来传递参数
	{		
		this.t=it.jtf;
		for(int i=0;i<5;i++)
		{
		t[i]=it.jtf[i];	
		}
	}
	
	
	
	//function a pour que le numero est ordonné
	public void jtfdisplay()//此处函数是将栈内元素正确的显示在文本框,采取的方法是每次压栈结束,先将栈内的前五个元素pop进文本框内
       {                        //(栈内不满五个元素,则全部放入),由于pop出了本应该进行运算的数元素后,所以还需要将文本框的内容push回栈
		for(int j=0;j<5;j++){
			t[j].setText(null);
		}
		int i=3;
		while(!ac.p.empty()&&i>=0){
			t[i].setText(String.valueOf(ac.pop()));			
		    i--;
		}
		do
		{
		    i++;
			ac.push(Float.parseFloat(t[i].getText()));
		}while(i<3);		
	}
	
	//actionEven
	public void actionPerformed(ActionEvent e)//对按钮事件的操作
         { 
		
		String sr=e.getActionCommand();
		if (sr.charAt(0)>='0'&&sr.charAt(0)<='9'){//按的键是0,9之间,
			if(t[4].getText().equals(null)) //若显示的框中无内容,直接加入
                        { t[4].setText(sr);  }  
                        else 
                        {t[4].setText(t[4].getText()+sr);} //若显示的框中已有内容需要组合	       
                }else if(sr.equals(".")){  //小数点的显示
			t[4].setText(t[4].getText()+sr);
		}
		else if(sr.equals("e"))//按下enter键进行压栈
		{	
			//empiler
			ac.push(Float.parseFloat(t[4].getText()));
		        ct.jtfdisplay();//并正确显示文本
		}else{
			  switch(sr.charAt(0))
			   { 
			  case '+': ac.add();break;
			  case '-': ac.sub();break;
			  case '*': ac.mult();break;
			  case '/':ac.div();break;
			  case 'n': ac.neg();break; 
		       }
			 ct.jtfdisplay();           //在每次运算完,都需执行显示函数
		    }
		
}

	@Override
	public void keyTyped(KeyEvent e) {  
		// TODO Auto-generated method stub
	
	}

	//keyevent
	@Override
	public void keyPressed(KeyEvent e) {//对键盘事件的操作,和按钮事件大同小异
		// TODO Auto-generated method stub
		String sr=String.valueOf(e.getKeyChar());
		if(e.getKeyCode()>=KeyEvent.VK_NUMPAD0&&e.getKeyCode()<=KeyEvent.VK_NUMPAD9){
			if(t[4].getText().equals(null)){ 
	               t[4].setText(sr);  
	           }  
	        else{t[4].setText(t[4].getText()+sr);}
		}else if(e.getKeyCode()==KeyEvent.VK_DECIMAL){
			t[4].setText(t[4].getText()+sr);
		}else if(e.getKeyCode()==KeyEvent.VK_ENTER){
			ac.push(Float.parseFloat(t[4].getText()));
		    ct.jtfdisplay();
		}else{
			  switch(e.getKeyCode())
			   { 
			  case KeyEvent.VK_ADD: ac.add();break;
			  case KeyEvent.VK_SUBTRACT: ac.sub();break;
			  case KeyEvent.VK_MULTIPLY: ac.mult();break;
			  case KeyEvent.VK_DIVIDE:   ac.div();break;
			  case KeyEvent.VK_N:        ac.neg();break; 
		       }
			 ct.jtfdisplay();
		    }
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
}
至此,设计完成(下图分别做了加和减的运算)

实现逆波兰表达式的java计算器_第2张图片实现逆波兰表达式的java计算器_第3张图片实现逆波兰表达式的java计算器_第4张图片



后记

       由于这是我第一次用java编程,也是第一次图形界面的编程,存在诸多问题,比如面前为止并未加入异常的处理,以及未形成成熟的java逻辑(老师在帮我处理问题时竟然说出了我的代码逻辑horrible),还需提高加强。

2015.02.01于Nîmes


你可能感兴趣的:(实现逆波兰表达式的java计算器)