Java小程序之

您所在的位置:网站首页 计算器小程序源码 Java小程序之

Java小程序之

2024-07-16 22:22| 来源: 网络整理| 查看: 265

Java小程序之–计算器 每个学习编程的人都会在成为大牛的路上编写出许多小程序。自学Java一段时间后准备写一个非控制台的应用程序,个人选择了计算器,目标是类似windows系统计算器,但只实现字符串输入、最后进行加减乘除平方开方等简单的运算。开发工具是eclipse Version: Neon Release (4.6.0),参考书是《Java疯狂讲义(第三版)》。由于只学了一点皮毛,swing也是第一次使用,很不熟练,只会搞个简单能看的界面样子出来。代码也毫无美感可言,可能还有不少bug,大神们可以指教,有可以改进的地方请告诉我,但请不要喷我,目前我只有这个水平,最后成品图如下: 成品图 开发的思路是分三个部分去完成。一是界面,二是输入处理,三是计算处理。 界面几乎是边看书边查资料边试着完成的,因为以前都是控制台小程序,第一次用界面。开始想的就是有一堆按键,一个显示框,显示框能显示按键的内容,按等于号后计算算式的结果。在做的过程中慢慢的理解为这个就是【搞一个框架(Frame),框架本身是一个可以装其他组件的容器,计算器需要的什么按键button啊显示框label啊都是组件,但是太多了就不好放,于是就把一样的组件打个包,用面板(Panel)给装起来,如果面板还多可以继续把面板打包,再把打包的面板放到框架里】这是以我目前的水平的理解,不对的话请大神们指正!!! 输入处理就是能把输入的乱七八糟的东西过滤成能进行算术运算的式子,这个是这次实践过程中花费时间最长、出问题最多、修改最频繁的部分。比如如何保证一个完整的数据只能包含一个小数点?比如运算符连续输入怎么处理?比如连续的开方求倒平方等如何确定括号的位置?比如如何保证括号是完整匹配的? 计算处理想通了就好理解,Double.parseDouble(String s)会讲字符串数字处理返回一个double数字,如果有字符串“5 + 3”,那么最终就是Double.parseDouble(“5”) + Double.parseDouble(“3”),如果有字符串“5 + 3 + 5”,那就是“5 ”+ “3 + 5”,进而是“5” + “3”+“5”,也就是` // 处理加法 index = content.indexOf(“+”); if (index != -1) { return parse(content.substring(0, index)) + parse(content.substring(index + 1)); 同理,其他的处理方法一样,递归调用就行。需要注意的有几个点:1,括号处理,要考虑匹配成对的括号。2,是乘以负数如2*(3-8)和除以负数以及减减需要特殊处理一下,因为按照通常的按负号拆分并不能处理这几个运算。

// 处理乘以负数*- if (content.contains("*-") || content.matches(".*(\\*\\s\\-).*")) { content = content.replaceAll("\\*\\s\\-", "*-"); content = multiplicationAndDivisionOfNegative(content, "*"); } // 处理除以负数/- if (content.contains("/-") || content.matches(".*(/\\s\\-).*")) { content = content.replaceAll("/\\s\\-", "/-"); content = multiplicationAndDivisionOfNegative(content, "/"); } // --转成+ if (content.contains("--") || content.matches(".*(\\-\\s\\-).*")) { content = content.replaceAll("\\-\\s\\-", "+"); content = content.replaceAll("\\-\\-", "+"); }

顺便说一下,正则表达式也是第一次使用,边看书边试着写自己需要的正则,只会最简单的,但是慢慢测试也渐渐达到自己想要的效果,大神们当然不屑如此,但是考虑到新手水平,请轻喷~~ 废话不多说,直接贴上完整代码吧,请大家指教!

package myDemo; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.SystemColor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.NumberFormat; import java.util.regex.Pattern; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JPanel; import javax.swing.border.BevelBorder; public class Calculator { // 主框架 private JFrame jframe = new JFrame("计算器by K.O"); // 菜单载体 private JMenuBar jmemubar = new JMenuBar(); // 菜单,酌情放入其他功能 private JMenu jmb_view = new JMenu("查看(V)"); private JMenu jmb_edit = new JMenu("编辑(E)"); private JMenu jmb_help = new JMenu("帮助(H)"); // 显示窗口载体 private JPanel jpanel_show = new JPanel(); // 输入显示标签 private JLabel jla_input = new JLabel(); // 结果显示标签 private JLabel jla_show = new JLabel(); // 错误信息显示标签 private JLabel jla_error = new JLabel(); // 计算器按键载体 private JPanel jp_button = new JPanel(); private String result = " "; // 按键显示字符 private String[] str = { "1", "2", "3", "+", "x²", "4", "5", "6", "-", "√", "7", "8", "9", "*", "1/x", "0", "(", ")", "÷", "n!", ".", "←", "c", "=", "π" }; // 按键 private JButton[] jb_button = new JButton[str.length]; /** * 界面初始化 */ private void init() { // 菜单添加到菜单载体中 jmb_view.setMnemonic('V'); jmemubar.add(jmb_view); jmb_edit.setMnemonic('E'); jmemubar.add(jmb_edit); jmb_help.setMnemonic('H'); jmemubar.add(jmb_help); jmb_view.setFont(new Font("", Font.ROMAN_BASELINE, 10)); jmb_edit.setFont(new Font("", Font.ROMAN_BASELINE, 10)); jmb_help.setFont(new Font("", Font.ROMAN_BASELINE, 10)); // 设置显示框计算结果大字体, 设置字体右对齐 jla_show.setText("0"); jla_show.setHorizontalAlignment(JLabel.RIGHT); jla_show.setFont(new Font("arial", Font.BOLD, 22)); jla_show.setForeground(Color.BLUE); // jla_show.setBackground(Color.BLUE); // 设置显示框输入显示的字体,设置字体右对齐 jla_input.setText(" "); jla_input.setHorizontalAlignment(JLabel.RIGHT); jla_input.setFont(new Font("", Font.ROMAN_BASELINE, 10)); // 设置错误信息显示 jla_error.setText(" "); jla_error.setHorizontalAlignment(JLabel.RIGHT); jla_error.setFont(new Font("arial", Font.ROMAN_BASELINE, 10)); jla_error.setForeground(Color.RED); jpanel_show.setLayout(new BorderLayout()); // 显示标签加载到显示窗口载体中 jpanel_show.add(jla_show, BorderLayout.SOUTH); jpanel_show.add(jla_input, BorderLayout.CENTER); jpanel_show.add(jla_error, BorderLayout.NORTH); jpanel_show.setBorder( new BevelBorder(BevelBorder.RAISED, new Color(180, 180, 180), null, SystemColor.scrollbar, null)); // 按键设置为网格布局 jp_button.setLayout(new GridLayout(5, 5, 4, 4)); jp_button.setBorder( new BevelBorder(BevelBorder.RAISED, new Color(180, 180, 180), null, SystemColor.scrollbar, null)); // 按键 for (int i = 0; i < jb_button.length; i++) { jb_button[i] = new JButton(str[i]); jb_button[i].setContentAreaFilled(false);// 除去默认的背景填充 jb_button[i].setFocusPainted(false);// 除去焦点的框 // jb_button[i].setForeground(Color.blue); // 按键注册监听器 jb_button[i].addActionListener(new ButtonListener()); // 按键添加到按键载体中 jp_button.add(jb_button[i]); } // 按键载体添加到主框架 jframe.add(jp_button, BorderLayout.CENTER); // 显示框载体加载到主框架 jframe.add(jpanel_show, BorderLayout.NORTH); // 菜单载体加载到主框架 jframe.setJMenuBar(jmemubar); // 窗口位置,左上角为屏幕中央 jframe.setLocationRelativeTo(null); // 自适应大小 jframe.pack(); // 设置X关闭 jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 不可放大 jframe.setResizable(false); // 显示窗口 jframe.setVisible(true); } /** * 事件处理 * * @author K.O * */ private class ButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { String content = String.valueOf(e.getActionCommand()); boolean flag1 = jla_input.getText().contains("="); // 输入处理的结果赋值给result result = parseInputStr(result, content); jla_input.setText(result); // 控制计算结果后继续输入 if (flag1 && content.matches("^\\d")) { result = content; jla_input.setText(result); jla_show.setText("0"); } if (content.equals("←")) backSpace();// 后退 if (content.equals("c")) clear();// 清屏 if (result.endsWith("=")) { String str = jla_input.getText(); // 如果(大于)数,报错“缺少)” if (countsOfSubstringInString(result, "(") > countsOfSubstringInString(result, ")")) { jla_error.setText("')' is missing!"); result = result.substring(0, result.length() - 1); } else if (result.contains("!")) { int index = indexOfNumberStart(result.substring(0, result.indexOf('!'))); String s = result.substring(index, result.indexOf('!')); if (parse(s) > 100) jla_error.setText("the argument for factorial is too large!"); else calculate(); } // 如果出现根号下负数,报错“负数没有平方根” else if (str.indexOf("sqt") != -1) { int index = indexOfOpecifiedMirrorBracket(str, '(', str.indexOf("sqt") + 3); String s = str.substring(str.indexOf("sqt") + 4, index); if (parse(s) < 0.0) { jla_error.setText("negative number do not have a square root!"); } else calculate(); } // 如果出现/0.0报错“0不能作为被除数” else if (jla_input.getText().indexOf("/") != -1) { String s = ""; int indexofdiv = indexOfNumberEnd(str, str.indexOf("/")); s = str.substring(str.indexOf("/") + 1, indexofdiv); if (parse(s) == Double.parseDouble("0")) {// 如果s=0 jla_error.setText("0 can not be the dividend!"); result = result.substring(0, result.length() - 1); } else calculate(); } else calculate(); } } } private void calculate() { result = String.valueOf(parse(result.substring(0, result.length() - 1))); jla_show.setText(formatResult(result)); } // 处理显示结果 private String formatResult(String result) { String finalResult = ""; Double d = Double.valueOf(result); NumberFormat nf = NumberFormat.getInstance(); nf.setGroupingUsed(false); if (Math.abs(d) >= 1 || Math.abs(d) == 0) finalResult = nf.format(d); else finalResult = d.toString(); return finalResult; } /** * 后退处理 * * @param content */ private void backSpace() { if (result.length() == 1 || result.equals("")) { result = " "; jla_input.setText(result); } else { result = result.substring(0, result.length() - 1); if (result.endsWith(" ")) result = result.substring(0, result.length() - 1); jla_input.setText(result); } jla_error.setText(" "); } /** * 清屏处理 * * @param content */ private void clear() { jla_error.setText(" "); jla_input.setText(" "); result = " "; jla_show.setText("0"); } public static void main(String[] args) { new Calculator().init(); } /** * 输入处理 * * @param result * @param content * @return */ private static String parseInputStr(String result, String content) { // 刚开始输入只能输入数字、π、-或者( if (result.equals(" ") || result.equals("")) { if (content.matches("\\d+|π|\\-|\\(*")) { result = "".concat(content); } } // 左括号数大于右括号数才能输入右括号 else if (content.equals(")")) { boolean b = result.matches(".*\\d$|.*\\)$");// result以数字结尾或者右括号结尾 if (countsOfSubstringInString(result, "(") > countsOfSubstringInString(result, ")") && b) result = result.concat(content); else result = result.concat(""); } // 以数字结尾 else if (Pattern.matches(".*\\d$|.*π$", result)) { // 不可输入00 if (lastNumberOfStr(result).matches("^0+") && /* !content.equals(".") &&!content.equals("=") && */ !content.matches("\\+|\\-|\\*|÷|\\.|=")) result = result + ""; // 数字后面跟x²,1/x,√ else if (content.matches("x²|1/x|√|n!")) { result = parseDigitEndWithFuncthion(result, content); } // x.y后不能接小数点,如2.1后不能输入点,不能出现2.1.2 else if (Pattern.matches(".*\\.\\d+$", result)) {// resul以.数字结尾 result = result.concat(content.matches("\\d*|\\+|\\-|\\*|÷|\\)|=") ? content : ""); } // 数字或小数点 else if (content.matches("\\d|\\.")) result = result.concat(content); else result = result.concat(content.matches("\\+|\\-|\\*|÷|\\)|=") ? " " + content : ""); } // 以小数点结尾 else if (Pattern.matches(".*\\.$", result) && Pattern.matches("^\\d", content)) { result = result.concat(content); } // 以左括号结尾 else if ((result).matches(".*\\($")) { result = result.concat(content.matches("\\d*|π|\\-|\\(") ? content : ""); } // 以右括号结尾 else if (Pattern.matches(".*\\)$", result)) { if (content.matches("\\+|\\-|\\*|÷|=")) { result = result + " " + content; } if (content.matches("\\)")) { result = result + content; } if (content.matches("x²|√|1/x")) { result = parseBrackets(result, content); } } // 以加减乘除结尾 else if (result.matches(".*\\+$|.*\\-$|.*\\*$|.*÷$|.*/$")) { result = result.replaceAll("÷", "/"); if (result.matches(".*\\-$")) {// 以减号结尾 if (result.length() == 1) result = result + (content.matches("\\(|\\d|π") ? content : "");// 负号 else if (result.length() > 1) {// 减号或左括号负号 boolean b = result.charAt(result.length() - 2) == '('; if (b) result = result + (content.matches("\\(|\\d|π") ? content : "");// 左括号负号 else result = result + (content.matches("\\(|\\d|π") ? " " + content : "");// 减号 } } else result = result + (content.matches("\\(|\\d|π") ? " " + content : ""); } // 以!结尾 else if (Pattern.matches(".*!$", result)) { result = result + (content.matches("\\+|\\-|\\*|/|=|\\)") ? content : ""); } return result; } /** * 计算处理 * * @param content * @return */ private static double parse(String content) { // 处理π if (content.contains("π")) content = content.replace("π", "3.1412926"); if (content.contains("1/x")) content = content.replace("1/x", "rec"); // 处理乘以负数*- if (content.contains("*-") || content.matches(".*(\\*\\s\\-).*")) { content = content.replaceAll("\\*\\s\\-", "*-"); content = multiplicationAndDivisionOfNegative(content, "*"); } // 处理除以负数/- if (content.contains("/-") || content.matches(".*(/\\s\\-).*")) { content = content.replaceAll("/\\s\\-", "/-"); content = multiplicationAndDivisionOfNegative(content, "/"); } // --转成+ if (content.contains("--") || content.matches(".*(\\-\\s\\-).*")) { content = content.replaceAll("\\-\\s\\-", "+"); content = content.replaceAll("\\-\\-", "+"); } // 处理平方 int index = content.indexOf("sqr"); if (index != -1) { int endindex = indexOfOpecifiedMirrorBracket(content, '(', index + 3); String d = "(" + content.substring(index + 3, endindex + 1) + "*" + content.substring(index + 3, endindex + 1) + ")"; return parse(content.substring(0, index) + d + content.substring(endindex + 1)); } // 处理开方 index = content.indexOf("sqt"); if (index != -1) { int endindex = indexOfOpecifiedMirrorBracket(content, '(', index + 3); double d = Math.sqrt(parse(content.substring(index + 3, endindex + 1))); return parse(content.substring(0, index) + d + content.substring(endindex + 1)); } // 处理求倒 index = content.indexOf("rec"); if (index != -1) { int endindex = indexOfOpecifiedMirrorBracket(content, '(', index + 3); double d = parse("1/" + content.substring(index + 3, endindex + 1)); return parse(content.substring(0, index) + d + content.substring(endindex + 1)); } // 处理括号 int startindex = content.indexOf("("); boolean b = countsOfSubstringInString(content, "(") == countsOfSubstringInString(content, ")"); if (startindex != -1 && b) { int endindex = indexOfFirstMirrorBracket(content, '('); double d = parse(content.substring(startindex + 1, endindex)); return parse(content.substring(0, startindex) + d + content.substring(endindex + 1)); } // 处理阶乘,由于阶乘很容易越界,故不考虑括号阶乘了 index = content.indexOf("!"); if (index != -1) { double d = factorial(parse(content.substring(indexOfLeftOperator(content, index) + 1, index))); return parse( content.substring(0, indexOfLeftOperator(content, index) + 1) + d + content.substring(index + 1)); } // 处理加法 index = content.indexOf("+"); if (index != -1) { return parse(content.substring(0, index)) + parse(content.substring(index + 1)); } // 处理减法 index = content.lastIndexOf("-"); if (index != -1) { return parse(content.substring(0, index)) - parse(content.substring(index + 1)); } // 处理乘法 index = content.indexOf("*"); if (index != -1) { return parse(content.substring(0, index)) * parse(content.substring(index + 1)); } // 处理除法 index = content.lastIndexOf("/"); if (index != -1) { return parse(content.substring(0, index)) / parse(content.substring(index + 1)); } // 处理空格 if (content.equals("") || content.equals(" ")) content = "0"; // 最后结果 return Double.parseDouble(content); } /** * 阶乘实现 * * @param d * @return */ private static double factorial(double d) { return (d == 0.0 ? 1 : d * factorial(d - 1)); } /** * 字符串中某子字符串的数量 * * @param string * @param substring * @return */ private static int countsOfSubstringInString(String string, String substring) { int sum = 0; String subStrHead = ""; String subStrTrail = ""; while (string.contains(substring)) { sum++; subStrHead = string.substring(0, string.indexOf(substring)); subStrTrail = string.substring(subStrHead.length() + substring.length()); string = subStrHead + subStrTrail; } return sum; } /** * 找最左边的左括号的镜像括号的位置,或者最右边的右括号的镜像括号的位置 */ private static int indexOfFirstMirrorBracket(String s, char c) { int indexresult = -1; int sum = 0; if (countsOfSubstringInString(s, "(") == countsOfSubstringInString(s, ")")) { if (c == '(') { int index = s.indexOf(c) - 1; do { index++; if (s.charAt(index) == '(') sum++; if (s.charAt(index) == ')') sum--; } while (sum != 0 && index < s.length()); indexresult = index - 1; } if (c == ')') { int index = s.lastIndexOf(c); do { if (s.charAt(index) == ')') { sum++; } if (s.charAt(index) == '(') sum--; index--; } while (sum != 0 && index >= 0); indexresult = index; } } return indexresult + 1; } /** * 指定位置的括号的镜像括号 * * @param s * @param c * @param index * @return */ private static int indexOfOpecifiedMirrorBracket(String s, char c, int index) { int indexresult = -1; int sum = 0; int startIndex = -1; int endIndex = -1; StringBuffer sb = new StringBuffer(s); if (countsOfSubstringInString(s, "(") == countsOfSubstringInString(s, ")")) { if (index == 0 || index == s.length() - 1) return indexOfFirstMirrorBracket(s, c); else if (c == '(') { sum = countsOfSubstringInString(s.substring(0, index), String.valueOf(c)); while (sum != 0) { startIndex = sb.indexOf("("); endIndex = indexOfFirstMirrorBracket(sb.toString(), c); sb = sb.replace(startIndex, startIndex + 1, "a").replace(endIndex, endIndex + 1, "a"); sum--; } indexresult = indexOfFirstMirrorBracket(sb.toString(), c); } else if (c == ')') { sum = countsOfSubstringInString(s.substring(index + 1), String.valueOf(c)); while (sum != 0) { startIndex = sb.indexOf(")"); endIndex = indexOfFirstMirrorBracket(sb.toString(), c); sb = sb.replace(startIndex, startIndex + 1, "a").replace(endIndex, endIndex + 1, "a"); sum--; } indexresult = indexOfFirstMirrorBracket(sb.toString(), c); } } return indexresult; } /** * 某个位置前面最近一个算术运算符的位置 * * @param s * @param specifiedIndex * @return */ private static int indexOfLeftOperator(String s, int specifiedIndex) { int temp = -1; if (specifiedIndex >= 1 && s.substring(0, specifiedIndex).matches(".*(\\-|\\+|\\*|/).*")) { do { specifiedIndex--; } while (!String.valueOf(s.charAt(specifiedIndex)).matches("\\+|\\-|\\*|/")); temp = specifiedIndex; } return temp; } /** * 某个位置后面最近一个算术运算符的位置 * * @param s * @param specifiedIndex * @return */ private static int indexOfRightOperator(String s, int specifiedIndex) { int temp = -1; boolean b = specifiedIndex >= 0 && specifiedIndex


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3