简单计算器
Description
计算一个算术表达式的值。(式子中每个数都是一位数,且除法运算时整除,即3/2=1。输入数据保证每个表达式合法。)
Input
有多组测试样例。一个算术表达式占一行。
Output
输出表达式的值。
Sample Input
1+1
2*3
Sample Output
2
6
分析:就是一个含有加减乘除的表达式,并且不含有括号,计算其值。明明是很简单的表达式求值,愣是让我水了几个小时,也是醉了。。。看来真是老了
表达式求值:1、先按照计算法则,给出各运算符的优先级,这个是为了比较两个相邻运算符应该先算哪一个。
2、接下来就是真正的比较计算了,总体的比较思想是开两个栈,一个用来存数字(题目比较水,只是一位的数字),一个用来存运算符。
3、从头到尾扫描一遍表达式,逐个读入数字或运算符,如果是数字,则直接压入数字栈即可;要是运算符,则要考虑以下几种情况:
1.运算符栈为空时,直接进栈即可。
2.若不为空,则比较当前运算符和运算符栈顶运算符的优先级,若栈顶的大,就代表它的优先级比较大,我们就要先把栈顶运算符弹出栈,同时从数字栈中弹出栈顶的两个数字,因为这两个数字就是运算符栈顶元素的两个操作数(这个如果不懂得话,可以手动模拟一下操作步骤,即可明白其间的关系),这点要注意,由于栈的特点,我们取出的数字顺序,是跟原来在运算符两边的位置是相反的,所以计算的时候要调过来。再把计算出的结果压入数字栈。
3.重复步骤3.2,直到当前运算符的优先级大于运算符栈顶运算符的优先级,这时,我们再把当前等待入栈的运算符入栈。
4、重复步骤2,直到表达式扫描完为止。
5、最后,运算符栈里剩的就是优先级相等的运算符了,我们只需要把它们一个一个取出来,按照顺序算出来即可。这个顺序,比上面的简单很多,每次从运算符栈顶弹出一个运算符op,再从数字栈里依次弹出两个数a,b,那么最后计算b op a的值,再将其放入数字栈中,直到运算符栈为空的时候,刚好我们的数字栈中只剩下了一个元素(因为每个运算符都是两个操作数,但是所有的都相邻排列的,所以所有的操作数恰好比运算符多1个),这个就是我们表达式的最终结果。
AC代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define INF 0x7fffffff
#define LL long long
#define LLL(a, b) a<<b
#define RRR(a, b) a>>b
#define MID(a, b) a+(b-a)/2
const int maxn = 10000000 + 10;
int cal(int x, int y, char p){ //计算x op y的值
if(p == '*') return x * y;
else if(p == '/') return x / y;
else if(p == '+') return x + y;
else return x - y;
}
int main(){
#ifdef sxk
freopen("in.txt", "r", stdin); //不用看,从文件读入用的,跟题目无关
#endif // sxk
int n;
int pri[300];
string s;
memset(pri, 0, sizeof(pri)); //初始化优先级数组
pri['*'] = pri['/'] = 3; //设定运算符的优先级
pri['+'] = pri['-'] = 1;
while(cin >> s){ //读入表达式
stack<int> num; //数字栈
stack<char> op; //运算符栈
int len = s.size();
for(int i=0; i<len; i++){
if(s[i] >= '0' && s[i] <= '9') num.push(s[i] - '0'); //是数字,直接压入数字栈
else{ //是运算符
if(!op.size()) op.push(s[i]); //运算符栈空,直接入栈
else{
while(pri[ s[i] ] <= pri[ op.top() ]){ //循环判断,把栈顶优先级不小于当前运算符优先级的运算符全部弹出栈
int x = num.top(); num.pop(); //弹出两个数字
int y = num.top(); num.pop();
char c = op.top(); op.pop(); //弹出运算符
num.push(cal(y, x, c)); //把计算结果压入数字栈
if(op.size() == 0) break; //一定要注意,不判空的话,会报Runtime Erro
}
op.push(s[i]); //再把当前待入栈运算符入栈
}
}
}
while(op.size()){ //最后的计算
int x = num.top(); num.pop();
int y = num.top(); num.pop();
char c = op.top(); op.pop();
num.push(cal(y, x, c));
}
printf("%d\n", num.top()); //栈顶元素,即为表达式的最终结果
}
return 0;
}