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