一、引言
看着自己的写的文章被很多人看,心里觉得暖暖的,一丝丝的成就感,激励着我坚持每天抽点时间写点对自己有用,对大家有用的文章。谢谢大家的关注,我会继续坚持努力。同时也写给未来的自己。言归正传,昨天参加了百度的在线笔试题,看到几道题目,拿出来和大家分享。
二、题目描述
编写一个四则运算计算器。
就是输入一个数学表达式,给出计算结果。如:输入1*5-10+15 输出:10.
原题截图(可能有点看不清):
三、代码
先把代码贴出来,再逐步分析:顺便说一句,我是用java来实现的
package test;
import java.util.Scanner;
import java.util.Stack;
public class BaiduTest {
private static Stack<Character> opeStack = new Stack<Character>();
private static Stack<Integer> numStack = new Stack<Integer>();
private static StringBuilder in = new StringBuilder();
private static StringBuilder number = new StringBuilder();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
System.out.println(cal(sc.nextLine()));
}
sc.close();
}
public static int cal(String input) {
in.append(input);
while (in.length() > 0) {
char temp = in.charAt(0);
in.delete(0, 1);//读一位,删除一位,从左至右
if (temp > '0' && temp < '9') {
number.append(temp);//如果temp是数字,则追加到number上
} else {
if (!"".equals(number.toString())) {
//如果number不为空,则将number加入到数字堆栈
int num = Integer.parseInt(number.toString());
numStack.push(num);
number.delete(0, number.length());//清空number
}
while (!opeStack.isEmpty() && !compare(temp)) {//如果操作栈不为空并且compare返回为false,则进行计算
int num2 = numStack.pop();
int num1 = numStack.pop();
char ope = opeStack.pop();
cal0(ope, num1, num2);//计算
}
if (temp != '#' && compare(temp)) {//如果是
opeStack.push(temp);//如果栈空或者上一个操作符是+、-,并且temp是*、/时,将temp入栈
}
}
}
//算式读完了,将最后一个数入栈
if (number.length() > 0) {
int num = Integer.parseInt(number.toString());
numStack.push(num);
}
//按入栈顺序计算算式
while (!opeStack.isEmpty()) {
int num2 = numStack.pop();
int num1 = numStack.pop();
cal0(opeStack.pop(), num1, num2);
}
return numStack.pop();//将最后的计算结果返回
}
public static void cal0(char ope, int num1, int num2) {
//进行两个数的计算。并将计算结果作为下一个次的操作数
switch (ope) {
case '+':
numStack.push(num1 + num2);
break;
case '-':
numStack.push(num1 - num2);
break;
case '*':
numStack.push(num1 * num2);
break;
case '/':
numStack.push(num1 / num2);
break;
}
}
public static boolean compare(char operation) {
if (opeStack.isEmpty())
return true;
char last = opeStack.peek();//获取操作栈栈顶元素,未出栈
switch (operation) {
//如果是下一个计算是+、-计算,则返回false,并计算上一个操作
//如:读到1+2+3,当读到第二个+时,可先计算出1+2的值了
case '+':
return false;
case '-':
return false;
case '*':
//如果下一个计算是*、/,并且上一个计算不是+、-,则可以进行上一个计算,如:读到:1*2/9,当读到/时,则可以先计算1*2
//如果下一个计算是*、/时,并且上一个计算是+、-,则不进行计算,继续向前读,如读到1+2*3,当读到*时,则不进行1+2的计算,继续读算式
if (last == '+' || last == '-')
return true;
return false;
case '/':
if (last == '+' || last == '-')
return true;
return false;
}
return true;
}
}
四、代码分析
(1)首先如何获取输入?
Java的标准输入用Scanner 用来获取标准输入,Scanner每次获取一整行scan.nextLine(),拿到了一个数学表达式就该处理了;
(2)如何将一个字符串解析为一个表达式?
先将String转为StringBuilder,StringBuilder提供了更加方便操作字符串的方法,而且节省内存。
按位读取字符,如果是数字,则写入StringBuilder number,如果是连续的数字,则追加再后面,如12+……。
(3)如何确定合适进行算式计算?
四个符号就可以确定:如1+1+,当读到第二个+时,则可以进行前一个算式。如果是1+1*,当读到*时,不能进行第一个算式的计算,如果是1*1+,当读到+时,可以进行第一个算式计算,如果是1*1*时,当读到第二个算式时,可以计算第一个算式的计算。总共就以上四种情况,当无法进行第一个算式时则继续读入算式,读到下个时,可以以此进行上一个判断。
(4)计算结果如何处理
计算结果则压入栈顶做为下一次计算的一个操作数。
五、总结
想清楚以上的几个问题,基本就可以写出程序了,大家试试吧。