java 计算器

之前我用java写了一个科学计算器实现,但是代码很烂,又臭又长,方法也是很低效。写得惨不忍睹。光光一个界面和限制输入就写了六七百行,虽然是科学计算器,但是没有实现计算功能。

今天我头脑清醒了一点,又重新写了一个完整可用的计算器。仿的是百度首页搜索到的网页计算器。目前没有发现什么问题。这次脑子比上次清醒多了,计算方法稍加修改,就可以变成科学计算器。只要稍稍加入一些操作,都是很简单的问题。

之前我竟然想为每一个操作副创建一个对象,然后,获取数字,等待下一个对象操作返回,做的十分复杂,写了一点我就难以写下去。今天这个代码,计算核心,也不过百十行代码,条例清晰不少,看起来也比上一个,清新干净不少。

但是有一点十分难受,我没有为这次代码写很多注释,上一个代码写的惨不忍睹,但是,我竟然非常细致的做了注释,十分详细。这次嘛。。。。。。不好意思了。因为这次代码其实我是特地帮别人写的交作业,用 eclipse实在是有点难用啊。所以注释是十分精简了,倘若日后有趣,在写科学计算器,那时在细细注释了得。

之前在网上也看来别人写的,我觉得我第一次可能是受了他们的代码的误导,所以写的如此难堪(emmmm,就算是锅,我也扣了)我看的那几份代码确实写的 烂 思路烂,代码烂,格式烂,映像里面好像有一个作者,写了五六层嵌套if,有意思的是,他留了github地址,还有个人博客地址,还有个人签名。一套release软件鸣谢的标准来的。,emmmmm。半调子水平。

本墨迹,真是十分墨迹

代码如下

package cal;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class Calculator {
    JFrame          frame;
    JPanel          panel;
    JButton[][]     buttons;
    JTextField      resultShow;
    JTextField      expShow;
    String          inputStr;
    buttonAction    Action;
    Double             num;
    int                brakets;
    int                leftBraket;
    int              rightBraket ;

    //以下为输入规则
    static String comand = "C=";         //不做任何处理的特殊符号

    static String chars[] = { 
            "",                                      //第一个输入,前面没有任何字符
            "1 2 3 4 5 6 7 8 9 0",
            "+ -",
            "* /",                                 // 3
            "(",
            ")",
            "%",
            ".",                                    // END
            "",
            ""                                        //最后一个必须是空,且不能删除
            };
    static String jump[] = {            //需要跳过不输入的字符
            "0()/%C=",
            "C=",                                    // 1..9
            ")%C=",                                   // +-
            "%)C=",                                //*/
            "%+-*/)C=",                            // (
            "1234567890.C=",                         // )
            "(%.1234567890C=",                        //
            "(.C=",
            ""                                        //最后一个必须是空,且不能删除
            };
    static String riplsx[] = {             //如果前面是chars 对应字符,需要将chars 替换为replace
            "",
            "",
            "+-*/",
            "+-*/",                                 // 3
            "",
            "",
            "",
            "+-*/%)",
            ""                                        //最后一个必须是空,且不能删除
            };
    static String rls2str[][] = {
            {".","+","-","*"},
            {"("},
            {"."},
            {"."},
            {"."},
            {"("},
            {""},
            {""} };
    static String rlsstr[][] = {
            {"0.","0+","0-","0*"},
            {"*("},
            {"0."},
            {"0."},
            {"0."},
            {"*("},
            {""},
            {""},
            {""}                                    //最后一个必须是空,且不能删除
            };
    static String     charBool = "123456789/*-+.0()";
    
    
    public Calculator() {
        // TODO 自动生成的构造函数存根
         frame                = new JFrame("计算器GUI");     //新建frame 设置标题
         panel                = new JPanel();                    //创建面板
         Action               = new buttonAction();              //创建监听实例
         inputStr             = new String("");                 //初始显示
         resultShow           = new JTextField();
         expShow              = new JTextField();
         num                  = 0.0;
         brakets              = 0;
         leftBraket           = 0;
         rightBraket          = 0;
             
    }
    
    public void show() {
        frame.setSize(480,400);                                  //设置frame大小
        frame.setLayout(new GridBagLayout());                    //使用 表格包布局
        frame.setResizable(false);                               //frame大小不可改变
        frame.setLocationRelativeTo(null);
        
        resultShow.setHorizontalAlignment(SwingConstants.RIGHT); //文字右对齐
        resultShow.setColumns(18);                               //设置文本框的列数是18
        resultShow.setBackground(Color.white);
        resultShow.setEditable(false);                           //不可编辑
        resultShow.setText("0");
        resultShow.setSize(400,100);
        resultShow.setFont(new Font("null",Font.BOLD,40));
        resultShow.setBorder(null);
        
        GridBagConstraints contains = new GridBagConstraints();
        contains.weightx     = 1;                                 
        contains.weighty      = 1;
        contains.gridx       = 0;
        contains.gridy       = 1;
        contains.gridwidth   = 4;
        contains.gridheight  = 1;
        contains.ipadx       = 350;
        contains.ipady       = 80;
        contains.fill        = GridBagConstraints.HORIZONTAL;

        this.frame.add(resultShow,contains);
        this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        expShow.setHorizontalAlignment(SwingConstants.RIGHT);//文字右对齐
        expShow.setColumns(18);                              //设置文本框的列数是18
        expShow.setBackground(Color.white);
        expShow.setEditable(false);                          //不可编辑
        expShow.setText("");
        expShow.setSize(400,60);
        expShow.setFont(new Font("null",0,25));
        expShow.setBorder(null);
        
        contains.gridy = 0;
        contains.ipady = 70;
        
       this.frame.add(expShow,contains);
        
        int k = 0;
        String strtemp = "()%C789/456*123-0.=+";
        contains.gridwidth = 1;
        contains.gridheight = 1;
        contains.ipadx = 350;
        contains.ipady = 80;
        buttons = new JButton[5][4];
        for (int i = 0; i < 5;i++) {
           for (int j = 0;j < 4;j++){
               buttons[i][j] = new JButton(strtemp.charAt(k++) + "");
               contains.gridx = j;
               contains.gridy = i + 2;
               if (i == 0 || 3 == j) {
                   buttons[i][j].setBackground(new Color(245,245,245));
               }else {
                   buttons[i][j].setBackground(Color.white);
               }
               buttons[i][j].setBorderPainted(false);
               buttons[i][j].setFont(new Font("null",Font.ITALIC,30));
               buttons[i][j].addActionListener(Action);
               this.frame.add(buttons[i][j],contains);
           }
       }
         this.frame.setVisible(true);
    }
    
     class buttonAction implements ActionListener{ 
         
         @Override
         public void actionPerformed(ActionEvent e) {
             System.out.println(e.getActionCommand());
             String cmd = e.getActionCommand();
             try {
                 inputStr = addInput(cmd);
             } catch (Exception e2) {
                // TODO: handle exception
                System.out.println(e2.getMessage());
                return;
             }
             switch (cmd) {
                 case ")":
                     riteBrakets();
                     rightBraket++; 
                     break;
                 case "(":
                     leftBraket++;
                     break;
                 case "C":
                     clear();
                     break;
                 case "=":
                     funResult();
                     return;
                 default:
             }
                 freshShow(inputStr);
         }

         private void riteBrakets() {
             if (leftBraket <= rightBraket) {                                 //如果左括号少,右括号取消
                     inputStr = inputStr.substring(0,inputStr.length() - 1);
                     freshShow(inputStr);
                 }
         }
         
         public Double getAnser(String s) throws Exception{        //可以改动一点点 把减法变成加负数,但是好像意义不大,
                s = s.replace("%","/100");
                int index = s.indexOf("(");                                //检测括号 优先计算 重复,直到计算完所有括号内容
                while ( index != -1) {
                    String braStr = getFirstBraStr(s);
                    Double braDou;
                    try {
                        braDou = this.getAnser(braStr);
                    }catch (Exception e) {
                        throw e;
                    }
                    braStr = "(" + braStr + ")";
                    s = s.replace(braStr,String.valueOf(braDou));        //将结果补回去
                    index = s.indexOf("(");
                }
                index = s.indexOf('*');                                    //乘除法优先
                while (index != -1) {
                    String leftNumStr;
                    String riteNumStr;
                    Double leftNumDou;
                    Double riteNumDou;
                    leftNumStr = getLeftStr(s,index);                    //获取左操作数
                    try {
                        leftNumDou = new Double(leftNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("left含有非法字符",e);
                    }
                    riteNumStr = getRiteStr(s,index);                    //获取右操作数
                    try {
                        riteNumDou = new Double(riteNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("含有非法字符",e);
                    }
                    String resultString = String.valueOf(leftNumDou * riteNumDou);
                    s = s.replace(leftNumStr + "*" + riteNumStr,resultString);
                    index = s.indexOf('*');
                }
                index = s.indexOf('/');                                    //乘除法优先
                while (index != -1) {
                    String leftNumStr;
                    String riteNumStr;
                    Double leftNumDou;
                    Double riteNumDou;
                    leftNumStr = getLeftStr(s,index);                    //获取左操作数
                    try {
                        leftNumDou = Double.valueOf(leftNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("left含有非法字符",e);
                    }
                    riteNumStr = getRiteStr(s,index);                    //获取右操作数
                    try {
                        riteNumDou = Double.valueOf(riteNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("含有非法字符",e);
                    }
                    String resultString = String.valueOf(leftNumDou/riteNumDou);
                    s = s.replace(leftNumStr + "/" + riteNumStr,resultString);
                    index = s.indexOf("/");
                }
                index = s.indexOf("+");                                    //加减
                while (index != -1) {
                    String leftNumStr;
                    String riteNumStr;
                    Double leftNumDou;
                    Double riteNumDou;
                    leftNumStr = getLeftStr(s,index);                    //获取左操作数
                    try {
                        leftNumDou = Double.valueOf(leftNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("left含有非法字符",e);
                    }
                    riteNumStr = getRiteStr(s,index);                    //获取右操作数
                    try {
                        riteNumDou = Double.valueOf(riteNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("含有非法字符",e);
                    }
                    String resultString = String.valueOf(leftNumDou + riteNumDou);
                    s = s.replace(leftNumStr + "+" + riteNumStr,resultString);
                    index = s.indexOf("+");
                }
                index = s.indexOf("-",1);                                //乘除法优先
                while (index != -1 && index != 0) {
                    String leftNumStr;
                    String riteNumStr;
                    Double leftNumDou;
                    Double riteNumDou;
                    leftNumStr = getLeftStr(s,index);                    //获取左操作数
                    try {
                        leftNumDou = new Double(leftNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("left含有非法字符",e);
                    }
                    riteNumStr = getRiteStr(s,index);                    //获取右操作数
                    try {
                        riteNumDou = new Double(riteNumStr);
                    }catch (Exception e) {
                        System.out.println(e.getMessage());
                        throw new Exception("含有非法字符",e);
                    }
                    String resultString = String.valueOf(leftNumDou - riteNumDou);
                    s = s.replace(leftNumStr + "-" + riteNumStr,resultString);
                    s = s.replace("--","-");
                    System.out.println("-value:" + s);
                    index = s.indexOf('-', 1);
                }
                return Double.valueOf(s);
            }

            public String getRiteStr(String s,int index) {
                char chk[] = "+-*/()".toCharArray();
                int retVal = s.length();
                for (char val:chk) {
                    int valIndex = s.indexOf(val,index + 1);
                    if (valIndex != -1 && valIndex < val) {
                        retVal = valIndex;
                    }
                }
                System.out.println("sub:" + s.substring(index + 1,retVal));
                return s.substring(index + 1,retVal);
            }

            public String getLeftStr(String s,int index) {
                char chk[] = "+-*/()".toCharArray();
                int retVal = -1;
                for (char val:chk) {
                    int valIndex = s.lastIndexOf(val,index - 1);
                    if (valIndex > retVal) {
                        retVal = valIndex;
                    }
                }
                return s.substring(retVal + 1,index);
            }

            public String getFirstBraStr(String s) {                    //返回第一个最外层匹配括号之间的字符串 如果右括号不全。返回到末尾
                if (s.indexOf("(") == -1) {                             //没有括号;
                    return "";
                }
                int leftBra = 1;
                int riteBra = 0;
                int left  = s.indexOf("(");
                int len   = left;
                int strLen = s.length() - 1;
                while (leftBra > riteBra && len < strLen) {
                    System.out.println("NO:" + leftBra + riteBra + len + strLen);
                    char ch = s.charAt(++len);
                    if (ch == '(') {
                        leftBra++;
                    }else if (ch == ')') {
                        riteBra++;
                    }
                }
                if (leftBra == riteBra) {
                    return s.substring(left + 1,len);
                }
                return s.substring(left + 1,strLen + 1);
            }

         
         private void funResult() {
                 String s = inputStr;
                 inputStr = "";
                 if (s.length() == 0) {
                     return;
                 }
                 if (indexOfLastFunc(s) == s.length() - 1) {
                     s = s.substring(0,s.length() - 1);
                 }
                 s = tabBrakets(s);             //补全括号
                 if (s.indexOf("=") == -1) {
                     expShow.setText(s + "=");
                 }else {
                     expShow.setText(s);
                }
                 try {
                     System.out.print(s);
                     s = getAnser(s).toString();
                 }catch (Exception e) {
                    freshShow("ERROR");
                }
                 
                 freshShow(s);
         }
         private String chkFuncZore(String s) {
                 int index = indexOfLastFunc(s);
                 int dotIndex = s.indexOf('.',index + 1);
                if ( dotIndex == -1) {             //没有小数点,当然可以输入啦
                    return s;
                }
                while (s.lastIndexOf('0') == (s.length()- 1) ) {
                    s = s.substring(0,s.length() - 1);
                }
                if (s.lastIndexOf('.') == (s.length() - 1)) {
                    s = s.substring(0,s.length() - 1);
                }
                return s;
         }
         
         private int indexOfLastFunc(String s) {
                 String chk = "+-*/(";
                int funIndex = -1;
                for (char ch:chk.toCharArray()) {
                    int index = s.lastIndexOf(ch);
                    if (index > funIndex) {
                        funIndex = index;
                    }
                }
                return funIndex;
         }
         
         private Boolean enableZore(String s) {
                 int index = indexOfLastFunc(s);
                if (s.indexOf(index + 1,'.') != -1) { //有小数点,当然可以输入多个0啦
                    return true;
                }
                String str = s.substring(index + 1,s.length());
                try {
                    index = Integer.parseInt(str);
                } catch (Exception e) {
                    // TODO: handle exception
                    System.out.print(e.getMessage());
                }
                if (index == 0) {
                    return false;
                }
                return true;
         }
         
         private Boolean enableDot(String s){
                 int index = indexOfLastFunc(s);
                 System.out.print("Dot index:" + index);
                 System.out.print("Dot index:" + s.indexOf(index + 1,'.'));
                if (s.indexOf('.',index + 1) != -1) {
                    return false;
                }
                return true;
         }
 
         private String tabBrakets(String s) {            //自动补全右括号
            while (rightBraket < leftBraket) {
                s = s + ")";
                rightBraket++;
            }
            return s;
        }

         private void clear() {
             inputStr    = "";
              leftBraket  = 0;
              rightBraket = 0;
              expShow.setText("");
              freshShow(inputStr);
        }
         
         private String addInput(String in) throws Exception { //如果触碰规则,则抛出异常。没有将in 输入到input就不能返回字符串,必须抛出异常
             System.out.println("输入字符是:" + in);
             String s = inputStr;
                                                         //START 这里是一些不好描述的特殊规则 应该只拦截非法输入 放行正确输入
             if (in.equals("0") && !enableZore(s)) {    //0 判断是否可用
                 throw new Exception("0不可输入");
             }
             if (in.equals(".") && !enableDot(s)) {
                 throw new Exception(".不可输入");
             }
             if ("+-*/%=".indexOf(in) != -1) {            //纠正操作副前面的小鼠点后多余的0
                 s = chkFuncZore(s);
             }                                            //END   这里是一些不好描述的特殊规则
             if (comand.indexOf(in) != -1) {             //comand里面的字符跳过不处理 也不能抛出异常
                    return s;
             }
            int len = s.length();                        //START 开始确定处理规则
            int flag = 0;
            if(len == 0) {                    
                ;
            }else {
                char ch = s.charAt(len - 1);
                System.out.println("最后一个字符是:" + ch);
                for (String val:chars) {
                    if (val.indexOf(ch) != -1)  {
                        System.out.println("找到上一个字符规则" + ch + "falg:" + flag);
                        break;
                    }
                    flag++;
                }
            }
                                                          //一下是规则处理
            if (flag == -1 || flag == chars.length - 1) { //如果有这一段,输入规则字符串最后一组就可以删除
                return s + in;                              //如果没有找到对应规则
            }
            //忽略规则
            int index = jump[flag].indexOf(in);
            if (index != -1){
                throw new Exception("非法字符忽略");
            }
            //替换规则
            index = riplsx[flag].indexOf(in);
            if (index != -1) {
                s = s.substring(0,s.length() - 1);
                return s + in;
            }
            //变换规则
            index = 0;
            for (String val:rls2str[flag]) {
                if (val.equals(in)) {
                    return s + rlsstr[flag][index];
                }
                index++;
            }
            return s + in;
        }
         
         private void freshShow(String s) {
             if (s.length() == 0) {
                 resultShow.setText("0");
             }else {
                resultShow.setText(s);
            }
            System.out.println("当前:" + s);
         }
         
     }
     public static void main(String[] args) {
        // TODO 自动生成的方法存根
            Calculator cal  = new Calculator();
            cal.show();
     }

}

原文地址:https://www.cnblogs.com/dosu/p/12799412.html