计算器小程序的改进理解

  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

猜你喜欢

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