实验一:Java计算器程序

简单计算器的实现

源码:https://github.com/klskk23/CalculaterV1.0-
更新内容2021-12-13
增加关于符号合法性的判断
实验内容:

  1. 学习GUI图形界面的设计Java Swing/Awt,创建交互友好的应用程序;
  2. 能通过界面按钮控件输入并实现算术表达式,输入的表达式即时在控件中显示,按下“=”按钮能实现运算,并将运算结果输出在控件中显示;要求能保存和浏览历史表达式的运算记录。
  3. 算术表达式求解,是指算术表达式中包括加、减、乘、除、括号等运算符,能求解包含括号的四则混合运算;并且能够检验表达式的合法性。
    实现效果:
    在这里插入图片描述

实现思路
利用swing创建一个窗体,设计按键布局等,设置按键监听,将按键的输入信息转成String类型,
然后将输入的中缀表达式转化为后缀表达式并且计算结果。
实现过程:
1.创建一个JFrame。

public class MainWindow extends JFrame {
    CalculatorPanel calculatorPanel=new CalculatorPanel(null);
    public MainWindow() {
        Container container = getContentPane();
        container.add(calculatorPanel);
        this.setTitle("计算器 BY 废旧螺栓机甲");
        this.setSize(470, 620);
        this.setLocation(100, 100);
        this.setResizable(false);
        this.setVisible(true);
        this.setFocusable(true);
    }

    public static void main(String[] args) {
        MainWindow mainWindow=new MainWindow();
    }
}

2.创建一个JPanel,添加按键,输入框,历史记录框,并且添加按键监听

public class CalculatorPanel extends JPanel {
    private boolean point_jud=true;//小数点合法性判断,true为可以输入小数点
    private boolean sym_jud =false;//运算符号合法性判断
    // 括号合法性判断,右括号数目小于等于左括号数目-1才能输入
    private int sym_l=0;
    private int sym_r=0;
    public static Font font1 = new Font("宋体", Font.BOLD, 15);
    public String str;
    private JButton lpt=new JButton();
    private JButton rpt=new JButton();

    private JButton answer=new JButton();
    private JButton button_add=new JButton();
    private JButton button_sub=new JButton();
    private JButton Button_mul=new JButton();
    private JButton button_div=new JButton();
    private JButton delete=new JButton();
    private JButton Button1=new JButton();
    private JButton Button2=new JButton();
    private JButton Button3=new JButton();
    private JButton Button4=new JButton();
    private JButton Button5=new JButton();
    private JButton Button6=new JButton();
    private JButton Button7=new JButton();
    private JButton Button8=new JButton();
    private JButton Button9=new JButton();
    private JButton Button0=new JButton();
    private JLabel show=new JLabel();
    public JTextArea output0= new JTextArea();
    public JTextArea input0=new JTextArea();
    private JButton AC=new JButton();
    private JButton point=new JButton();
    private JLabel bg=new JLabel();
    Calculator infix;
    public CalculatorPanel(LayoutManager layout) {
        super(layout);
        infix=new Calculator();


        input0.setBounds(10,10,320,50);
        input0.setText("");
        input0.setLineWrap(true);
        this.add(input0);

        show.setBounds(370,0,100,20);
        show.setText("历史");
        this.add(show);

        output0.setBounds(340,20,100,610);
        output0.setText("");
        output0.setLineWrap(true);
        this.add(output0);
        //按键宽80,高100,400*400按键区域

        AC.setIcon(new ImageIcon("img/AC.png"));
        AC.setBounds(10,70,80,100);
        this.add(AC);

        delete.setIcon(new ImageIcon("img/delete.png"));
        delete.setBounds(90,70,80,100);
        this.add(delete);

        lpt.setIcon(new ImageIcon("img/left.png"));
        lpt.setBounds(170,70,80,100);
        this.add(lpt);

        rpt.setIcon(new ImageIcon("img/right.png"));
        rpt.setBounds(250,70,80,100);
        this.add(rpt);

        Button7.setIcon(new ImageIcon("img/7.png"));
        Button7.setBounds(10,170,80,100);
        this.add(Button7);

        Button8.setIcon(new ImageIcon("img/8.png"));
        Button8.setBounds(90,170,80,100);
        this.add(Button8);

        Button9.setIcon(new ImageIcon("img/9.png"));
        Button9.setBounds(170,170,80,100);
        this.add(Button9);

        button_div.setIcon(new ImageIcon("img/div.png"));
        button_div.setBounds(250,170,80,100);
        this.add(button_div);

        Button4.setIcon(new ImageIcon("img/4.png"));
        Button4.setBounds(10,270,80,100);
        this.add(Button4);

        Button5.setIcon(new ImageIcon("img/5.png"));
        Button5.setBounds(90,270,80,100);
        this.add(Button5);

        Button6.setIcon(new ImageIcon("img/6.png"));
        Button6.setBounds(170,270,80,100);
        this.add(Button6);

        Button_mul.setIcon(new ImageIcon("img/mul.png"));
        Button_mul.setBounds(250,270,80,100);
        this.add(Button_mul);

        Button1.setIcon(new ImageIcon("img/1.png"));
        Button1.setBounds(10,370,80,100);
        this.add(Button1);

        Button2.setIcon(new ImageIcon("img/2.png"));
        Button2.setBounds(90,370,80,100);
        this.add(Button2);

        Button3.setIcon(new ImageIcon("img/3.png"));
        Button3.setBounds(170,370,80,100);
        this.add(Button3);

        button_add.setIcon(new ImageIcon("img/add.png"));
        button_add.setBounds(250,370,80,100);
        this.add(button_add);

        Button0.setIcon(new ImageIcon("img/0.png"));
        Button0.setBounds(10,470,80,100);
        this.add(Button0);

        point.setIcon(new ImageIcon("img/point.png"));
        point.setBounds(90,470,80,100);
        this.add(point);

        answer.setIcon(new ImageIcon("img/ans.png"));
        answer.setBounds(170,470,80,100);
        this.add(answer);

        button_sub.setIcon(new ImageIcon("img/sub.png"));
        button_sub.setBounds(250,470,80,100);
        this.add(button_sub);

        System.out.println(str);
        lpt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                sym_l += 1;
                input0.setText(input0.getText()+"(");
            }
        });
        rpt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(sym_r<=sym_l-1){
                    input0.setText(input0.getText()+")");
                    sym_r+=1;
                }
            }
        });
        delete.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                char add='+',sub='-',div='/',mul='*';

                String str = input0.getText();
                StringBuilder str2 = new StringBuilder();
                for (int i = 0; i < (str.length() - 1); i++) {
                    str2.append(str.charAt(i));
                }
                if (str2.toString().equals("")) {
                    input0.setText("");
                } else {
                    input0.setText(str2.toString());
                }
                if(str.charAt(str.length()-1)==add||str.charAt(str.length()-1)==sub||str.charAt(str.length()-1)==div||str.charAt(str.length()-1)==mul)sym_jud=true;
                else sym_jud=false;
            }
        });
        Button0.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"0");
                sym_jud =true;
            }
        });
        Button1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"1");
                sym_jud =true;

            }
        });

        Button2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"2");
                sym_jud =true;
            }
        });
        Button3.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"3");
                sym_jud =true;
            }
        });
        Button4.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"4");
                sym_jud =true;
            }
        });
        Button5.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"5");
                sym_jud =true;
            }
        });
        Button6.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"6");
                sym_jud =true;
            }
        });
        Button7.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"7");
                sym_jud =true;
            }
        });
        Button8.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"8");
                sym_jud =true;
            }
        });
        Button9.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input0.setText(input0.getText()+"9");
                sym_jud =true;
            }
        });

        button_add.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(sym_jud)input0.setText(input0.getText()+"+");
                sym_jud =false;
                point_jud=true;
            }
        });
        button_sub.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(sym_jud)
                    input0.setText(input0.getText()+"-");
                sym_jud =false;
                point_jud=true;
            }
        });
        Button_mul.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(sym_jud) input0.setText(input0.getText()+"*");
                sym_jud =false;
                point_jud=true;
            }
        });
        button_div.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(sym_jud) input0.setText(input0.getText()+"/");
                sym_jud =false;
                point_jud=true;
            }
        });
        answer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                point_jud=true;
                sym_jud =true;
                str=input0.getText();
                output0.setText(output0.getText()+input0.getText()+"="+infix.test(str)+'\n');
                input0.setText("");
            }
        });

        AC.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                point_jud=true;
                sym_jud =true;
                input0.setText("");output0.setText("");
            }
        });
        point.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(point_jud){input0.setText(input0.getText()+".");
                    point_jud=false;
                }
            }
        });

    }
}

4.创建一个计算类Calculator用来处理得到的中缀表达式



import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


public class Calculator {
    /**
     *提前将 符号的优先级定义好
     */
    private static final Map<Character, Integer> basic = new HashMap<Character, Integer>();
    static {
        basic.put('-', 1);
        basic.put('+', 1);
        basic.put('*', 2);
        basic.put('/', 2);
        basic.put('(', 0);//在运算中  ()的优先级最高,但是此处因程序中需要 故设置为0
    }

    public String test(String str){
        String str0 =toSuffix(str);
        return dealEquation(str0);
    }

    /**
     * 将  中缀表达式  转化为  后缀表达式
     */
    public String toSuffix(String infix){
        List<String> queue = new ArrayList<String>();                                    //定义队列  用于存储 数字  以及最后的  后缀表达式
        List<Character> stack = new ArrayList<Character>();                             //定义栈    用于存储  运算符  最后stack中会被 弹空

        char[] charArr = infix.trim().toCharArray();                                    //字符数组  用于拆分数字或符号
        String standard = "*/+-()";                                                        //判定标准 将表达式中会出现的运算符写出来
        char ch = '&';                                                                    //在循环中用来保存 字符数组的当前循环变量的  这里仅仅是初始化一个值  没有意义
        int len = 0;                                                                    //用于记录字符长度 【例如100*2,则记录的len为3 到时候截取字符串的前三位就是数字】
        for (int i = 0; i < charArr.length; i++) {                                        //开始迭代

            ch = charArr[i];                                                            //保存当前迭代变量
            if(Character.isDigit(ch)) {                                                    //如果当前变量为 数字
                len++;
            }else if(Character.isLetter(ch)) {                                            //如果当前变量为  字母
                len++;
            }else if(ch == '.'){                                                        //如果当前变量为  .  会出现在小数里面
                len++;
            }else if(Character.isSpaceChar(ch)) {                                        //如果当前变量为 空格  支持表达式中有空格出现
                if(len > 0) {                                                            //若为空格 代表 一段结束 ,就可以往队列中  存入了  【例如100 * 2  100后面有空格 就可以将空格之前的存入队列了】
                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));    //往 队列存入 截取的 字符串
                    len = 0;                                                            //长度置空
                }
                continue;                                                                //如果空格出现,则一段结束  跳出本次循环
            }else if(standard.indexOf(ch) != -1) {                                        //如果是上面标准中的 任意一个符号
                if(len > 0) {                                                            //长度也有
                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));    //说明符号之前的可以截取下来做数字
                    len = 0;                                                            //长度置空
                }
                if(ch == '(') {                                                            //如果是左括号
                    stack.add(ch);                                                        //将左括号 放入栈中
                    continue;                                                            //跳出本次循环  继续找下一个位置
                }
                if (!stack.isEmpty()) {                                                    //如果栈不为empty
                    int size = stack.size() - 1;                                        //获取栈的大小-1  即代表栈最后一个元素的下标
                    boolean flag = false;                                                //设置标志位
                    while (size >= 0 && ch == ')' && stack.get(size) != '(') {            //若当前ch为右括号,则 栈里元素从栈顶一直弹出,直到弹出到 左括号
                        queue.add(String.valueOf(stack.remove(size)));                    //注意此处条件:ch并未入栈,所以并未插入队列中;同样直到找到左括号的时候,循环结束了,所以左括号也不会放入队列中【也就是:后缀表达式中不会出现括号】
                        size--;                                                            //size-- 保证下标永远在栈最后一个元素【栈中概念:指针永远指在栈顶元素】
                        flag = true;                                                    //设置标志位为true  表明一直在取()中的元素
                    }
                    while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) {    //若取得不是()内的元素,并且当前栈顶元素的优先级>=对比元素 那就出栈插入队列
                        queue.add(String.valueOf(stack.remove(size)));                    //同样  此处也是remove()方法,既能得到要获取的元素,也能将栈中元素移除掉
                        size--;
                    }
                }
                if(ch != ')') {                                                            //若当前元素不是右括号
                    stack.add(ch);                                                        //就要保证这个符号 入栈
                } else {                                                                //否则就要出栈 栈内符号
                    stack.remove(stack.size() - 1);
                }
            }
            if(i == charArr.length - 1) {                                                //如果已经走到了  中缀表达式的最后一位
                if(len > 0) {                                                            //如果len>0  就截取数字
                    queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1, i+1)));
                }
                int size = stack.size() - 1;                                            //size表示栈内最后一个元素下标
                while (size >= 0) {                                                        //一直将栈内  符号全部出栈 并且加入队列中  【最终的后缀表达式是存放在队列中的,而栈内最后会被弹空】
                    queue.add(String.valueOf(stack.remove(size)));
                    size--;
                }
            }

        }
        return queue.stream().collect(Collectors.joining(","));                            //将队列中元素以,分割 返回字符串
    }


    /**
     * 将 后缀表达式 进行  运算 计算出结果
     * @param equation
     * @return
     */
    public String dealEquation(String equation){
        String [] arr = equation.split(",");                                    //根据, 拆分字符串
        List<String> list = new ArrayList<String>();                            //用于计算时  存储运算过程的集合【例如list中当前放置  100   20  5  /  则取出20/5 最终将结果4存入list   此时list中结果为  100  4 】


        for (int i = 0; i < arr.length; i++) {                                    //此处就是上面说的运算过程, 因为list.remove的缘故,所以取出最后一个数个最后两个数  都是size-2
            int size = list.size();
            switch (arr[i]) {
                case "+": double a = Double.parseDouble(list.remove(size-2))+ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(a));     break;
                case "-": double b = Double.parseDouble(list.remove(size-2))- Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(b));     break;
                case "*": double c = Double.parseDouble(list.remove(size-2))* Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(c));     break;
                case "/": double d = Double.parseDouble(list.remove(size-2))/ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(d));       break;
                default: list.add(arr[i]);     break;                                    //如果是数字  直接放进list中
            }
        }

        return list.size() == 1 ? list.get(0) : "运算失败" ;                    //最终list中仅有一个结果,否则就是算错了
    }



}


5.添加图片素材文件
在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值