1 //简易计算器小程序 2 //方法1 3 4 package jsj; 5 6 7 import java.util.Scanner; 8 //java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入 9 10 public class Calculator { 11 12 public static void main(String[] args) { 13 14 System.out.println("-----------------------------------"); 15 16 System.out.println("请输入一个算术表达式,如:45*23"); 17 18 Scanner in = new Scanner(System.in);// 从键盘接收数据 19 20 String str = in.nextLine();// nextline方式接收字符串 21 22 StringBuffer buffer = new StringBuffer(); 23 /*当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。 24 和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。 25 StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。 26 由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。 */ 27 28 StringBuffer buffer1 = new StringBuffer(); 29 30 char t = ' ';//默认初始化符号位,即“+-*/” 31 32 for (int i = 0; i < str.length(); i++) { 33 34 if (str.charAt(i) == '+' || str.charAt(i) == '-' 35 36 || str.charAt(i) == '*' || str.charAt(i) == '/') { 37 38 t = str.charAt(i);//把符号位赋值给t 39 //charAt()功能类似于数组,可以把字符串看作是char类型的数组,它是把字符串拆分获取其中的某个字符;返回指定位置的字符。 40 // charAt(i),i为int类型,i从0开始。 41 42 43 for (int j = i + 1; j < str.length(); j++) { 44 45 buffer1.append(str.charAt(j)); 46 //append() 方法在被选元素的结尾(仍然在内部)插入指定内容。 47 /*Stringbuffer 有append()方法 48 Stringbuffer其实是动态字符串数组 49 /*Stringbuffer 有append()方法 50 append()是往动态字符串数组添加,跟“xxxx”+“yyyy”相当那个‘+’号 51 /*Stringbuffer 有append()方法 52 跟String不同的是Stringbuffer是放一起的 53 String1+String2 和Stringbuffer1.append("yyyy")虽然打印效果一样,但在内存中表示却不一样 54 String1+String2 存在于不同的两个地址内存 55 Stringbuffer1.append(Stringbuffer2)放在一起 */ 56 57 } 58 59 break; 60 61 } else { 62 63 buffer.append(str.charAt(i)); 64 65 } 66 67 } 68 69 String c = buffer.toString();//将buffer对象转换成指定的字符编码的字符串。 70 /*比如: 71 StringBuffer sb = new StringBuffer("abcd") ; 72 sb.append("efg") ; 73 String str = sb.toString() ; 74 System.out.println(str) ; // out : "abcdefg" 75 76 使用StringBuffer的toString()方法,可以将StringBuffer转换成String */ 77 78 String d = buffer1.toString(); 79 80 double a = Double.parseDouble(c); 81 82 double b = Double.parseDouble(d); 83 /* 84 Double.parseDouble方法是把数字类型的字符串,转换成double类型 85 Double.valueOf方法是把数字类型的字符串,转换成Double类型 86 比如:字符 0.94 87 采用 valueOf 得到的结果是 0.9400000000000001 88 而采用 parseDouble 得到的结果是 0.94*/ 89 90 double sum = 0; 91 92 if (t == '+') { 93 94 sum = a + b; 95 96 } 97 98 if (t == '-') { 99 100 sum = a - b; 101 102 } 103 104 if (t == '*') { 105 106 sum = a * b; 107 108 } 109 110 if (t == '/') { 111 112 sum = a / b; 113 114 } 115 116 System.out.println("程序运算..."); 117 118 System.out.println(c+t+d+"="+sum); 119 120 System.out.print("-----------------------------------"); 121 122 } 123 124 } 125 126 127 128 运行结果: 129 ----------------------------------- 130 请输入一个算术表达式,如:45*23 131 11*8 132 程序运算... 133 11*8=88.0 134 -----------------------------------
1 //方法二: 2 3 package jsj; 4 5 import java.util.Scanner; 6 7 /* 8 9 * 《大话设计模式》中的计算器实现代码 10 * https://blog.csdn.net/Frank_Jay/article/details/52900089 11 12 * */ 13 14 public class Operation { //Operation 类 15 16 public static double GetResult(double numA, double numB, String opr) {//3个参数 17 18 double result = 0d;//数值后面的d,表示是double类型数,比如 double b = 3.2d 19 20 switch (opr) { //opr表示符号的选择 21 22 case "+": 23 24 result = numA + numB; 25 26 break; 27 28 case "-": 29 30 result = numA - numB; 31 32 break; 33 34 case "*": 35 36 result = numA * numB; 37 38 break; 39 40 case "/": 41 42 result = numA / numB; 43 44 break; 45 46 } 47 48 return result; 49 50 } 51 52 53 54 public static void main(String[] args) { 55 56 System.out.println("请输入数字A:"); //友好交互提示 57 58 Scanner scan = new Scanner(System.in); 59 // 从键盘接收数据 60 61 String strNumA = scan.nextLine(); // next方式接收字符串 62 //nextLine()方法返回的是Enter键之前没有被读取的所有字符,它是可以得到带空格的字符串的 63 //next()方法在读取内容时,会过滤掉有效字符前面的无效字符, 64 //对输入有效字符之前遇到的空格键、Tab键或Enter键等结束符,next()方法会自动将其过滤掉 65 // 判断是否还有输入 66 System.out.println("请输入运算符号(+、-、*、/):"); 67 68 String strOpr = scan.nextLine(); 69 70 System.out.println("请输入数字B"); 71 72 String strNumB = scan.nextLine(); 73 74 String strResult = ""; 75 76 double Result = GetResult(Double.parseDouble(strNumA), Double.parseDouble(strNumB), strOpr); 77 //数字类型的String字符串转换为浮点数通常采用parseDouble()和valueOf()方法 78 /* 79 Double.parseDouble(java.lang.String)的参数只能是String, 80 如果参数改为double类型提示“The method parseDouble(String) in the type Double is not applicable for the arguments (double)”错误。 81 Double.valueOf()的参数类型可以是浮点型或者是字符串均可。 82 */ 83 84 strResult = String.valueOf(Result); 85 86 System.out.println("结果为"+strResult); 87 88 } 89 90 91 92 } 93 94 95 96 运行结果: 97 请输入数字A: 98 11 99 请输入运算符号(+、-、*、/): 100 * 101 请输入数字B 102 8 103 结果为88.0
方法二是方法1的改进,更加符合人的逻辑思维,相比于方法1更加快捷方便。
理解用户需求:一个快捷的运算输入(方法二),而不是一个个的拆分输入(方法1),那么想要更好地扩展使用,可以用有界面结构的计算机小程序。
1 //方法3: 2 3 package jsj; 4 5 import javax.swing.*; 6 import java.awt.*; 7 import java.awt.event.ActionEvent; 8 import java.awt.event.ActionListener; 9 import java.util.Stack; 10 11 class MyException extends Exception{ 12 public MyException() { 13 super(); 14 } 15 public MyException(String message) { 16 super(message); 17 } 18 } 19 20 public class MyCalculator extends JFrame{ 21 /* 22 * 23 */ 24 25 private JTextField textField; //输入文本框 26 private String input; //结果 27 private String operator; //操作符 28 29 public MyCalculator() { 30 input = ""; 31 operator = ""; 32 33 JPanel panel = new JPanel(); 34 textField = new JTextField(30); 35 textField.setEditable(false); //文本框禁止编辑 36 textField.setHorizontalAlignment(JTextField.LEFT); 37 //textField.setBounds(100, 100, 20, 20); //在容器布局为空情况下生效 38 textField.setPreferredSize(new Dimension(200,30));//设置该组件的初始大小 39 40 //将textField加入本JFrame中,布局为边界布局,位置为north 41 this.add(textField, BorderLayout.NORTH); 42 43 String[] name= {"7","8","9","+","4","5","6","-","1","2","3","*","0","C","=","/"}; 44 45 //将这个panel的布局设置为网格布局,有四行四列,行间距和列间距为1 46 panel.setLayout(new GridLayout(4,4,1,1)); 47 48 for(int i=0;i<name.length;i++) { 49 50 JButton button = new JButton(name[i]); 51 52 //设置按钮的时间监听 53 button.addActionListener(new MyActionListener()); 54 //将按钮加入到panel中 55 panel.add(button); 56 } 57 //将panel加入到本JFrame中,布局为边界布局,位置为centre 58 this.add(panel,BorderLayout.CENTER); 59 } 60 61 class MyActionListener implements ActionListener{ //内部类实现按钮响应 62 63 @Override 64 public void actionPerformed(ActionEvent e) { 65 int cnt=0; 66 String actionCommand = e.getActionCommand(); //获取按钮上的字符串 67 if(actionCommand.equals("+") || actionCommand.equals("-") || actionCommand.equals("*") 68 || actionCommand.equals("/")) { 69 input += " " + actionCommand + " "; 70 } 71 else if(actionCommand.equals("C")) { //清除输入 72 input = ""; 73 } 74 else if(actionCommand.equals("=")) { //按下等号 75 try { 76 input+= "="+calculate(input); 77 } catch (MyException e1) { 78 if(e1.getMessage().equals("被除数不能为0")) 79 input = e1.getMessage(); 80 else 81 input = e1.getMessage(); 82 } 83 textField.setText(input); 84 input=""; 85 cnt = 1; 86 } 87 else 88 input += actionCommand; //按下数字 89 90 //因为如果不按“=”按钮cnt一直未0,所以可以保证显示输入的数字和操作键 91 if(cnt == 0) 92 textField.setText(input); 93 } 94 } 95 //这里需要借助栈来完成表达式的计算,首先将字符串分割成字符串数组, 96 //由中缀的定义知数组奇数位为运算符(从第0位开始),偶数位为操作数, 97 // 因此可将偶数为操作数进栈,遇见+(-)运算符,则将下一个数以正(负)的形式压人栈中, 98 // 遇见*或/运算符,则将栈顶元素出栈与数组后一元素进行计算,并将其结果重新压入栈中, 99 // 直至遍历至数组最后一个元素。 100 101 private String calculate(String input) throws MyException{ //计算函数 102 String[] comput = input.split(" "); 103 //System.out.println(input); 104 Stack<Double> stack = new Stack<>(); 105 Double m = Double.parseDouble(comput[0]); 106 stack.push(m); //第一个操作数入栈 107 108 for(int i = 1; i < comput.length; i++) { 109 if(i%2==1) { 110 if(comput[i].equals("+")) 111 stack.push(Double.parseDouble(comput[i+1])); 112 if(comput[i].equals("-")) 113 stack.push(-Double.parseDouble(comput[i+1])); 114 if(comput[i].equals("*")) { //将前一个数出栈做乘法再入栈 115 Double d = stack.peek(); //取栈顶元素 116 stack.pop(); 117 stack.push(d*Double.parseDouble(comput[i+1])); 118 } 119 if(comput[i].equals("/")) { //将前一个数出栈做乘法再入栈 120 double help = Double.parseDouble(comput[i+1]); 121 if(help == 0) 122 throw new MyException("被除数不能为0"); 123 //不会继续执行该函数 124 double d = stack.peek(); 125 stack.pop(); 126 stack.push(d/help); 127 } 128 } 129 } 130 131 double d = 0d; 132 133 while(!stack.isEmpty()) { //求和 134 d += stack.peek(); 135 stack.pop(); 136 } 137 138 String result = String.valueOf(d); 139 return result; 140 } 141 142 public static void main(String[] args) { 143 JFrame f = new MyCalculator(); 144 f.setTitle(f.getClass().getSimpleName()); 145 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 146 f.setBounds(400, 200, 500, 300); 147 f.setVisible(true); 148 } 149 }
计算器页面显示:
//我大部分的学习,搜索都放在代码注释上了,从方法一到方法二是逻辑上的改进,不用断开输入,方法二到方法三是用户界面的改进,从无界面到习惯的有界面的改进。
该界面(方法3)相比于方法1,2更加简单明了,也就是电脑中自带的计算器界面。
方法1,2参考链接 https://blog.csdn.net/Frank_Jay/article/details/52900089
方法3参考链接 https://blog.csdn.net/q982151756/article/details/80647663