2021-05-07

                                                                      

Java编程之计算器


思路:计算器的实现分为三个步骤,首先是设计一个自己的栈类,然后是对表达式转为后缀表达式并计算后缀表达式,最后是计算器界面的设计。

一、定义栈

  1. 栈(stack):是线性表的一种,限制仅在线性表的一端进行插入和删除操作。其中允许插入和删除的一端称为栈顶(top),不允许插入和删除的一端称为栈底(bottom)。

说明:在此项目中栈主要用于将中缀表达式转为后缀表达式

具体代码如下:

public class Stack <T>{
    public int front;
    private int Maxsize;
    private T data[];
    public int lenth()//返回栈中的元素个数
    {
        return front+1;
    }
    public Stack(int size)
    {
        this.Maxsize=size;
        data=(T [])new Object[Maxsize];
        this.front=-1;
    }
    public void Push(T a)//压入数据
    {
        data[++front]=a;
    }
    public T Pop()//弹出数据
    {
        return data[front--];
    }
    public T getTop() {//获取栈顶元素
        return data[front];
    }
    public boolean isEmpty()//判断栈是否为空
    {
        if(front==-1)
            return true;
        else return false;
    }
}

二、将中缀表达式转为后缀表达式,并计算后缀表达式

  1. 中缀转后缀的方法

中缀表达式便于人们的理解与计算,但是后缀表达式更方便计算机的运算(如二叉树、堆栈的方法计算)

中缀表达式就是我们正常使用的那种,例如:1+3*2

后缀表达式就是123*+;

中缀表达式转后缀表达式的方法很多,大家可以自行去了解,此处只讲解一种

基于堆栈的算法

    从左到右扫描每一个字符。如果扫描到的字符是操作数,就直接输出这些操作数

    如果扫描到的字符是一个操作符,分三种情况:

    (1)如果堆栈是空的,直接将操作符存储到堆栈中(push it)

    (2)如果该操作符的优先级大于堆栈出口的操作符,就直接将操作符存储到堆栈中

    (3)如果该操作符的优先级低于堆栈出口的操作符,就将堆栈出口的操作符导出, 直到该操作符的优先级大于堆栈顶端的操作符。将扫描到的操作符导入到堆栈中。

    如果遇到的操作符是左括号"(”,就直接将该操作符输出到堆栈当中。该操作符只有在遇到右括号“)”的时候移除。这是一个特殊符号该特殊处理。

    如果扫描到的操作符是右括号“)”,将堆栈中的数据出栈,直到遇见左括号“(”。将堆栈中的左括号移出堆栈。继续扫描下一个字符

    如果输入的中缀表达式已经扫描完了,但是堆栈中仍然存在操作符的时候,将栈中的数据依次出栈

2.后缀表达式的计算

  从左往右依次扫描后缀表达式(定义一个数组num(也可以用栈)用于存储计算结果)

(1)如果是数字,那么直接入栈到num中

(2)如果是运算符,将栈顶的两个数字出栈,出栈后对两个数字进行相应的运算,并将运算结果入栈

注意:在此项目中由于得到的后缀表达式是一个字符串,在计算后缀表达式时要将字符型的操作数数据转为整形数据。在中缀表达式转后缀表达式时,为了方便对后缀表达式的操作

          用‘#’将操作数和操作符分隔开。

public class Turnexpression {

    private  Stack<Character> s1=new Stack<Character>(50);
    //private  Stack<Character> s3=new Stack<Character>(50);
    private  Stack<Character> s4=new Stack<Character>(50);
    //private  Stack<Integer> s2=new Stack<Integer>(50);
    //private Queue<Character>  que=new LinkedList<Character>();
    private  String in;
    protected String output="";
    public   Turnexpression()
    {

    }
    public  float totrans() {//计算后缀表达式
        float flo[] = new float[50];
        int valuetop = 0;
        String ji="";int ko=s4.lenth();String yu="";
        while (!s4.isEmpty())
        {
            ji+=s4.Pop();
        }//System.out.println(ji);
        char mt[]=ji.toCharArray();
        for(int k=ji.length()-1;k>=0;k--)
            yu+=mt[k];
      //System.out.println(yu);
      float num=0;String temp="";int i;
        for(i=0;i<yu.length();) {
            char ch = yu.charAt(i);
            if(Character.isDigit(ch)||ch=='.')
            {
                //System.out.println(ch);
               while (Character.isDigit(ch)||ch=='.'){
                   temp+=ch;
                    ch=yu.charAt(++i);
                   // System.out.println("ddw");
               }
                num=Float.parseFloat(temp);
               temp="";
                flo[valuetop++]=num;

            }else
            {
                if(ch==43)//这里的数字代表运算符的ASCLL码
                {
                    float tem=flo[valuetop-2]+flo[valuetop-1];
                    valuetop--;
                    flo[valuetop-1]=tem;
                    i++;
                }
                if(ch==45)
                {
                    float tem=flo[valuetop-2]-flo[valuetop-1];
                    valuetop--;
                    flo[valuetop-1]=tem; i++;
                }
                if(ch==42)
                {
                    float tem=flo[valuetop-2]*flo[valuetop-1];
                    valuetop--;
                    flo[valuetop-1]=tem;i++;
                }
                if(ch==94)//幂运算
                {
                    float tem=(float) Math.pow(flo[valuetop-2],flo[valuetop-1]);
                    //float tem=flo[valuetop-2]*flo[valuetop-1];
                    valuetop--;
                    flo[valuetop-1]=tem; i++;
                }
                if(ch==37)
                {
                    float tem=flo[valuetop-2]%flo[valuetop-1];
                    valuetop--;
                    flo[valuetop-1]=tem;i++;
                }
                if(ch==47)
                {
                    //System.out.println(valuetop);
                    float tem=flo[valuetop-2]/flo[valuetop-1];
                    valuetop--;
                    flo[valuetop-1]=tem; i++;
                }
                if(ch=='#')
                    i++;
            }

        }//System.out.println("ds"+flo[valuetop-1]);
        if(valuetop-1==-1)
            return 0;
        else
      // System.out.println(flo[valuetop-1]);
        return flo[valuetop-1];

    }
    public void SetString(String in)
    {
        this.in=in;
    }
    public String doTrans() {//将中缀表达式转后缀表达式

        for (int j = 0; j < in.length(); j++) {
            char ch = in.charAt(j);
            int n=in.length();
            if(j>0&&!Character.isDigit(in.charAt(j-1))&&ch>=48&&ch<58&&in.charAt(j-1)!='.')
                s4.Push('#');
            //if(!Character.isDigit(in.charAt(j+1))/*in.charAt(j+1)=='+'||in.charAt(j+1)=='-'||in.charAt(j+1)=='*'||in.charAt(j+1)=='/'||in.charAt(j+1)=='%'
                  //  ||in.charAt(j+1)=='^'||in.charAt(j+1)=='('||in.charAt(j+1)==')'*/&&(j+2)<in.length())

            switch (ch) {
                case '+':
                case '-':
                    gotOper(ch, 1);
                    break;
                case '^':
                    gotOper(ch, 3);
                    break;
                case '*':
                case '/':
                case '%':
                    gotOper(ch, 2);
                    break;
                case '(':
                   s1.Push(ch);
                    break;
                case ')':
                    gotParen(ch);
                    break;
                default:
                {

                    output = output + ch;
                   // System.out.println("ch"+ch);
                    s4.Push(ch);

                    if(j + 1 < n && (in.charAt(j+1)=='+'||in.charAt(j+1)=='-'||in.charAt(j+1)=='*'
                            ||in.charAt(j+1)=='/'||in.charAt(j+1)=='%'
                            ||in.charAt(j+1)=='^'||in.charAt(j+1)==')'||in.charAt(j+1)=='(')|| j + 1 == n)
                        s4.Push('#');
                    //System.out.println("ch"+s4.Pop());
                   // System.out.println("ch"+s4.getTop());
               }
                    break;
            }
        }
        while (!s1.isEmpty()) {
           // s2.Push(s1.Pop());
            char k=s1.Pop();
          output = output + k;
          s4.Push(k);
        }
        return output;

    }
    public void gotOper(char opThis, int prec1) {//在中缀转后缀过程中对表达式的具体操作
        while (!s1.isEmpty()){
            char opTop = s1.Pop();
            if (opTop == '(') {
                s1.Push(opTop);
                break;
            }
            else {
                int prec2=0;
                if (opTop == '+' || opTop == '-')
                    prec2 = 1;
                else if(opTop == '/' || opTop == '*'||opTop == '%')
                    prec2 = 2;
                else if(opTop=='^')
                    prec2=3;
                if (prec2 < prec1) {
                    s1.Push(opTop);
                    break;
                }
                else
                {output = output + opTop;
                s4.Push(opTop);
                }
            }
        }
        s1.Push(opThis);
    }
    public void gotParen(char ch){//在转后缀表达式时处理遇到‘)’的情况
        while (!s1.isEmpty()) {
            char chx = s1.Pop();
            if (chx == '(')
                break;
            else
            { output = output + chx;
            s4.Push(chx);
            }
        }
    }
    public int Judje(String kn)//用于输入的判断表达式是否正确
    {
        char str[]=kn.toCharArray();
        int l=kn.length();
        if(str[0]=='-'||str[0]=='+'||str[0]=='*'||str[0]=='/'||str[0]=='%'||str[0]=='^'||str[0]=='.'||str[0]==')')
            return 1;
        if(str[l-1]=='+'||str[l-1]=='-'||str[l-1]=='*'||str[l-1]=='/'||str[l-1]=='%'||str[l-1]=='^'
                ||str[l-1]=='.'||str[l-1]=='(')
            return 2;
        for(int i=1;i<kn.length()-1;i++)
        {
            if(str[i]=='/'&&str[i+1]=='0')
                return 5;
        }
       // System.out.println("第2");
        boolean tip=true;boolean tip2=true;
        for(int i=1;i<kn.length()-1;i++)
        {
           // System.out.println(str[i]);
              if((str[i]=='.'||str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'||str[i]=='%'||str[i]=='^')
                      &&!((Character.isDigit(str[i-1])&&Character.isDigit(str[i+1]))||(str[i-1]=='('||str[i-1]==')')||
                      (str[i+1]=='('||str[i+1]==')')))
                  tip=false;
              //else tip=false;
              //System.out.println("tip"+tip);
        }
        if(!tip)
            return 3;
        int A1=0,A2=0;
        for(int i=0;i<kn.length();i++)
        {
            if(str[i]=='(')
                A1++;
            else if(str[i]==')')
                A2++;
        }//System.out.println("第3");
        if(A1!=A2) tip2=false;
       // {//System.out.println("tip:"+tip+" "+"tip2:"+tip2);
        if (!tip2)return 4;//}
        return  9;
    }

三、界面设计(GUI编程)

界面功能:

  1. 获取用户输入的表达式
  2. 调用Turnexpression类(将中缀表达式转为后缀表达式,并计算后缀表达式)的对象中的方法对表达式进行计算
  3. 显示计算结果

界面成果如下:

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Interface extends JFrame implements ActionListener {
    private JTextField t1;
    private Turnexpression turnexpression = new Turnexpression();
    public void computer() {
        JFrame f1 = new JFrame("计算器");  //创建顶层容器(窗口)
        f1.setLocation(200, 300);
        f1.setSize(300, 350);        //设置窗口大小
        f1.setResizable(false);
        JPanel p1 = new JPanel(new BorderLayout(5, 5)); //创建一个面板
        //里面的new BorderLayout(5,5)是设置面板的布局(边框布局)
        //其中(5,5)的第1个5表示上下控件间距,第2个表示左右控件间距

        p1.setBorder(new EmptyBorder(5, 5, 5, 5));   //设置边界距离  border 边界
        //面板的setBorder函数,用于设置面板边缘向内收缩宽度
        //里面的EmtyBorder(5,5,5,5)表示面板上,左,下,右各向内收缩 5个像素
        t1 = new JTextField(); //创建一个单行文本框
        t1.setFont(new Font("宋体",Font.BOLD,17));
        t1.setColumns(20);  //这个用于设置文本框的列数  Columns 列
        t1.setHorizontalAlignment(SwingConstants.LEFT); //设置文本框右对齐
        //Horizontal 水平的		Alignment 对齐

        JPanel p2 = new JPanel(new GridLayout(5, 5, 5, 5));//创建第二个面板
        //其中设置其布局为网格布局,(第一个4表示1行4个控件)
        //第2个4表示1列4个控件,第1个5表示上下控件间隔为5,第2个5表示左右控件间隔为5(像素)

        JButton b1 = new JButton("7");    //创建16个按钮
        b1.addActionListener(this);//注册
        JButton b2 = new JButton("8");
        b2.addActionListener(this);
        JButton b3 = new JButton("9");
        b3.addActionListener(this);
        JButton b4 = new JButton("/");
        b4.addActionListener(this);
        JButton  k1=new JButton("^");k1.addActionListener(this);
        JButton  k2=new JButton("(");k2.addActionListener(this);
        JButton  k3=new JButton(")");k3.addActionListener(this);
        JButton  k4=new JButton("%");k4.addActionListener(this);
        p2.add(k1);
        p2.add(k2);
        p2.add(k3);
        p2.add(k4);
        JButton b5 = new JButton("4");
        b5.addActionListener(this);
        JButton b6 = new JButton("5");
        b6.addActionListener(this);
        JButton b7 = new JButton("6");
        b7.addActionListener(this);
        JButton b8 = new JButton("*");
        b8.addActionListener(this);

        JButton b9 = new JButton("1");
        b9.addActionListener(this);
        JButton b10 = new JButton("2");
        b10.addActionListener(this);
        JButton b11 = new JButton("3");
        b11.addActionListener(this);
        JButton b12 = new JButton("-");
        b12.addActionListener(this);

        JButton b13 = new JButton("0");
        b13.addActionListener(this);
        JButton b14 = new JButton(".");
        b14.addActionListener(this);
        JButton b15 = new JButton("=");
        b15.addActionListener(this);
        JButton b16 = new JButton("+");
        b16.addActionListener(this);

        p2.add(b1);    //将16个按钮全部添加到网格布局的面板p2中
        p2.add(b2);
        p2.add(b3);
        p2.add(b4);
        p2.add(b5);
        p2.add(b6);
        p2.add(b7);
        p2.add(b8);
        p2.add(b9);
        p2.add(b10);
        p2.add(b11);
        p2.add(b12);
        p2.add(b13);
        p2.add(b14);
        p2.add(b15);
        p2.add(b16);
        JButton dele = new JButton("《");
        dele.addActionListener(this);
        JPanel p3 = new JPanel();   //创建第三个面板,用于保存之前的文本框t1
        p3.add(t1, BorderLayout.NORTH);     //将文本框t1添加到面板p3中
        p3.add(dele, BorderLayout.EAST);
        p1.add(p3, BorderLayout.NORTH);//将p3添加到 为边框布局面板的p1的北部
        p1.add(p2, BorderLayout.CENTER); //将p2添加到面板的中部
        f1.add(p1);           //p1面板添加到窗口
        f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭时操作
        f1.setVisible(true);   //设置可见
    }


    @Override
    public void actionPerformed(ActionEvent event) {
        Object soure = ((JButton) (event.getSource())).getText();//获取按钮文字
        //System.out.println(soure);
        if (soure == "1") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "1");
        } else if (soure == "《") {
            String sf="";
            sf=t1.getText();String df="";
            if(!sf.isEmpty()){
                //System.out.println(sf);
             df=sf.substring(0,sf.length()-1);
            t1.setText(df);}else t1.setText("");
        }   else if (soure == "%") {
            //System.out.println(soure);
            t1.setText(t1.getText()+"%");
        }else if (soure == "^") {
            //System.out.println(soure);
            t1.setText(t1.getText() +"^");
        }else if (soure == ")") {
            //System.out.println(soure);
            t1.setText(t1.getText() +")");
        } else if (soure == "(") {
            //System.out.println(soure);
            t1.setText(t1.getText() +"(");
        } else if (soure == ".") {
            //System.out.println(soure);
            t1.setText(t1.getText() + ".");
        } else if (soure == "2") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "2");
        } else if (soure == "3") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "3");
        } else if (soure == "4") {
            //System.out.println(soure);
            t1.setText( t1.getText() + "4");
        } else if (soure == "5") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "5");
        } else if (soure == "6") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "6");
        } else if (soure == "7") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "7");
        } else if (soure == "8") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "8");
        } else if (soure == "9") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "9");
        } else if (soure == "0") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "0");
        } else if (soure == "+") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "+");
        } else if (soure == "-") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "-");
        } else if (soure == "*") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "*");
        } else if (soure == "/") {
            //System.out.println(soure);
            t1.setText(t1.getText() + "/");
        } else if (soure == "=") {
            String ui=t1.getText();
            char yu=ui.charAt(0); //StringBuffer sd;
            String  gh="";
            if(yu=='-')
            {
               // System.out.println("fdsf");
                StringBuffer  sd=new StringBuffer(ui);
                if(yu=='('&&ui.charAt(1)=='-')
                sd.insert(1,'0');
                else if(yu=='-')
                    sd.insert(0,'0');
                    gh=sd.toString();
                turnexpression.SetString(gh);
                if(turnexpression.Judje(gh)==1)
                    JOptionPane.showMessageDialog(null, "表达式开头错误,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                else if(turnexpression.Judje(gh)==2)
                    JOptionPane.showMessageDialog(null, "表达式结尾错误,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                else if(turnexpression.Judje(gh)==3)
                    JOptionPane.showMessageDialog(null, "表达式运算符两边应为数字,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                else  if(turnexpression.Judje(gh)==4)
                    JOptionPane.showMessageDialog(null, "表达式括号不匹配,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                else  if(turnexpression.Judje(gh)==5)
                    JOptionPane.showMessageDialog(null, "除数不能为零,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                else {
                    String uot= turnexpression.doTrans();
                    System.out.println("后缀表达式:"+uot);
                    float tr=turnexpression.totrans();
                    t1.setText(t1.getText()+"="+tr);}
            }else {
           // gh=sd.toString();

                StringBuffer  sdh=new StringBuffer(ui);
                String op="";
                boolean ght=true;
                String kl=t1.getText();
                for(int k=0;k<sdh.length();k++)
                {
                    char yui=sdh.charAt(k);
                    if(k+1<sdh.length()&&yui=='('&&ui.charAt(k+1)=='-')
                    {
                       sdh.insert(k+1,'0');
                        ght=false;
                    }
                }System.out.println(op);
                op=sdh.toString();
                if(!ght)
                {
                    turnexpression.SetString(op);
                    //turnexpression.totrans();
                    if(turnexpression.Judje(op)==1)
                        JOptionPane.showMessageDialog(null, "表达式开头错误,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                    else if(turnexpression.Judje(op)==2)
                        JOptionPane.showMessageDialog(null, "表达式结尾错误,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                    else if(turnexpression.Judje(op)==3)
                        JOptionPane.showMessageDialog(null, "表达式运算符两边应为数字,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                    else  if(turnexpression.Judje(op)==4)
                        JOptionPane.showMessageDialog(null, "表达式括号不匹配,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                    else  if(turnexpression.Judje(op)==5)
                        JOptionPane.showMessageDialog(null, "除数不能为零,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                    else {
                        String uot= turnexpression.doTrans();
                        System.out.println("后缀表达式:"+uot);
                        float tr=turnexpression.totrans();
                        t1.setText(t1.getText()+"="+tr);}
                }else
                    {
            turnexpression.SetString(t1.getText());
            //turnexpression.totrans();
                        if(turnexpression.Judje(t1.getText())==1)
                            JOptionPane.showMessageDialog(null, "表达式开头错误,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                        else if(turnexpression.Judje(t1.getText())==2)
                            JOptionPane.showMessageDialog(null, "表达式结尾错误,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                        else if(turnexpression.Judje(t1.getText())==3)
                            JOptionPane.showMessageDialog(null, "表达式运算符两边应为数字,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                        else  if(turnexpression.Judje(t1.getText())==4)
                            JOptionPane.showMessageDialog(null, "表达式括号不匹配,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
                        else  if(turnexpression.Judje(t1.getText())==5)
                            JOptionPane.showMessageDialog(null, "除数不能为零,请重新输入", "提示", JOptionPane.ERROR_MESSAGE);
           else {
            String uot= turnexpression.doTrans();
            System.out.println("后缀表达式:"+uot);
            float tr=turnexpression.totrans();
           t1.setText(t1.getText()+"="+tr);}}}

        }

    }

    public static void main(String[] args) {
        Interface t = new Interface();
        t.computer();
    }
}

  

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值