本程序包含+、-、*、/的优先级运算,包含等于,清除,删除三种功能。
使用到了基础的栈的知识
完整代码在页面底部,传统手艺复制粘贴(手动狗头)可直接运行。
一.页面布局
使用的WindowBuilder对界面进行布局,简单直接。使用方法:安装WindowBuilder插件,然后在eclipse右键-----Open With-----WindowBuilder Editor-----点击底部Design即可。
没安装WindowBuilder也不影响使用。
所有的按钮都是JButton,输出框是JTextField。
二.栈的设计
分为两个栈,数字栈和符号栈。
Stack<Double> stack1 = new Stack<Double>(); // 数字栈
Stack<Character> stack2 = new Stack<Character>(); // 符号栈
数字栈:
从输入串起始位置开始读取,读取连续数字并保存为double型,若此时读取到小数点,则读取小数点后的连续数字直到遇见+、-、*、/,作为之前整数的小数部分并入栈,否则就直接入栈。
temp = inputFormula.charAt(i); // String 取其某一个元素
if ((temp >= '0' && temp <= '9') || temp == '.'){ //获得各个数字
double sum = temp - '0';
int j = i + 1;
boolean flag = true; //是否为小数
int index = 1; // 记录第几位小数
while(j < inputFormula.length()){ //获得了这个完整的数但是它可能为负数
temp = inputFormula.charAt(j);
if (temp == '.'){ // 如果下一位是小数点
flag = false;
index = 1;
++j;
continue;
}
else if (flag && (temp >= '0' && temp <= '9')){ // 如果下一位是数字
sum = sum * 10 + temp - '0';
++j;
}
else if (!flag && (temp >= '0' && temp <= '9')){ //如果下一位不是数字
sum += Math.pow(0.1,index) * (temp - '0');
index ++;
++j;
}
else break;
} //到此时截止,sum为一个正确的实数
符号栈:
当字符栈为空时,运算符直接入栈;当栈外优先级大于等于栈内优先级,入栈;当栈不为空并且栈外优先级低于栈内优先级,将高优先级的运算先计算了,然后入栈。(此处只有+和*运算,因为我将“-”后面的数保存为负数,将/后的数变为倒数,详情见后面)
else if (temp == '+' || temp == '-' || temp == '*' || temp == '/' ){ // 处理字符
// 当栈中为空时 或者 栈外优先级大于等于栈内优先级,入栈
if (stack2.empty() || getPriority(temp) >= getPriority(stack2.peek().charValue())) // 有优先级的
{
if(temp == '+' || temp == '-')
{
stack2.push('+');
}
else if(temp == '*' ||temp == '/')
{
stack2.push('*');
}
}
else{
// 当栈不为空 并且 栈外优先级低于栈内优先级,将高优先级的运算先计算了,然后入栈。
while(!stack2.empty() && (getPriority(temp) < getPriority(stack2.peek().charValue()))){
char c = stack2.peek().charValue();
stack2.pop();
double num2 = stack1.peek().doubleValue();
stack1.pop();
double num1 = stack1.peek().doubleValue();
stack1.pop();
if (c == '+') stack1.push(num1 + num2);
if (c == '-') stack1.push(num1 + num2);
if (c == '*') stack1.push(num1 * num2);
if (c == '/') stack1.push(num1 * num2);
}
stack2.push(temp); // 实际保存进去的运算符未变,变的是需要计算的几个数
}
}
三.删除处理
分为归零操作和删除末尾字符的操作。
归零操作直接将文本框的内容设置为0即可
删除末尾字符操作是从尾部删除输入串,符合删除条件时删除尾部,当删的剩第一个数的整数部分时,如果这个数绝对值大于十就可以继续删,绝对值小于十再删将值设置为0。
当字符串内含+、-、*、/、.时说明符合删除条件,可以继续删除。
int returnToZero(String getInput)
{
if(getInput.contains(".")||getInput.contains("+")||getInput.contains("-")
||getInput.contains("*")||getInput.contains("/"))
return 1;
return 0;
}
点击事件:
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
inputFormula = textField.getText();
if(returnToZero(textField.getText()) == 1) // 可以删的情况(含加减乘除小数点)
{
textField.setText(textField.getText().substring(0,inputFormula.length()-1));
}
// 此时只剩下整数部分,在范围内则设置为0
else if(Integer.parseInt(textField.getText()) < 10 && Integer.parseInt(textField.getText()) > -10)
{
textField.setText("0");
}
else // 如123 -123
{
textField.setText(textField.getText().substring(0,inputFormula.length()-1));
}
}
});
四.运算逻辑
加减运算
因为是用栈进行保存数据,遵行后进先出的原则,进行减法运算时,取一个运算符“-”和两个数,若为连续的减法运算,倒数第二个数字被当做正数,故此运算逻辑有误。
直接将“-”后的数字保存为负数,所以运算时使用的只是加法规则且运算逻辑正确。
标记负号
if (inputFormula.charAt(i) == '-' ) // 将后一个数负数保存
{
if(i == 0) // 如果第一位是“-”,则传一个0进去,不然数不够用
stack1.push(0.0);
isNegative = 1;
}
存为负数
if (isNegative == 1) // 当标志为1说明sum是一个负数
{
sum = sum * -1;
isNegative = 0;
}
只入栈加号
if(temp == '+' || temp == '-')
{
stack2.push('+');
}
运算
while(!stack2.empty()){
char c = stack2.peek().charValue();
stack2.pop();
double num2 = stack1.peek().doubleValue();
stack1.pop();
double num1 = stack1.peek().doubleValue();
stack1.pop();
if (c == '+') stack1.push(num1 + num2);
if (c == '-') stack1.push(num1 + num2);
if (c == '*') stack1.push(num1 * num2);
if (c == '/') stack1.push(num1 * num2);
}
乘除运算
因为是用栈进行保存数据,遵行后进先出的原则,进行除法运算时,取一个运算符“/”和两个数,若为连续的除法运算,倒数第二个数字被当做被除数,故此运算逻辑有误。
直接将“/”后的数字保存为本身的倒数,所以运算时使用的只是乘法规则且运算逻辑正确。
标记除号-----存为倒数-----只入栈乘号-----运算
代码与加减运算类似,就不上代码了。
五.总结
1.功能的正常使用上完全没有问题,根据用户正确的输入按照运算优先级顺序输出正确结果。
2.用户输入不规范时,由于符号太多,数字栈中的数字出栈完了无法进行运算,所以会报空栈错误,此处有待改进。(如2----3)
六.完整代码
点个赞吧!大哥
package calculator;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.SwingConstants;
import java.awt.event.ActionListener;
import java.util.Stack;
import java.awt.event.ActionEvent;
public class Calculator {
//减法运算有问题
private JFrame frame;
private static JTextField textField;
private static int isNegative = 0; //如果为0则为首字母为负号而不是运算符
private static String inputFormula ;
private static boolean isDivision = false;
Stack<Double> stack1 = new Stack<Double>(); // 数字栈
Stack<Character> stack2 = new Stack<Character>(); // 符号栈
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Calculator window = new Calculator();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Calculator() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setTitle("计算器");
frame.setBounds(100, 100, 345, 342);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 默认退出模式
frame.getContentPane().setLayout(null);
textField = new JTextField(); // 文本框
textField.setHorizontalAlignment(SwingConstants.RIGHT);
textField.setFont(new Font("宋体", Font.PLAIN, 27));
textField.setText("0");
textField.setBounds(14, 0, 296, 45);
frame.getContentPane().add(textField);
textField.setColumns(10);
//为了方便看,将Button的初始化放在一起
JButton btn7 = new JButton("7");
btn7.setBounds(14, 62, 45, 47);
frame.getContentPane().add(btn7);
JButton btn8 = new JButton("8");
btn8.setBounds(73, 62, 45, 47);
frame.getContentPane().add(btn8);
JButton btn9 = new JButton("9");
btn9.setBounds(132, 62, 45, 47);
frame.getContentPane().add(btn9);
JButton btn4 = new JButton("4");
btn4.setBounds(14, 122, 45, 47);
frame.getContentPane().add(btn4);
JButton btn5 = new JButton("5");
btn5.setBounds(73, 122, 45, 47);
frame.getContentPane().add(btn5);
JButton btn6 = new JButton("6");
btn6.setBounds(132, 122, 45, 47);
frame.getContentPane().add(btn6);
JButton btn1 = new JButton("1");
btn1.setBounds(14, 182, 45, 47);
frame.getContentPane().add(btn1);
JButton btn2 = new JButton("2");
btn2.setBounds(73, 182, 45, 47);
frame.getContentPane().add(btn2);
JButton btn3 = new JButton("3");
btn3.setBounds(132, 182, 45, 47);
frame.getContentPane().add(btn3);
JButton btnpoint = new JButton(".");
btnpoint.setBounds(14, 240, 45, 47);
frame.getContentPane().add(btnpoint);
JButton btn0 = new JButton("0");
btn0.setBounds(73, 240, 45, 47);
frame.getContentPane().add(btn0);
JButton btnc = new JButton("C");
btnc.setBounds(132, 240, 45, 47);
frame.getContentPane().add(btnc);
JButton btndivision = new JButton("/");
btndivision.setBounds(194, 240, 45, 47);
frame.getContentPane().add(btndivision);
JButton btnadd = new JButton("+");
btnadd.setBounds(194, 62, 45, 47);
frame.getContentPane().add(btnadd);
JButton btnminus = new JButton("-");
btnminus.setBounds(194, 122, 45, 47);
frame.getContentPane().add(btnminus);
JButton btnmultiply = new JButton("*");
btnmultiply.setBounds(194, 182, 45, 47);
frame.getContentPane().add(btnmultiply);
JButton btnequals = new JButton("=");
btnequals.setBounds(253, 182, 57, 105);
frame.getContentPane().add(btnequals);
JButton btnDelete = new JButton("<--");
btnDelete.setBounds(253, 62, 57, 107);
frame.getContentPane().add(btnDelete);
//以下为各个Button的点击事件
btn7.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("7");
else
textField.setText(textField.getText()+"7");
}
});
btn8.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("8");
else
textField.setText(textField.getText()+"8");
}
});
btn9.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("9");
else
textField.setText(textField.getText()+"9");
}
});
btn4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("4");
else
textField.setText(textField.getText()+"4");
}
});
btn5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("5");
else
textField.setText(textField.getText()+"5");
}
});
btn6.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("6");
else
textField.setText(textField.getText()+"6");
}
});
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("1");
else
textField.setText(textField.getText()+"1");
}
});
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("2");
else
textField.setText(textField.getText()+"2");
}
});
btn3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("3");
else
textField.setText(textField.getText()+"3");
}
});
btn0.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("0");
else
textField.setText(textField.getText()+"0");
}
});
btnpoint.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("0.");
}
});
btnc.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textField.setText("0");
//inputAllOperation = null;
}
});
btndivision.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("0"); //
else
{
textField.setText(textField.getText()+"/");
}
}
});
btnadd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("0"); //
else
{
textField.setText(textField.getText()+"+");
}
}
});
btnminus.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("-"); //
else
textField.setText(textField.getText()+"-");
}
});
btnmultiply.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(textField.getText().equals("0"))
textField.setText("0"); //
else
textField.setText(textField.getText()+"*");
}
});
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
inputFormula = textField.getText();
if(returnToZero(textField.getText()) == 1) // 可以删的情况(含加减乘除小数点)
{
textField.setText(textField.getText().substring(0,inputFormula.length()-1));
}
// 此时只剩下整数部分,在范围内则设置为0
else if(Integer.parseInt(textField.getText()) < 10 && Integer.parseInt(textField.getText()) > -10)
{
textField.setText("0");
}
else // 如123 -123
{
textField.setText(textField.getText().substring(0,inputFormula.length()-1));
}
}
});
btnequals.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
inputFormula = textField.getText();
char temp;
System.out.println(inputFormula);
for (int i = 0; i < inputFormula.length(); ++i) // 遍历所有字符
{
if (inputFormula.charAt(i) == '-' ) // 将后一个数负数保存
{
if(i == 0) // 如果第一位是“-”,则传一个0进去,不然数不够用
stack1.push(0.0);
isNegative = 1;
}
if(inputFormula.charAt(i) == '/')
{
isDivision = true;
}
temp = inputFormula.charAt(i); // String 取其某一个元素
if ((temp >= '0' && temp <= '9') || temp == '.'){ //获得各个数字
double sum = temp - '0';
int j = i + 1;
boolean flag = true; //是否为小数
int index = 1; // 记录第几位小数
while(j < inputFormula.length()){ //获得了这个完整的数但是它可能为负数
temp = inputFormula.charAt(j);
if (temp == '.'){ // 如果下一位是小数点
flag = false;
index = 1;
++j;
continue;
}
else if (flag && (temp >= '0' && temp <= '9')){ // 如果下一位是数字
sum = sum * 10 + temp - '0';
++j;
}else if (!flag && (temp >= '0' && temp <= '9')){ //如果下一位不是数字
sum += Math.pow(0.1,index) * (temp - '0');
index ++;
++j;
}
else break;
} //到此时截止,sum为一个正确的实数
if (isNegative == 1) // 当标志为1说明sum是一个负数
{
sum = sum * -1;
isNegative = 0;
}
if (isDivision) // 当标志为true将其保存为倒数,用以乘法运算
{
sum = 1.0 / sum;
isDivision = false;
}
System.out.println(sum); // sum代表每一个独立的数字
stack1.push(sum); // 进栈
i = j - 1; // 将标签移到数字之后
}
else if (temp == '+' || temp == '-' || temp == '*' || temp == '/' ){ // 处理字符
// 当栈中为空时 或者 栈外优先级大于等于栈内优先级,入栈
if (stack2.empty() || getPriority(temp) >= getPriority(stack2.peek().charValue())) // 有优先级的
{
if(temp == '+' || temp == '-')
{
stack2.push('+');
}
else if(temp == '*' ||temp == '/')
{
stack2.push('*');
}
}
else{
// 当栈不为空 并且 栈外优先级低于栈内优先级,将高优先级的运算先计算了,然后入栈。
while(!stack2.empty() && (getPriority(temp) < getPriority(stack2.peek().charValue()))){
char c = stack2.peek().charValue();
stack2.pop();
double num2 = stack1.peek().doubleValue();
stack1.pop();
double num1 = stack1.peek().doubleValue();
stack1.pop();
if (c == '+') stack1.push(num1 + num2);
if (c == '-') stack1.push(num1 + num2);
if (c == '*') stack1.push(num1 * num2);
if (c == '/') stack1.push(num1 * num2);
}
stack2.push(temp); // 实际保存进去的运算符未变,变的是需要计算的几个数
}
}
}
if (!stack2.empty()){ // 符号栈不为空就一直出
while(!stack2.empty()){
char c = stack2.peek().charValue();
stack2.pop();
double num2 = stack1.peek().doubleValue();
stack1.pop();
double num1 = stack1.peek().doubleValue();
stack1.pop();
if (c == '+') stack1.push(num1 + num2);
if (c == '-') stack1.push(num1 + num2);
if (c == '*') stack1.push(num1 * num2);
if (c == '/') stack1.push(num1 * num2);
}
}
textField.setText((stack1.peek().toString()));
System.out.println(stack1.peek().doubleValue());
stack1.pop(); // 虽然结果出栈了,但它显示在文本框中,仍然会被在此记录,避免栈内有无效数据
}
});
}
public int getPriority(char temp)
{
if (temp == '+') return 3;
if (temp == '-') return 3;
if (temp == '*') return 4;
if (temp == '/') return 4;
return 0;
}
// 专门写一个函数看它是否应该设置为0 包含加减乘除小数点时 可以删
int returnToZero(String getInput)
{
if(getInput.contains(".")||getInput.contains("+")||getInput.contains("-")
||getInput.contains("*")||getInput.contains("/"))
return 1;
return 0;
}
}