计算器小程序的改进

//简易计算器小程序

阅读过程:

1.  网上看到一个简单的小程序,是关于输入数字和加减乘除符号,可以运算结果的

(阅读后理解搜索的在代码后注释着)

 1 //方法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 }

运行结果:

请输入数字A:

11

请输入运算符号(+、-、*、/):

*

请输入数字B

8

结果为88.0

2.阅读过程2:觉得这样的输入太麻烦了,能不能直接输入出结果呢?改进一下,不是单独输入,而是一起输入,直接出结果。

  1 //方法2
  2 
  3 package jsj;
  4 
  5 
  6 import java.util.Scanner;
  7 //java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入
  8 
  9 public class Calculator {
 10 
 11      public static void main(String[] args) {
 12 
 13          System.out.println("-----------------------------------");
 14 
 15          System.out.println("请输入一个算术表达式,如:45*23");
 16 
 17          Scanner in = new Scanner(System.in);// 从键盘接收数据
 18       
 19          String str = in.nextLine();// nextline方式接收字符串
 20 
 21          StringBuffer buffer = new StringBuffer();
 22          /*当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。 
 23                              和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。 
 24            StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。 
 25                               由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。 */
 26 
 27          StringBuffer buffer1 = new StringBuffer();
 28 
 29          char t = ' ';//默认初始化符号位,即“+-*/”
 30 
 31          for (int i = 0; i < str.length(); i++) {
 32 
 33              if (str.charAt(i) == '+' || str.charAt(i) == '-'
 34 
 35                      || str.charAt(i) == '*' || str.charAt(i) == '/') {
 36 
 37                  t = str.charAt(i);//把符号位赋值给t
 38                 //charAt()功能类似于数组,可以把字符串看作是char类型的数组,它是把字符串拆分获取其中的某个字符;返回指定位置的字符。 
 39                 // charAt(i),i为int类型,i从0开始。 
 40  
 41 
 42                  for (int j = i + 1; j < str.length(); j++) {
 43 
 44                      buffer1.append(str.charAt(j));
 45               //append() 方法在被选元素的结尾(仍然在内部)插入指定内容。
 46              /*Stringbuffer 有append()方法 
 47                Stringbuffer其实是动态字符串数组 
 48              /*Stringbuffer 有append()方法 
 49                append()是往动态字符串数组添加,跟“xxxx”+“yyyy”相当那个‘+’号 
 50              /*Stringbuffer 有append()方法 
 51                                         跟String不同的是Stringbuffer是放一起的 
 52                String1+String2 和Stringbuffer1.append("yyyy")虽然打印效果一样,但在内存中表示却不一样 
 53                String1+String2 存在于不同的两个地址内存 
 54                Stringbuffer1.append(Stringbuffer2)放在一起 */
 55                      
 56                  }
 57 
 58                  break;
 59 
 60              } else {
 61 
 62                  buffer.append(str.charAt(i));
 63 
 64              }
 65 
 66          }
 67 
 68          String c = buffer.toString();//将buffer对象转换成指定的字符编码的字符串。
 69          /*比如:
 70           StringBuffer sb = new StringBuffer("abcd") ;
 71            sb.append("efg") ;
 72            String str = sb.toString() ;
 73            System.out.println(str) ; // out : "abcdefg" 
 74 
 75                  使用StringBuffer的toString()方法,可以将StringBuffer转换成String */
 76 
 77          String d = buffer1.toString();
 78 
 79          double a = Double.parseDouble(c);
 80 
 81          double b = Double.parseDouble(d);
 82         /* 
 83            Double.parseDouble方法是把数字类型的字符串,转换成double类型
 84            Double.valueOf方法是把数字类型的字符串,转换成Double类型
 85                               比如:字符 0.94
 86                              采用 valueOf  得到的结果是 0.9400000000000001
 87                              而采用 parseDouble 得到的结果是 0.94*/
 88 
 89          double sum = 0;
 90 
 91          if (t == '+') {
 92 
 93              sum = a + b;
 94 
 95          }
 96 
 97          if (t == '-') {
 98 
 99              sum = a - b;
100 
101          }
102 
103          if (t == '*') {
104 
105              sum = a * b;
106 
107          }
108 
109          if (t == '/') {
110 
111              sum = a / b;
112 
113          }
114 
115          System.out.println("程序运算...");
116 
117          System.out.println(c+t+d+"="+sum);
118 
119          System.out.print("-----------------------------------");
120 
121      }
122 
123 }

运行结果:

-----------------------------------

请输入一个算术表达式,如:45*23

11*8

程序运算...

11*8=88.0

-----------------------------------

 

心得:

方法二是方法1的改进,更加符合人的逻辑思维,相比于方法1更加快捷方便。

理解用户需求:一个快捷的运算输入(方法二),而不是一个个的拆分输入(方法1),那么想要更好地扩展使用,可以用有界面结构的计算机小程序。

 

3.阅读过程3:

还是太麻烦了,能不能呈界面化,更加简单些,不要是数据化,这样会更加清晰!

  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更加简单明了,也就是电脑中自带的计算器界面。

程序是为了方便用户使用的,Java引入图形化界面编程。

了解了一下内容:

1.JFrame 是容器类

2.AWT 是抽象窗口组件工具包,是 Java 最早的用于编写图形节目应用程序的开发包。

3.Swing 是为了解决 AWT 存在的问题而新开发的包,它以 AWT 为基础的。

复习和学习了Java的GUI图形界面设计,以及监听器,堆栈等等的综合运用。

方法1,2参考链接  https://blog.csdn.net/Frank_Jay/article/details/52900089

方法3参考链接    https://blog.csdn.net/q982151756/article/details/80647663

猜你喜欢

转载自www.cnblogs.com/xjwang-0219/p/10473664.html