一、 需求描述
1、要有友好、易于操作的界面。
2、能够实现输入:数学表达式(数字加、减、乘、除和括号)
输出:表达式的正确结果
3、有错误提醒和报错处理功能。
二、 实现思想
1、 利用队列与堆栈将中缀表达式转化为后缀表达式。
2、 利用堆栈将表达式计算出结果并将结果输出。
3、 利用Jframe设计计算器友好界面。
三、 数据结构设计
(一)、中缀转化为后缀实现
设以‘#’字符作为结束符的中缀算术表达式已经保存在s1字符串中,转换后得到的后缀算术表达式拟存于s2字符串中。由中缀表达式转换为后缀表达式的规则可知:转换前后,表达式中的数值项的次序不变,而运算符的次序发生了变化,由处在两个运算对象的中间变为处在两个运算对象的后面,同时去掉了所有的括号。为了使转换正确,必须设定一个运算符栈,并在栈底放入一个特殊算符,假定为‘#’字符,让它具有最低的运算符优先级,假定为数值0,此栈用来保存扫描中缀表达式得到的暂不能放入后缀表达式中的运算符,待它的两个运算对象都放入到后缀表达式以后,再令其出栈并写入到后缀表达式中。
把中缀表达式转换为后缀表达式算法的基本思路是从头到尾地扫描中缀表达式中的每个字符,对于不同类型的字符按不情况进行处理。若遇到的是空格则认为是分隔符,不需要进行处理;若遇到的是数字或小数点,则直接写入到s2中,并在每个数值的最后写入一个空格;若遇到的是左括号,则应把它压入到运算符栈中,待以它开始的括号内的表达式转换完毕后再出栈;若遇到的是右括号,则表明括号内的中缀表达式已经扫描完毕,把从栈底直到保存着的对应左括号之间的运算符依次退栈并写入s2串中;若遇到的是运算符,当该运算符的优先级大于栈顶运算符的优先级(加减运算符的优先级设定为1,乘除运算符的优先级设定为2,在栈中保存的特殊运算符‘#’和‘(’的优先级设定为0)时,表明该运算符的后一个运算对象还
没有被扫描并放入到s2串中,应把它暂存于运算符栈中,待它的后一个运算对象从s1串中读出并写入到s2串中后,再另其出栈并写入s2串中;若遇到的运算符的优先级小于等于栈顶运算符的优先级,这表明栈顶运算符的两个运算对象已经被保存到s2串中,应将栈顶运算符退栈并写入到s2串中,对于新的栈顶运算符仍继续进行比较和处理,直到被处理的运算符的优先级大于栈顶运算符的优先级为止,然后另该运算符进栈即可。
按照以上过程扫描到中缀表达式结束符‘#’时,把栈中剩余的运算符依次退栈并写入到后缀表达式中,再向s2写入表达式结束符‘#’,整个转换过程就处理完毕,在s2中就得到了转换成的后缀表达式。
例如,设中缀算术表达式s1为:10+(18+9*3)/15-6#,使用的运算符栈用R表示,则转换过程如下:
1、开始时存放后缀表达式的字符串s2为空,R中压入有‘#’算符,它具有最低的优先级0:
#
2、当扫描到s1中的左括号时,s2和R中的数据变化如下:
1 0
# + (
3、当扫描到s1中的数值3时,s2和R中的数据变化为:
1 0 1 8 9 3
# + ( + *
4、当扫描到s1中的右括号时,s2和R变为:
1 0 1 8 9 3 * +
# +
5、当扫描到s1中的数值15时,s2和R又变为:
1 0 1 8 9 3 * + 1 5
# + /
6、当扫描到s1中的‘#’字符时,s2和R为:
1 0 1 8 9 3 * + 1 5 / + 6
# -
7、当整个处理过程结束后,R栈为空,s2为:
1 0 1 8 9 3 * + 1 5 / + 6 - #
(二)利用堆栈计算后缀表达式结果
对后缀表达式求值比直接对中缀表达式求值简单。在后缀表达式中,不需要括号,而且操作符的优先级也不再起作用了。可以用如下算法对后缀表达式求值:
1、初始化一个空堆栈
2、从左到右读入后缀表达式
3、如果字符是一个操作数,把它压入堆栈。
4、如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果不能够弹出两个操作数,后缀表达式的语法就不正确。
5、到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
四、 功能设计
1、main类
是程序的核心类,也是入口类。
(1)对成员变量的初始化,包括存放表达式的字符串length、用来存放后缀表达式的数组output[]、用来存放处理完毕表达式的数组input[],以及一些为了将String类型的表达式字符串字符中数字与符号分开的必要的成员变量的声明等。
(2)核心代码,中缀转化为后缀
private String[] transPostExp(){
for (int i = 0 ; i < ln ; i++){
postExpStack.displayStack("no" + i + " stack is: ");
String ch = input[i];
System.out.println(ch);
if (ch.equalsIgnoreCase("+")||ch.equalsIgnoreCase("-"))
doOper1(ch,1);
else if(ch.equalsIgnoreCase("*")||ch.equalsIgnoreCase("/"))
doOper1(ch,2);
else if(ch.equalsIgnoreCase("("))
postExpStack.push(ch);
else if (ch.equalsIgnoreCase(")"))
doOper2();
else
output[n++]=ch;
}
while(!postExpStack.isEmpty()){
if(postExpStack.top().equalsIgnoreCase("#"))
postExpStack.pop();
else
output[n++] = postExpStack.pop();
}
return output;
}
(3)优先级判断:分别有两个方法,doOper1和doOper2,对不同符号的优先级进行判断,并作出相应操作。
(4)进行计算的calculate类,利用堆栈对表达式进行计算并输出结果。
2、NewJFrame类,继承自javax.swing.JFrame,完成与图形化界面有关的设计。
3、Stack类,有关堆栈的基本操作,方便其他类中对堆栈相关操作的方法调用。
五、 运行环境说明
Eclipse运行环境
六、 操作说明
1、本计算器支持十进制运算。
2、数字键0——9用于数字的键入,可键入个位数,也可连续键入多位数。
3、“(”及“)”用于左右括号的运算,加上括号即进行优先运算,内层的括号先于外层括号计
算,有括号的计算先于没有括号的。
4、“.”用于小数点的键入
5、“+”“-”“*”“/”“=”分别用于加、减、乘、除及相等的运算。
6、Del键位逐字删除,C为清屏。
7、如出现违规操作会有报错提醒。
七、 系统测试用例
1、输入:((2*3)*2+4*2进制转十进制在线计算器(23+3))/2
输出结果:58,如图所示。
2、输入如()、(*5)+2、(2+3))、((2+3)、3.33等非法表达式均会得到报错,如图所示
八、 收获及体会
1、 对Java数据结构有关堆栈和队列的内容有了更加深入和深刻的体会。
2、 更加熟练了对Eclipse环境编写代码的运用。
3、 编程过程中查了相关资料,提高了搜集和整理资料的能力。
4、 编写两个程序提高了对时间的统筹和策划能力。
5、 提高了对开发文档的书写能力。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论