zoukankan      html  css  js  c++  java
  • 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();
         }
    
    }

  • 相关阅读:
    luogu P1064|| 01背包||金明的预算
    NOIp蒟蒻的爆零记——HA-0132
    模板输入计划
    1112测试教你做人
    NOIP注意事项
    强连通分量的一二三 | | JZOJ【P1232】 | | 我也不知道我写的什么
    图的割点 | | jzoj【P1230】 | | gdoi | |备用交换机
    【游戏作品】Sunset Game 制作组出品游戏一览
    【说明】我们计划从博客园迁移到知乎啦
    【总结】操作系统的重点
  • 原文地址:https://www.cnblogs.com/dosu/p/12799412.html
Copyright © 2011-2022 走看看