简单计算器的实现源代码

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class Calculater extends JFrame {
    private static final long serialVersionUID = 1L;


    private boolean flag = false; //每次点击'='之后其值更新为真,之后再次点击任何按键将清空文本框,并将其值更新为false
    private boolean point = false;//point 为false 时无小数点,小数点生效
    private JPanel contentPane;	//主窗格
    private JTextField txtUnder;	//上层文本框,用于显示输入的表达式
    private JTextField txtUpper;	//下层文本框,用于显示当前的输入
    private String strUpper = "";	//上层文本
    private String strUnder = "";	//下层文本
    private String x = "";


    public static void main(String[] args) {
        Calculater frame = new Calculater();
        frame.setVisible(true);
        //frame.setResizable(false);	//不可更改窗口大小
    }

    public Calculater() {
        setTitle("简易计算器");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 416, 620);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);


        JPanel paneText = new JPanel();		//添加文本窗格
        paneText.setBounds(0, 0, 400, 170);
        contentPane.add(paneText);
        paneText.setLayout(null);

        txtUpper = new JTextField(strUpper);	//添加上方文本框
        txtUpper.setHorizontalAlignment(JTextField.RIGHT);	//设置文本右对齐
        txtUpper.setFont(new Font("Consolas", Font.PLAIN, 30));
        txtUpper.setEditable(false);
        txtUpper.setBounds(0, 0, 400, 65);
        paneText.add(txtUpper);

        txtUnder = new JTextField(strUnder);	//添加下方文本框
        txtUnder.setHorizontalAlignment(JTextField.RIGHT);	//设置文本右对齐
        txtUnder.setFont(new Font("Consolas", Font.PLAIN, 50));
        txtUnder.setEditable(false);
        txtUnder.setBounds(0, 65, 400, 105);
        paneText.add(txtUnder);


        JPanel PaneButton = new JPanel();		//添加按键窗格
        PaneButton.setBounds(0, 170, 400, 412);
        contentPane.add(PaneButton);
        PaneButton.setLayout(new GridLayout(6, 4, 0, 0));

        String[] btn = {"(",")","历史","记录","%","CE","Del","*",	//设置按键文字
                "7","8","9","/","4","5","6","+",
                "1","2","3","-","±","0",".","="};

        for(int i=0;i<btn.length;i++) {			//添加按键
            Button button = new Button(btn[i]);
            button.setFont(new Font("Consolas", Font.PLAIN, 25));
            button.addActionListener(new btnActionListener()); 	//添加监听器
            //button.addKeyListener(new btnKeyListener());
            PaneButton.add(button);
        }


    }


    class btnActionListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {

            String cmd = e.getActionCommand();



           //如果按下‘=’则flag设为真,清空上下文本框,再设置flag为假。
            if(flag) {
                strUnder = "";
                strUpper = "";
                flag = false;
            }
            /**
             * point
             每个运算数只能有一个小数点。在下一次使用加减乘除和括号前小数点都失效
             */
            char a = cmd.charAt(0);
            if(point && cmd.length()==1 && (a<'0'||a>'9') && a!='.') { //当point为真(使用过小数点了)并且a 为非小数点的运算符
                // (并利用长度为1来限制CE和Del还有“历史记录”这几个按钮)时将point置为假。
                point = false;
            }



            /**清空键,将上下文本框清空,等待下次输入。*/
            if(cmd.equals("CE")) {
                strUpper = "";
                strUnder = "";
            }
            /**删除键,将下方文本框中的最后一个字符(若存在)*/
            //删掉,但无法删除上方文本框的字符。
            else if (cmd.equals("Del")) {
                if(strUnder.length()>0) {
                    strUnder = strUnder.substring(0,strUnder.length()-1);
                }
            }
            /**基本运算符*/
            else if(cmd.equals("+")||cmd.equals("-")||cmd.equals("*")||cmd.equals("/")) {//如果按了运算符
                char s = ' ';
                if(!strUnder.isEmpty()) {		//获取下方文本框最后字符
                    s = strUnder.charAt(strUnder.length()-1);
                }

                if(strUpper.isEmpty()&&strUnder.isEmpty()) {}	//上下均空时运算符按键失效
                else if(!strUnder.isEmpty()&&(s=='+'||s=='-'||s=='*'||s=='/')) { //当已经输入一个运算符时,再次输入视为运算符更新
                    strUnder = strUnder.substring(0,strUnder.length()-1)+cmd;
                }
                else if (!strUnder.isEmpty()&&strUnder.charAt(strUnder.length()-1)=='.'){}

                else if (!strUnder.isEmpty()&&strUnder.charAt(strUnder.length()-1)=='('){}

                else if(!strUnder.isEmpty()&&strUnder.charAt(0)!='(') {
                    strUpper += strUnder;
                    strUnder = cmd;
                }

                else {//下空上不空(右括号情况)以及开头左括号情况时在下括号添加运算符
                    strUnder += cmd;
                }

            }
            /**左括号按键*/
            else if(cmd.equals("(")) {
                if ((!strUnder.isEmpty())&&(strUnder.charAt(strUnder.length()-1)<='9')&&(strUnder.charAt(strUnder.length()-1)>'0')){//如果数字后按左括号
                    //则会自动在左括号前加乘号
                    strUpper = strUnder+"*";
                    strUnder = cmd;
                }
                else if ((!strUnder.isEmpty())&&strUnder.charAt(strUnder.length()-1)=='.'){}//小数点后不能直接加左括号

                else{
                strUpper += strUnder;
                    strUnder = cmd;
                }

            }
            /**右括号按键,将下方文本框内容上移*/
            else if(cmd.equals(")")) {
                if (strUnder.charAt(0)!='('){}//如果没有左括号,右括号失效
                else if (strUnder.charAt(strUnder.length()-1)>'9'||strUnder.charAt(strUnder.length()-1)<'0'){}
                //如果前一个字符是运算符
                else {
                strUpper = strUpper + strUnder + ")";
                strUnder = "";}

            }
            /**百分号按键,当下层问空时百分号键失效
             *
             */
            else if (cmd.equals("%")) {}


            /**正负号按键,在下方文本框中的文本前加上“(-”
             * */
            else if (cmd.equals("±")) {
                strUnder = strUnder + "(-";
            }

            /**历史记录按键*/
            else if (cmd.equals("历史")||cmd.equals("记录")){
                JDialog frame = new JDialog();
                frame.setBounds(100,100,600,600);
                JTextArea jt = new JTextArea();
                JScrollPane scrollPane = new JScrollPane(jt);
                frame.getContentPane().add(scrollPane);
                jt.setText(x);
                jt.setFont(new Font("Consolas", Font.PLAIN, 30));
                frame.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
                frame.setVisible(true);
            }

            /**小数点按键。若point为真,按键失效。否则,下方文本框添加
            小数点并point的值赋为真,开始生效。另外,若按下小数点时
            表达式为空或前一位非数字,则自动在小数点前添加数字0。*/
            else if(cmd.equals(".")) {
                if(point) {return;}
                else if(strUnder.isEmpty()&&!strUpper.isEmpty()) {}//下层为空上层非空时小数点按键失效。(避免右括号之后输入数字)
                else if(strUnder.isEmpty()) {//若下层为空则自动添0
                    strUnder += "0.";
                    point = true;
                }
                else {
                    char t = strUnder.charAt(strUnder.length()-1);//记录最后一个字符
                    if(t<'0'||t>'9') {//若为操作符,则自动添0
                        strUpper += strUnder;
                        strUnder = "0.";
                    }
                    else strUnder += ".";
                    point = true;
                }
            }
            /**等于号按键,按下即触发计算表达式,并将flag赋为真,下次点
            击任何按键将清空上下文本框。*/
            else if (cmd.equals("=")) {
                if(strUnder.isEmpty()&&strUpper.isEmpty()) {
                    return;
                }
                flag = true;
                strUpper += strUnder;
                strUnder = CalculatorUtil.calc(strUpper);//计算结果
                x = x+"\r\n" +strUpper+"="+strUnder;
                if (strUnder.isEmpty()||strUpper.isEmpty()){
                    x = x;
                }


            }

            /**数字按键*/
            else {
                if(strUnder.isEmpty()&&!strUpper.isEmpty()) {}//下层为空上层非空时数字键失效(按下右括号的情况,右括号后面不能马上接数字)
                else if(strUnder.isEmpty()) {
                    strUnder += cmd;
                }
                else {
                    char t = strUnder.charAt(strUnder.length()-1);//其他情况时获取下文本框最后一个字符
                    if((t=='+'||t=='-'||t=='*'||t=='/') && (strUnder.charAt(0)!='(')) {//如果最后一个字符是运算符,且开头没有左括号
                        strUpper += strUnder;//则将其上移
                        strUnder = cmd;//下文本框更新为运算符
                    }
                    else {
                        strUnder += cmd;
                    }
                }
            }
            txtUpper.setText(strUpper);	//更新上方文本框的文本
            if(strUpper.length()>23) {
                txtUpper.setFont(new Font("Consolas", Font.PLAIN, 690/strUpper.length()));
            }
            else {
                txtUpper.setFont(new Font("Consolas", Font.PLAIN, 30));
            }

            txtUnder.setText(strUnder);	//更新下方文本框的文本
            if(strUnder.length()>15) {
                txtUnder.setFont(new Font("Consolas", Font.PLAIN, 700/strUnder.length()));
            }
            else {
                txtUnder.setFont(new Font("Consolas", Font.PLAIN, 50));
            }
        }
    }
package Calculator;//@Calculate.java
import java.util.Stack;
import java.util.StringTokenizer;


public class CalculatorUtil {

    public static String calc(String str) {
        if (checkString(str) == false) { //检查括号匹配
            return "error";
        }


        str = getcalc(str);		//进行计算(此时仅包含基本运算符和小括号)
        if(str.equals("error")||str.equals("Devide 0")) {
            return str;
        }

        java.text.DecimalFormat format = new java.text.DecimalFormat("#,###.######");//数值格式化

        return format.format(Double.parseDouble(str));
    }

    /**
     检查左右小括号的匹配
     */
    private static boolean checkString(String str) {
        // 检查括号括号匹配
        Stack<Character> sta = new Stack<Character>();
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == '(') {//找到左括号就入栈
                sta.push(str.charAt(i));
            } else if (str.charAt(i) == ')') {//如果找到右括号
                if (sta.empty() || sta.peek() != '(') {//判断如果栈空或者没有左括号,说明右括号多了
                    return false;
                } else {
                    sta.pop();//左括号出栈
                }
            }
        }
        if (sta.size() > 0)//遍历完后还有左括号没有出栈,说明左括号多了
            return false;
        return true;
    }

    /**
     并将负号做处理以便计算。
     */
    private static String Preprocess(String str) {
        for (int i = 0; i < str.length()-1; i++) {
            if (str.charAt(i) == '(' && str.charAt(i + 1) == '-') { //将“(-”转化为“(0-”
                str = str.substring(0, i + 1) + "0" + str.substring(i + 1, str.length());
            }
        }
        return str;
    }

    private static String getcalc(String str) {
        if (str.isEmpty()) {
            return str;
        }
        /**
         * 将中缀表达式转换为后缀表达式,并在运算数与运算符之间
         * 添加分隔符‘$’,最后进行后缀表达式的计算。中缀表达式
         * 储存在str中,后缀表达式储存在s中。
         */
        Stack<Character> sta = new Stack<Character>();
        String s = "$";
        int i = 0;
        if (str.charAt(0) == '(') {
            sta.push('(');
            i++;
        }
        boolean flag = false;
        for (; i < str.length(); i++) {
            if (str.charAt(i) == '+' && (i == 0 || (str.charAt(i - 1) < '0' && str.charAt(i - 1) != ')')))
                i++;
            if (str.charAt(i) == '-') {
                flag = true;
                i++;
            }
            while (i < (int) str.length() && ((str.charAt(i) >= '0' && str.charAt(i) <= '9') || str.charAt(i) == '.' || str.charAt(i)=='E')) {
                if (flag) {
                    s += "-$";
                    flag = false;
                }
                s += str.charAt(i);
                i++;
            }
            s += "$";
            if (i < (int) str.length()) {
                if (sta.empty() || str.charAt(i) == '(')
                    sta.push(str.charAt(i));
                else if (str.charAt(i) == '+' || str.charAt(i) == '-') {
                    while (sta.size() > 0 && sta.peek() != '(') {
                        s += sta.pop() + "$";
                    }
                    sta.push(str.charAt(i));
                } else if (str.charAt(i) == '*' || str.charAt(i) == '/') {
                    while (sta.size() > 0 && (sta.peek() == '*' || sta.peek() == '/')) {
                        s += sta.pop() + "$";
                    }
                    sta.push(str.charAt(i));
                } else {
                    while (sta.size() > 0 && sta.peek() != '(') {
                        s += sta.pop() + "$";
                    }
                    sta.pop();
                }
            }
        }

        while (sta.size() > 0) {
            s += sta.pop() + "$";
        }

        /**进行后缀表达式的计算
         */
        Stack<Double> stack = new Stack<Double>();
        StringTokenizer token = new StringTokenizer(s, "$", false);
        while (token.hasMoreTokens()) {
            String t = token.nextToken();
            if((t.equals("+")||t.equals("-")||t.equals("*")||t.equals("/"))&&stack.size()<2) {
                return "error";
            }
            if (t.equals("+")) {
                stack.push(stack.pop() + stack.pop());
            } else if (t.equals("-")) {
                double a = stack.pop();
                stack.push(stack.pop() - a);
            } else if (t.equals("*")) {
                stack.push(stack.pop() * stack.pop());
            } else if (t.equals("/")) {
                double a = stack.pop();
                if(Math.abs(a-0)<1E-6) {
                    return "Devide 0";
                }
                stack.push(stack.pop() / a);
            } else {
                stack.push(Double.parseDouble(t));
            }
        }

        double c = stack.pop();
        if(sta.size()>0) {
            return "error";
        }

        return String.valueOf(c);
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值