歡迎光臨
每天分享高質量文章

200 行 Java 程式碼搞定計算器程式

(點選上方公眾號,可快速關註)


來源:CarpenterLee,

www.cnblogs.com/CarpenterLee/p/8045117.html

發現了大學時候寫的計算器小程式,還有個圖形介面,能夠圖形化展示運算式語法樹。

只有200行Java程式碼,不但能夠計算加減乘除,還能夠匹配小括號~

程式碼點評:

從樸素的介面配色到簡單易懂錯誤提示,無不體現了“使用者體驗”至上的設計理念;程式碼異常處理全面合理、滴水不漏,程式碼縮排優雅大方,變數命名直觀易懂;再結合長度適中簡單明瞭的註釋,程式整體給人一種清新脫俗之感。背後不難看出作者對學習的熱愛以及對設計的苛求,工匠精神可見一斑,真可謂是大學資料結構學以致用的典範!

關於資料結構的乾貨,可參考博主的《深入理解Java集合框架》系列文章,一定不讓你失望。

http://www.cnblogs.com/CarpenterLee/p/5545987.html

實現演演算法參考嚴蔚敏的《資料結構(C語言版)》第三章“棧和佇列”,3.2.5節“運算式求值”。

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Graphics;

import java.awt.Point;

import java.awt.TextField;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import java.util.Stack;

 

import javax.swing.JFrame;

 

/**

 * 圖形介面的計算器程式,只能計算加減乘除,

 * 算式中可以有小括號。數字可以是小數

 */

public class CalcGUI extends JFrame{

    private static final long serialVersionUID = 1L;

    private TreeNode resultTree;

    private String textFieldString;

    private boolean calcSuccess = true;

    private char ops[][] = {

            {‘>’, ‘>’, ”, ‘>’},

            {‘>’, ‘>’, ”, ‘>’},

            {‘>’, ‘>’, ‘>’, ‘>’, ”, ‘>’},

            {‘>’, ‘>’, ‘>’, ‘>’, ”, ‘>’},

            {‘

            {‘E’, ‘E’, ‘E’, ‘E’, ‘E’, ‘E’, ‘E’},

            {‘

    };

    Stack nodesStack = new Stack();

    Stack opsStack = new Stack();

    public static void main(String[] args) {

        CalcGUI gui = new CalcGUI();

        gui.userGUI();

    }

    public void userGUI(){

        this.setLayout(new BorderLayout());

        TextField tf = new TextField(“請輸入運算式,按Enter開始計算~”, 40);

        tf.selectAll();

        tf.getText();

        tf.addKeyListener(new KeyAdapter(){

            public void keyPressed(KeyEvent e){

                if(e.getKeyCode() == KeyEvent.VK_ENTER){

                    textFieldString = ((TextField)e.getComponent()).getText();

                    calcSuccess = true;

                    resultTree = null;

                    try{

                        resultTree = calc(textFieldString + “#”);

                    }catch(Exception e1){

                        calcSuccess = false;

                    }

                    CalcGUI.this.repaint();

                }

            }

        });

        this.add(tf, BorderLayout.NORTH);

        this.setSize(500, 500);

        this.setTitle(“calc GUI”);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.setResizable(true);

        this.setVisible(true);

    }

    private int levelHeight = 60;

    private int diameter  = 25;

    public void paint(Graphics g){

        super.paint(g);

        if(calcSuccess){

            if(resultTree != null){

                g.drawString(“計算結果為:” + resultTree.value, 10, 80);

                int rootBeginX = this.getWidth() / 2;

                int rootBeginY = 100;

                Point p = new Point(rootBeginX, rootBeginY);

                drawTree(g, resultTree, p, this.getWidth() / 2 – 20, p);

            }

        }else{

            g.setColor(Color.RED);

            g.drawString(“運算式語法有誤!”, 10, 80);

        }

    }

    private void drawCircle(Graphics g, Point p, int r){

        g.drawOval(p.x – r, p.y – r, r * 2, r * 2);

    }

    private void drawTree(Graphics g, TreeNode node, Point pme, int width, Point pfather){

        if(node == null) return;

//      System.out.println(“in drawTree, node.value=” + node.value + “,node.op=” + node.op);

        g.setColor(Color.GREEN);

        this.drawCircle(g, pme, diameter / 2);

        g.drawLine(pme.x, pme.y, pfather.x, pfather.y);

        if(node.op != ‘E’){

            g.setColor(Color.BLACK);

            g.drawString(String.valueOf(node.op), pme.x, pme.y);

        }else{

            g.setColor(Color.BLACK);

            g.drawString(String.valueOf(node.value), pme.x – diameter / 2, pme.y);

        }

        drawTree(g, node.lft, new Point(pme.x – width / 2, pme.y + levelHeight), width / 2, pme);

        drawTree(g, node.rt, new Point(pme.x + width / 2, pme.y + levelHeight), width / 2, pme);

    }

    public TreeNode calc(String inStr) throws Exception{

        opsStack.push(‘#’);

        StringBuilder buf = new StringBuilder();

        int i = 0;

        while(i < inStr.length()){

            if(Character.isDigit(inStr.charAt(i)) || inStr.charAt(i) == ‘.’){// number

                buf.delete(0, buf.length());

                while(i < inStr.length() && 

                        (Character.isDigit(inStr.charAt(i)) || inStr.charAt(i) == ‘.’))

                    buf.append(inStr.charAt(i++));

                Double number = Double.parseDouble(buf.toString());

                nodesStack.push(new TreeNode(number));

            }else if(inStr.charAt(i) == ‘ ‘){

                i++;

                continue;

            }else{// operation

                char op = inStr.charAt(i);

                int subNew = getSub(op);

                boolean goOn = true;

                while(goOn){

                    if(opsStack.isEmpty())

                        throw new Exception(“運運算元太少!”);

                    char opFormer = opsStack.peek();

                    int subFormer = getSub(opFormer);

                    switch(ops[subFormer][subNew]){

                    case ‘=’:

                        goOn = false;

                        opsStack.pop();

                        break;

                    case ‘

                        goOn = false;

                        opsStack.push(op);

                        break;

                    case ‘>’:

                        goOn = true;

                        TreeNode n1 = nodesStack.pop();

                        TreeNode n0 = nodesStack.pop();

                        double rs = doOperate(n0.value, n1.value, opFormer);

                        nodesStack.push(new TreeNode(rs, opFormer, n0, n1));

                        opsStack.pop();

                        break;

                    default:

                        throw new Exception(“沒有匹配的運運算元:” + op);

                    }

                }

                i++;

            }

        }

        return nodesStack.pop();

         

    }

    private double doOperate(double n0, double n1, char op) throws Exception{

        switch(op){

        case ‘+’: return n0 + n1;

        case ‘-‘: return n0 – n1;

        case ‘*’: return n0 * n1;

        case ‘/’: return n0 / n1;

        default: throw new Exception(“非法運運算元:” + op);

        }

    }

    private int getSub(char c){

        switch(c){

            case ‘+’: return 0;

            case ‘-‘: return 1;

            case ‘*’: return 2;

            case ‘/’: return 3;

            case ‘(‘: return 4;

            case ‘)’: return 5;

            case ‘#’: return 6;

            default : return -1;

        }

    }

}

class TreeNode{

    public double value;

    public char op = ‘E’;

    public TreeNode lft;

    public TreeNode rt;

    public TreeNode(double value){

        this.value = value;

    }

    public TreeNode(double value, char op, TreeNode lft, TreeNode rt){

        this.value = value;

        this.op = op;

        this.lft = lft;

        this.rt = rt;

    }

    StringBuilder buf = new StringBuilder();

    public String toString(){

        out(this);

        return buf.toString();

    }

    private void out(TreeNode node){

        if(node == null) return;

        out(node.lft);

        if(node.op != ‘E’)

            buf.append(node.op);

        else

            buf.append(node.value);

        out(node.rt);

    }

}

看完本文有收穫?請轉發分享給更多人

關註「ImportNew」,提升Java技能

贊(0)

分享創造快樂