1、简单计算器的实现

实验内容:

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

中缀表达式转换为后缀表达式:

①遇到‘)’,将操作符栈内运算符弹出,直到‘(’

②当中缀表达式扫描结束,判断操作符栈是否为空,未空则,将操作符栈内运算符全部弹出

①后缀表达式队列:postQueue,用于存储逆波兰表达式(其实不用队列排序直接输出也行) ②操作符栈:opStack,对用户输入的操作符进行处理,用于存储运算符

算法思想:从左向右依次读取算术表达式的元素X,分以下情况进行不同的处理: (1)如果X是操作数,直接入队 (2)如果X是运算符,再分以下情况:  a)如果栈为空,直接入栈。  b)如果X==”(“,直接入栈。  c)如果X==”)“,则将栈里的元素逐个出栈,并入队到后缀表达式队列中,直到第一个配对的”(”出栈。(注:“(”和“)”都不 入队)       d)如果是其他操作符(+ - * /),则和栈顶元素进行比较优先级。 如果栈顶元素的优先级大于等于X,则出栈并把栈中弹出的元素入队,直到栈顶元素的优先级小于X或者栈为空。弹出完这些元素后,才将遇到的操作符压入到栈中。 (3)最后将栈中剩余的操作符全部入队。

后缀表达式值的计算:使用一个栈opStack来进行值的计算。 从左向右扫描后缀表达式,遇到操作数压入opStack栈,遇到运算符,将栈顶的2个元素出栈计算,再将结果压入opStack栈;直到结束,将栈中唯一的元素出栈。

后缀表达式求解   需要用到一个结果栈opStack :用于存放计算的中间过程的值和最终结果

算法思想:首先准备一个栈opStack. 1、从左开始向右遍历后缀表达式的元素。 2、如果取到的元素是操作数,直接入栈opStack,如果是运算符,从栈中弹出2个数进行运算,然后把运算结果入栈 3、当遍历完后缀表达式时,计算结果就保存在栈里了。

整个面板用了BorderLayout布局,分为北,左和中。中部采用网格布局。定义这个类为Carculator。

实验代码:

package start;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Objects;

public class Carculator extends JFrame implements ActionListener {
    private JPanel jp_north = new JPanel();
    private JTextField input_text = new JTextField();
    private JButton c_Btn = new JButton("c");
    private static String b = "";
    private JPanel jp_center = new JPanel();

    private JTextField History = new JTextField();// 历史记录文本框初始值设为空


    public Carculator() throws HeadlessException {
        this.a();
        this.addNorthComponent();
        this.addCenterButton();
    }

    public void a() {
        this.setTitle("计算器");
        this.setSize(300, 300);
        this.setLayout(new BorderLayout());
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    public void addNorthComponent() {
        this.input_text.setPreferredSize(new Dimension(200, 30));
        jp_north.add(input_text);
        jp_north.add(c_Btn);
        this.add(jp_north, BorderLayout.NORTH);
        c_Btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input_text.setText(" ");
                 b=" ";
            }
        });
    }

    public void addCenterButton() {
        String btn_text = "1234567890+-*/.=()";
        this.jp_center.setLayout(new GridLayout(6, 3));
        for (int i = 0; i <= 17; i++) {
            String temp = btn_text.substring(i, i + 1);
            JButton btn = new JButton();
            btn.setText(temp);
            btn.addActionListener(this);
            jp_center.add(btn);
        }
        this.add(jp_center, BorderLayout.CENTER);
        this.setResizable(false);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String label = e.getActionCommand();// 获得事件源的标签
        if(".0123456789+-*/=()".indexOf(label)!=-1) {
            this.input_text.setText(input_text.getText() +label);
        }

        if (Objects.equals(label,"=")) {
            String s[] = houzhui(this.b);
            String result = Result(s);
            this.b = result + "";
            input_text.setText(this.b);
            History.setText(History.getText()+"="+input_text.getText()+"\n");

        }  else if(Objects.equals(label, "c"))// 清空按钮,消除显示屏文本框前面所有的输入和结果
        {
            this.b = "";
            input_text.setText("");// 更新文本域的显示,显示初始值;
        }
        else
        {
            this.b=this.b+label;
            input_text.setText(this.b);
            // History.setText(History.getText()+this.b);


        }

    }

    private String[] houzhui(String str) {
        String s = "";// 用于承接多位数的字符串
        char opStack[] = new char[100];// 静态栈,对用户输入的操作符进行处理,用于存储运算符
        String postQueue[] = new String[100];// 后缀表达式字符串数组,为了将多位数存储为独立的字符串
        int top = -1, j = 0;// 静态指针top,控制变量j
        for (int i = 0; i < str.length(); i++)// 遍历中缀表达式
        // indexof函数,返回字串首次出现的位置;charAt函数返回index位置处的字符;
        {
            if ("0123456789.".indexOf(str.charAt(i)) >= 0) // 遇到数字字符的情况
            {
                s = "";// 作为承接字符,每次开始时都要清空
                for (; i < str.length() && "0123456789.".indexOf(str.charAt(i)) >= 0; i++) {
                    s = s + str.charAt(i);
                }
                i--;
                postQueue[j] = s;// 数字字符直接加入后缀表达式
                j++;
            } else if ("(".indexOf(str.charAt(i)) >= 0) {// 遇到左括号
                top++;
                opStack[top] = str.charAt(i);// 左括号入栈
            } else if (")".indexOf(str.charAt(i)) >= 0) {// 遇到右括号
                for (; ; )// 栈顶元素循环出栈,直到遇到左括号为止
                {
                    if (opStack[top] != '(') {// 栈顶元素不是左括号
                        postQueue[j] = opStack[top] + "";// 栈顶元素出栈
                        j++;
                        top--;
                    } else { // 找到栈顶元素是左括号
                        top--;// 删除栈顶左括号
                        break;// 循环结束
                    }
                }
            }
            if ("*%/".indexOf(str.charAt(i)) >= 0)// 遇到高优先级运算符
            {
                if (top == -1) {// 若栈为空则直接入栈
                    top++;
                    opStack[top] = str.charAt(i);
                } else {// 栈不为空,把栈中弹出的元素入队,直到栈顶元素优先级小于x或者栈为空
                    if ("*%/".indexOf(opStack[top]) >= 0) {
                        // 栈顶元素也为高优先级运算符
                        postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后缀表达式
                        j++;
                        opStack[top] = str.charAt(i);// 当前运算符入栈
                    } else if ("(".indexOf(opStack[top]) >= 0) {// 栈顶元素为左括号,当前运算符入栈
                        top++;
                        opStack[top] = str.charAt(i);
                    } else if ("+-".indexOf(str.charAt(i)) >= 0) {// 遇到低优先级运算符
                        postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后缀表达式
                        j++;
                        opStack[top] = str.charAt(i);// 当前元素入栈
                    }
                }
            } else if ("+-".indexOf(str.charAt(i)) >= 0) {
                if (top == -1) {
                    top++;
                    opStack[top] = str.charAt(i);
                } else {
                    if ("*%/".indexOf(opStack[top]) >= 0) {
                        // 栈顶元素也为高优先级运算符
                        postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后缀表达式
                        j++;
                        opStack[top] = str.charAt(i);// 当前运算符入栈
                    } else if ("(".indexOf(opStack[top]) >= 0) {// 栈顶元素为左括号,当前运算符入栈
                        top++;
                        opStack[top] = str.charAt(i);
                    } else if ("+-".indexOf(str.charAt(i)) >= 0) {// 遇到低优先级运算符
                        postQueue[j] = opStack[top] + "";// 栈顶元素出栈进入后最表达式
                        j++;
                        opStack[top] = str.charAt(i);// 当前元素入栈
                    }
                }
            }
        }
        for (; top != -1; ) {// 遍历结束后将栈中剩余元素依次出栈进入后缀表达式
            postQueue[j] = opStack[top] + "";
            j++;
            top--;
        }
        return postQueue;
    }

    public String Result(String str[]) {
        String Result[] = new String[100];// 顺序存储的栈,数据类型为字符串
        int Top = -1;// 静态指针Top
        for (int i = 0; str[i] != null; i++) {
            if ("+-*%/".indexOf(str[i]) < 0) {
                Top++;
                Result[Top] = str[i];
            }
            if ("+-*%/".indexOf(str[i]) >= 0)// 遇到运算符字符,将栈顶两个元素出栈计算并将结果返回栈顶
            {
                double x, y, n;
                x = Double.parseDouble(Result[Top]);// 顺序出栈两个数字字符串,并转换为double类型
                Top--;
                y = Double.parseDouble(Result[Top]);
                Top--;

                if ("*".indexOf(str[i]) >= 0) {
                    n = y * x;
                    Top++;
                    Result[Top] = String.valueOf(n);// 将运算结果重新入栈

                }
                if ("/".indexOf(str[i]) >= 0) {
                    if (x == 0)// 被除数不允许为0
                    {
                        String s = "error!";
                        return s;
                    } else {
                        n = y / x;
                        Top++;
                        Result[Top] = String.valueOf(n);// 将运算结果重新入栈
                    }
                }
                if ("%".indexOf(str[i]) >= 0) {
                    if (x == 0)// 被除数不允许为0
                    {
                        String s = "error!";
                        return s;
                    } else {
                        n = y % x;
                        Top++;
                        Result[Top] = String.valueOf(n);// 将运算结果重新入栈
                    }
                }
                if ("-".indexOf(str[i]) >= 0) {
                    n = y - x;
                    Top++;
                    Result[Top] = String.valueOf(n);// 将运算结果重新入栈
                }
                if ("+".indexOf(str[i]) >= 0) {
                    n = y + x;
                    Top++;
                    Result[Top] = String.valueOf(n);// 将运算结果重新入栈
                }

            }
        }
        return Result[Top];// 返回最终结果
    }

    public static void main(String[] args) {
        Carculator carculator = new Carculator();
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值