一.项目要求
(1)能通过设计的按钮控件输入并实现算术表达式,表达式在文本框中显示,运算结果输出显示;保存和浏览历史运算记录;
(2)能够检验算术表达式的合法性;
(3)能够实现混合运算的求解,算术表达式中包括加、减、乘、除、括号等运算符;
(4)要求交互界面友好,程序健壮。
二.项目平台
IDEA.Java Swing
三.项目实现过程
1.设计思想:
要实现完整计算式的输入并运算,就得用到计算后缀表达式的算法,和将中缀表达式转换为后缀表达式的算法。
2.算法基本思想:
从左向右遍历中缀表达式
①:遇到数字字符,直接加入后缀表达式。
②:遇到高优先级运算符,若栈为空直接入栈,若栈不为空,则将当前运算符与栈顶元素比较。
情况1 栈顶元素也为高优先级运算符:栈顶元素出栈加入后缀表达式,当前运算符入栈。这样的操作使得栈中不会出现连续的高优先级运算符。
情况2 栈顶元素为’('左括号:将当前元素入栈。
情况3 栈顶元素为低优先级运算符:将当前元素入栈。
③:遇到’(‘左括号,将左括号入栈。
④:遇到’)'右括号,将栈顶元素顺序出栈,直到栈顶元素为左括号,此时删去栈顶的左括号。
⑤:遇到低优先级运算符,若栈为空直接入栈,若栈不为空,则将当前运算符与栈顶元素比较。
计算后缀表达式
运算规则:遍历后缀表达式
①:遇到数字字符,直接入栈。
②:遇到运算符,顺序出栈两个元素(数字),进行运算,将运算结果入栈循环以上步骤最终栈中剩下的那个数字就是最终答案。
3.主要代码实现:
(1)功能按钮实现
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();//命令实现
if (label == "=") {
resultText.setText(this.b);
History.setText(History.getText() + resultText.getText());
String s[] = operation(this.b);
String result = Result(s);
this.b = result + "";
resultText.setText(this.b);
History.setText(History.getText() + "=" + resultText.getText() + "\n");//同步历史记录
} else if (label == "c") {
this.b = "";
resultText.setText("0");
} else if (label == ".") {
char a = label.charAt(0);
if (point) {//按钮失效
return;
} else if (b.isEmpty()) {//自动补零
b += "0.";
point = true;
} else {
char t = b.charAt(b.length() - 1);
if (t == '+' || t == '-' || t == 'x' || t == '÷') {
b += "0.";
point = true;
} else if (t == '.') {
point = true;
} else {
b += ".";
point = true;
}
}
point = false;//重置
}else if(label=="+"||label=="-"||label=="x"||label=="÷") {//符号限制
char s = b.charAt(b.length() - 1);
if (!b.isEmpty() && (s == '+' || s == '-' || s == 'x' || s == '÷')) { //当已经输入一个运算符时,再次输入视为运算符更新
b = b.substring(0, b.length() - 1) + label;
}
else {
b += label;
}
}
else {
this.b = this.b + label;
resultText.setText(this.b);
}
}
(2)将中缀表达式变为后缀表达式
private String[] operation(String str) {
String s = "";
char a[] = new char[100];
String ans[] = new String[100];
int top = -1, j = 0;
/**含负数运算的实现
*
*/
for (int i = 0; i < str.length()-1; i++) {
if (str.charAt(i) == '(' && str.charAt(i + 1) == '-') { //将“(-”转化为“(0-”
str = str.substring(0, i + 1) + "0" + str.substring(i + 1, str.length());
}
}
for (int i = 0; i < str.length(); i++) {
if ("0123456789.".indexOf(str.charAt(i)) >= 0) {
s = "";
for (; i < str.length() && "0123456789.".indexOf(str.charAt(i)) >= 0; i++) {
s = s + str.charAt(i);
}
i--;
ans[j] = s;
j++;
} else if ("(".indexOf(str.charAt(i)) >= 0) {
top++;
a[top] = str.charAt(i);
} else if (")".indexOf(str.charAt(i)) >= 0) {
for (; ; ) {
if (a[top] != '(') {
ans[j] = a[top] + "";
j++;
top--;
} else {
top--;
break;
}
}
} else if ("x÷".indexOf(str.charAt(i)) >= 0) {
if (top == -1) {
top++;
a[top] = str.charAt(i);
} else {
if ("x÷".indexOf(a[top]) >= 0) {
ans[j] = a[top] + "";
j++;
a[top] = str.charAt(i);
} else if ("(".indexOf(a[top]) >= 0) {
top++;
a[top] = str.charAt(i);
} else if ("+-".indexOf(a[top]) >= 0) {
top++;
a[top] = str.charAt(i);
}
}
} else if ("+-".indexOf(str.charAt(i)) >= 0) {
if (top == -1) {
top++;
a[top] = str.charAt(i);
} else {
if ("x÷".indexOf(a[top]) >= 0) {
ans[j] = a[top] + "";
j++;
a[top] = str.charAt(i);
} else if ("(".indexOf(a[top]) >= 0) {
top++;
a[top] = str.charAt(i);
} else if ("+-".indexOf(a[top]) >= 0) {
ans[j] = a[top] + "";
j++;
a[top] = str.charAt(i);
}
}
}
}
for (; top != -1; ) {
ans[j] = a[top] + "";
j++;
top--;
}
return ans;
}
(3)计算后缀表达式
public String Result(String str[]) {
String Result[] = new String[100];
int Top = -1;
for (int i = 0; str[i] != null; i++) {
if ("+-x÷".indexOf(str[i]) < 0) {
Top++;
Result[Top] = str[i];
}
if ("+-x÷".indexOf(str[i]) >= 0) {
double x, y, n;
x = Double.parseDouble(Result[Top]);
Top--;
y = Double.parseDouble(Result[Top]);
Top--;
if ("-".indexOf(str[i]) >= 0) {
n = y - x;
Top++;
Result[Top] = String.valueOf(n);
}
if ("+".indexOf(str[i]) >= 0) {
n = y + x;
Top++;
Result[Top] = String.valueOf(n);
}
if ("x".indexOf(str[i]) >= 0) {
n = y * x;
Top++;
Result[Top] = String.valueOf(n);
}
if ("÷".indexOf(str[i]) >= 0) {
if (x == 0) {
String s = "ERROR";
return s;
} else {
n = y / x;
Top++;
Result[Top] = String.valueOf(n);
}
}
}
}
return Result[Top];
}
四.最终项目实现
项目完整代码:
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Calculator extends JFrame implements ActionListener {
private String[] KEYS = {"c", "(", ")", "+", "7", "8", "9", "-", "4", "5", "6", "x", "1", "2", "3", "÷", ".", "0", "="};
private JButton keys[] = new JButton[KEYS.length];
private JTextField resultText = new JTextField("0.0");
private String b = "";
/**
* @point 若正在输入运算数(即非运算符),则point生效,
* 用于标记当前运算数是否已经输入小数点,以保证
* 每个运算数只能有一个小数点。
*/
private boolean point = false;
private JTextArea History = new JTextArea();// 历史记录文本框初始值设为空
private JLabel label = new JLabel("历史记录");
public Calculator() {
super("计算器");
this.setLayout(null);//设置布局管理器为默认值
resultText.setBounds(20, 5, 255, 40);
resultText.setHorizontalAlignment(JTextField.RIGHT);//右对齐
resultText.setEditable(false);
this.add(resultText);
History.setBounds(300, 30, 200, 250);// 设置文本框大小
History.setAlignmentX(LEFT_ALIGNMENT);// 文本框内容左对齐
History.setEditable(false);// 文本框不允许修改结果
label.setBounds(300, 5, 100, 20);//设置标签位置及大小
History.setLineWrap(true);//自动换行
History.setWrapStyleWord(true);//换行不断字
this.add(History);//将面板添加到总窗体中
this.setLayout(null);
this.add(label);
/**设置按钮
*
*/
int x = 20, y = 55;//按钮布局
for (int i = 0; i < KEYS.length; i++) {
keys[i] = new JButton();
keys[i].setText(KEYS[i]);
keys[i].setBounds(x, y, 60, 40);
if (x < 215) {
x += 65;
} else {
x = 20;
y += 45;
}
this.add(keys[i]);
}
for (int i = 0; i < KEYS.length; i++) {
keys[i].addActionListener(this);//设置监听
}
this.setResizable(false);
this.setBounds(500, 200, 520, 320);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();//命令实现
if (label == "=") {
resultText.setText(this.b);
History.setText(History.getText() + resultText.getText());
String s[] = operation(this.b);
String result = Result(s);
this.b = result + "";
resultText.setText(this.b);
History.setText(History.getText() + "=" + resultText.getText() + "\n");//同步历史记录
} else if (label == "c") {
this.b = "";
resultText.setText("0");
} else if (label == ".") {
char a = label.charAt(0);
if (point) {//按钮失效
return;
} else if (b.isEmpty()) {//自动补零
b += "0.";
point = true;
} else {
char t = b.charAt(b.length() - 1);
if (t == '+' || t == '-' || t == 'x' || t == '÷') {
b += "0.";
point = true;
} else if (t == '.') {
point = true;
} else {
b += ".";
point = true;
}
}
point = false;//重置
}else if(label=="+"||label=="-"||label=="x"||label=="÷") {//符号限制
char s = b.charAt(b.length() - 1);
if (!b.isEmpty() && (s == '+' || s == '-' || s == 'x' || s == '÷')) { //当已经输入一个运算符时,再次输入视为运算符更新
b = b.substring(0, b.length() - 1) + label;
}
else {
b += label;
}
}
else {
this.b = this.b + label;
resultText.setText(this.b);
}
}
private String[] operation(String str) {
String s = "";
char a[] = new char[100];
String ans[] = new String[100];
int top = -1, j = 0;
/**含负数运算的实现
*
*/
for (int i = 0; i < str.length()-1; i++) {
if (str.charAt(i) == '(' && str.charAt(i + 1) == '-') { //将“(-”转化为“(0-”
str = str.substring(0, i + 1) + "0" + str.substring(i + 1, str.length());
}
}
for (int i = 0; i < str.length(); i++) {
if ("0123456789.".indexOf(str.charAt(i)) >= 0) {
s = "";
for (; i < str.length() && "0123456789.".indexOf(str.charAt(i)) >= 0; i++) {
s = s + str.charAt(i);
}
i--;
ans[j] = s;
j++;
} else if ("(".indexOf(str.charAt(i)) >= 0) {
top++;
a[top] = str.charAt(i);
} else if (")".indexOf(str.charAt(i)) >= 0) {
for (; ; ) {
if (a[top] != '(') {
ans[j] = a[top] + "";
j++;
top--;
} else {
top--;
break;
}
}
} else if ("x÷".indexOf(str.charAt(i)) >= 0) {
if (top == -1) {
top++;
a[top] = str.charAt(i);
} else {
if ("x÷".indexOf(a[top]) >= 0) {
ans[j] = a[top] + "";
j++;
a[top] = str.charAt(i);
} else if ("(".indexOf(a[top]) >= 0) {
top++;
a[top] = str.charAt(i);
} else if ("+-".indexOf(a[top]) >= 0) {
top++;
a[top] = str.charAt(i);
}
}
} else if ("+-".indexOf(str.charAt(i)) >= 0) {
if (top == -1) {
top++;
a[top] = str.charAt(i);
} else {
if ("x÷".indexOf(a[top]) >= 0) {
ans[j] = a[top] + "";
j++;
a[top] = str.charAt(i);
} else if ("(".indexOf(a[top]) >= 0) {
top++;
a[top] = str.charAt(i);
} else if ("+-".indexOf(a[top]) >= 0) {
ans[j] = a[top] + "";
j++;
a[top] = str.charAt(i);
}
}
}
}
for (; top != -1; ) {
ans[j] = a[top] + "";
j++;
top--;
}
return ans;
}
public String Result(String str[]) {
String Result[] = new String[100];
int Top = -1;
for (int i = 0; str[i] != null; i++) {
if ("+-x÷".indexOf(str[i]) < 0) {
Top++;
Result[Top] = str[i];
}
if ("+-x÷".indexOf(str[i]) >= 0) {
double x, y, n;
x = Double.parseDouble(Result[Top]);
Top--;
y = Double.parseDouble(Result[Top]);
Top--;
if ("-".indexOf(str[i]) >= 0) {
n = y - x;
Top++;
Result[Top] = String.valueOf(n);
}
if ("+".indexOf(str[i]) >= 0) {
n = y + x;
Top++;
Result[Top] = String.valueOf(n);
}
if ("x".indexOf(str[i]) >= 0) {
n = y * x;
Top++;
Result[Top] = String.valueOf(n);
}
if ("÷".indexOf(str[i]) >= 0) {
if (x == 0) {
String s = "ERROR";
return s;
} else {
n = y / x;
Top++;
Result[Top] = String.valueOf(n);
}
}
}
}
return Result[Top];
}
public static void main(String arg[]) {
Calculator c = new Calculator();
}
}
运行界面: