200⾏Java代码搞定计算器程序
发现了⼤学时候写的计算器⼩程序,还有个图形界⾯,能够图形化展⽰表达式语法树,哈哈;)
只有200⾏Java代码,不但能够计算加减乘除,还能够匹配⼩括号~
代码点评:
从朴素的界⾯配⾊到简单易懂错误提⽰,⽆不体现了“⽤户体验”⾄上的设计理念;代码异常处理全⾯合理、滴⽔不漏,代码缩进优雅⼤⽅,变量命名直观易懂;再结合长度适中简单明了的注释,程序整体给⼈⼀种清新脱俗之感。背后不难看出作者对学习的热爱以及对设计的苛求,⼯匠精神可见⼀斑,真可谓是⼤学数据结构学以致⽤的典范!
关于数据结构的⼲货,可参考博主的,⼀定不让你失望。
实现算法参考严蔚敏的《数据结构(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 rialVersionUID = 1L;
private TreeNode resultTree;
private String textFieldString;
private boolean calcSuccess = true;
private char ops[][] = {
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', 'E'},
{'E', 'E', 'E', 'E', 'E', 'E', 'E'},
{'<', '<', '<', '<', '<', 'E', '='},
};
Stack<TreeNode> nodesStack = new Stack<TreeNode>();
stimulateStack<Character> opsStack = new Stack<Character>();
public static void main(String[] args) {
CalcGUI gui = new CalcGUI();
gui.urGUI();
}
public void urGUI(){
this.tLayout(new BorderLayout());
TextField tf = new TextField("请输⼊表达式,按Enter开始计算~", 40);
tf.lectAll();
tf.addKeyListener(new KeyAdapter(){
public void keyPresd(KeyEvent e){
KeyCode() == KeyEvent.VK_ENTER){
textFieldString = ((Component()).getText();cryptology
calcSuccess = true;
resultTree = null;
try{
resultTree = calc(textFieldString + "#");
}catch(Exception e1){
calcSuccess = fal;
}
paint();
}
}
});
this.add(tf, BorderLayout.NORTH);
this.tSize(500, 500);
this.tTitle("calc GUI");
this.tDefaultCloOperation(JFrame.EXIT_ON_CLOSE);
this.tResizable(true);
this.tVisible(true);
}
private int levelHeight = 60;
private int diameter = 25;
public void paint(Graphics g){regedit
super.paint(g);
if(calcSuccess){
if(resultTree != null){
g.drawString("计算结果为:" + resultTree.value, 10, 80);
int rootBeginX = Width() / 2;
int rootBeginY = 100;
Point p = new Point(rootBeginX, rootBeginY);
drawTree(g, resultTree, p, Width() / 2 - 20, p);
}
}el{
g.tColor(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.tColor(Color.GREEN);
this.drawCircle(g, pme, diameter / 2);
g.drawLine(pme.x, pme.y, pfather.x, pfather.y);
if(node.op != 'E'){
g.tColor(Color.BLACK);
scalerg.drawString(String.valueOf(node.op), pme.x, pme.y);
}el{
g.tColor(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, , 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.String());
nodesStack.push(new TreeNode(number));
}el if(inStr.charAt(i) == ' '){
i++;
continue;
}el{// 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]){母亲节快乐英文
ca '=':
goOn = fal;
opsStack.pop();
break;
ca '<':
goOn = fal;
opsStack.push(op);
break;
ca '>':
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){
ca '+': return n0 + n1;
ca '-': return n0 - n1;
ca '*': return n0 * n1;
ca '/': return n0 / n1;
default: throw new Exception("⾮法操作符:" + op);
}
}
private int getSub(char c){
switch(c){
ca '+': return 0;
ca '-': return 1;
ca '*': return 2;
ca '/': return 3;
ca '(': return 4;
ca ')': return 5;
ca '#': 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;
come with methis.op = op;
this.lft = lft;
< = rt;
}
StringBuilder buf = new StringBuilder();雅思考试机经
public String toString(){
out(this);
String();
}
private void out(TreeNode node){
if(node == null) return;
out(node.lft);
if(node.op != 'E')
buf.append(node.op);
el
buf.append(node.value);
);
}
}