用栈来实现多位数的表达式计算
代码实现
我的想法:
- 用两个数组来装,把String直接用正则表达式划分为对应的数组
- 然后转成整型代入计算
我的代码:
package stack;
public class Calculater {
public static void main(String[] args) {
String expression = "7235*1235+3235+2235/1235-2*";
//创建两个栈,分别为数栈和符号栈
//没有必要像上次一样创建两个类,在分别对应类创建对应的栈
NSStack numStack = new NSStack(20);
NSStack operStack = new NSStack(20);
String[] str = null;
str = expression.split("[*/+-]");
System.out.println(str[1]);
System.out.println(str.length);
//定义相关变量
int index = 0;
//扫描索引
char ch = ' ';
//用于承接扫描的单个字符
int num1 = 0;
int num2 = 0;
//int oper = 0;
//为什么定义符号位0,还为int型
int res = 0;//结果
int i = 0;
//用来判断是否输入相应的数字
while (true){
//ch = expression.substring(index,index + 1).charAt(0);
//没有必要加上substring的方法生成一个子字符串
ch = expression.charAt(index);
//判断ch是什么
if(operStack.isOper(ch)){
//问题来了,如果是多位数,他会出现一位数加一下的情况
//如何把多位数看作是一个数扫描的时候
numStack.push(Integer.parseInt(str[i]));
System.out.println(str[i]);
i++;
//如果是运算符,总共是三中情况
//情况一;符号栈为空,直接加入
if(operStack.isEmpty()){
operStack.push(ch);
//好吧!我忘记了,低转高是自动的,不需要类型强转
}else if(operStack.priority(operStack.top()) < operStack.priority(ch) ){
//情况二:符号栈不为空,并且输入的运算符优先级比符号栈里面的优先级要高
operStack.push(ch);
}else{
//情况三:符号栈不为空,并且输入的运算符优先级比符号栈里面的低
num1 = numStack.pop();
num2 = numStack.pop();
res = numStack.cal(num1,num2,operStack.pop());
operStack.push(ch);
//符号入栈,别忘记
numStack.push(res);
//结果入栈,这个老是忘记
}
}
//放哪?放在判断语句之前,已经是倒数第二个,那就最后一个少判断一次
//放在判断语句之后,倒数第二个,最后一个执行完了才会再继续运行
//循环完毕的条件
if(index == (expression.length() - 1)){
break;
}
index ++;
}
//检索完毕开始运行站内的符号和数字
while (true){
if(operStack.isEmpty()){
break;
}
//判断为空没必要再用top指针,直接有对应的方法
num1 = numStack.pop();
num2 = numStack.pop();
res = operStack.cal(num1,num2,operStack.pop());
numStack.push(res);
}
System.out.println(expression + " " + numStack.pop());
}
}
class NSStack{
int maxSize;
int top = -1;
int[] ss;
public NSStack(int maxSize) {
this.maxSize = maxSize;
ss = new int[maxSize];
}
public boolean isEmpty(){
return top == -1;
}
public boolean isFull(){
return top == (maxSize - 1);
}
public void push(int m){
if(isFull()){
return;
}
top ++;
ss[top] = m;
}
public int pop(){
if(isEmpty()){
return 0;
}
int temp = ss[top];
top --;
return temp;
}
public int top(){
return ss[top];
}
//优先级用数字表示,数字越大,优先级越高
public int priority(int oper){
if(oper == '*' || oper == '/'){
//这里真心没看懂,我知道是转换成对应的unicode码
//但是你在走索的时候就是用的char,为啥在判定优先级的时候
//不用,要去用int.很麻烦,虽然确实也可以
return 1;
}else if(oper == '+' || oper == '-'){
return 0;
}else{
return -1;
}
}
//判断是不是一个运算符
public boolean isOper(char val){
return val == '*' || val == '-' || val == '+' || val == '/'||val == '=';
}
//难道还有等号?应该是吧!没有!他是一个一个string.charAt()
//来遍历表达式,获取符号,比我想得简单
//计算方法
public int cal(int num1 ,int num2,int oper){
int res = 0;
switch (oper){
case '+':
res = num1 + num2;
System.out.println(num1 + "+" + num2 + "=" + res);
break;
case '-':
res = num2 - num1;
System.out.println(num2 + "-" + num1 + "=" + res);
break;
case '*':
res = num1 * num2;
System.out.println(num1 + "*" + num2 + "="+ res);
break;
case '/':
res = num2 / num1;
System.out.println(num2 + "/" + num1 + "="+ res);
break;
default:
break;
}
return res;
//运算注意顺序,加法和乘法是没有的,减法和除法是有的
}
}
问题:
- 因为数字的进栈和出栈是根据符号而来的,将字符串拆分成数字直接输入,两个问题面对。
- 如果原来的方式扫描,你如何做到扫瞄完完整的数字在添加而不是扫描到一个就添加一个。
- 换成我写的方式,数字和符号的添加方式就变了,不再是来一个数字,添加一下,而是有一个符号就添加一下,最后一个数字不能进栈了。想用一个等号链接,但是好像没找到相应的正则表达式
答:去看看下面的,第一个问题不是问题,判断是否输入有两种方式,一种是遇到了符号,一种是数组的索引到头了。不是为空!话说就算为空,那也是默认值,那你也可以算出来,char的默认值是什么?/00000
教程代码:
package stack;
public class Calculater {
public static void main(String[] args) {
String expression = "7235*1235+3235+2235/1235-2*";
//创建两个栈,分别为数栈和符号栈
//没有必要像上次一样创建两个类,在分别对应类创建对应的栈
NSStack numStack = new NSStack(20);
NSStack operStack = new NSStack(20);
String[] str = null;
int index = 0;
//扫描索引
char ch = ' ';
//用于承接扫描的单个字符
int num1 = 0;
int num2 = 0;
//int oper = 0;
//为什么定义符号位0,还为int型
int res = 0;//结果
String keepNum = "";
//用于拼接多位数
while (true){
//ch = expression.substring(index,index + 1).charAt(0);
//没有必要加上substring的方法生成一个子字符串
ch = expression.charAt(index);
//判断ch是什么
if(operStack.isOper(ch)){
//如果是运算符,总共是三中情况
//情况一;符号栈为空,直接加入
if(operStack.isEmpty()){
operStack.push(ch);
//好吧!我忘记了,低转高是自动的,不需要类型强转
}else if(operStack.priority(operStack.top()) < operStack.priority(ch) ){
//情况二:符号栈不为空,并且输入的运算符优先级比符号栈里面的优先级要高
operStack.push(ch);
}else{
//情况三:符号栈不为空,并且输入的运算符优先级比符号栈里面的低
num1 = numStack.pop();
num2 = numStack.pop();
res = numStack.cal(num1,num2,operStack.pop());
operStack.push(ch);
//符号入栈,别忘记
numStack.push(res);
//结果入栈,这个老是忘记
}
}else{
keepNum += ch;
if(index == expression.length() - 1){
numStack.push(Integer.parseInt(keepNum));
}else{
//判断下一位是不是数字,如果是数字
// 就继续扫描,如果是运算符就入栈
//数以这里是看后一位,而不改变index的值
if(operStack.isOper(expression.charAt(index + 1))){
numStack.push(Integer.parseInt(keepNum));
//重要,记得清空keepNum
keepNum = "";
}
}
}
//放哪?放在判断语句之前,已经是倒数第二个,那就最后一个少判断一次
//放在判断语句之后,倒数第二个,最后一个执行完了才会再继续运行
//循环完毕的条件
if(index == (expression.length() - 1)){
break;
}
index ++;
}
//检索完毕开始运行站内的符号和数字
while (true){
if(operStack.isEmpty()){
break;
}
//判断为空没必要再用top指针,直接有对应的方法
num1 = numStack.pop();
num2 = numStack.pop();
res = operStack.cal(num1,num2,operStack.pop());
numStack.push(res);
}
System.out.println(expression + " " + numStack.pop());
}
}
class NSStack{
int maxSize;
int top = -1;
int[] ss;
public NSStack(int maxSize) {
this.maxSize = maxSize;
ss = new int[maxSize];
}
public boolean isEmpty(){
return top == -1;
}
public boolean isFull(){
return top == (maxSize - 1);
}
public void push(int m){
if(isFull()){
return;
}
top ++;
ss[top] = m;
}
public int pop(){
if(isEmpty()){
return 0;
}
int temp = ss[top];
top --;
return temp;
}
public int top(){
return ss[top];
}
//优先级用数字表示,数字越大,优先级越高
public int priority(int oper){
if(oper == '*' || oper == '/'){
//这里真心没看懂,我知道是转换成对应的unicode码
//但是你在走索的时候就是用的char,为啥在判定优先级的时候
//不用,要去用int.很麻烦,虽然确实也可以
return 1;
}else if(oper == '+' || oper == '-'){
return 0;
}else{
return -1;
}
}
//判断是不是一个运算符
public boolean isOper(char val){
return val == '*' || val == '-' || val == '+' || val == '/'||val == '=';
}
//难道还有等号?应该是吧!没有!他是一个一个string.charAt()
//来遍历表达式,获取符号,比我想得简单
//计算方法
public int cal(int num1 ,int num2,int oper){
int res = 0;
switch (oper){
case '+':
res = num1 + num2;
System.out.println(num1 + "+" + num2 + "=" + res);
break;
case '-':
res = num2 - num1;
System.out.println(num2 + "-" + num1 + "=" + res);
break;
case '*':
res = num1 * num2;
System.out.println(num1 + "*" + num2 + "="+ res);
break;
case '/':
res = num2 / num1;
System.out.println(num2 + "/" + num1 + "="+ res);
break;
default:
break;
}
return res;
//运算注意顺序,加法和乘法是没有的,减法和除法是有的
}
}
总结对比:
- 教程思路,如果不断扫描,如果下一个数是数字,那就再字符串之后拼接。如果不是,那就有两种情况,一种是遇到符号,一种是到达栈的末尾,都是入栈,然后清空字符串