本程序包含+、-、*、/的优先级运算,包含等于,清除,删除三种功能。
使用到了基础的栈的知识
完整代码在页面底部,传统手艺复制粘贴(手动狗头)可直接运行。
一.页面布局
使用的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 == '-'