输入描述:
存在多种数据,每组数据一行,表达式不存在空格
输入
6/2+3+3*4
输出
18
思路:
1.设置运算符的级别: 其中#为0级,$为1级
2.初始化:将#压入op栈,$添加在需要运算的那串字符串后面
3.遍历字符串的过程中 :
遇到数据就用GetNumber()提取出来 并压入data栈中
遇到运算符就比较当前运算符与op的栈顶运算符(算法的核心!!!):
(1)若栈顶算符级别更低,则将当前算符压栈------(此栈顶算符的有关运算推迟进行)
(2)若栈顶算符级别更高或级别相等,------(此栈顶算符的有关运算要立即进行)-------则出栈1个栈顶算符和2个数据,运算后压入data栈。
(3)#和$的作用是:#比所有算符(+-*/)的级别都低,所以(+-*/)都能顺利入栈,(+-*/)比$级别都高, 使得 (+-*/)都能顺利出栈(而运算符的出栈就意味着计算)。 而#比$级别低(#在栈中),所以不会进行运算 这样就理解了第2步的准备工作。
总结简单记忆:
栈顶op < 当前op --------------->当前op入栈
栈顶op >= 当前op -------------->要计算
#include<iostream>
#include<cstdio>
#include<string>
#include<stack>
#include<cctype>
using namespace std;
int Priority(char ch) {
if(ch == '#')
return 0;
else if(ch == '$')
return 1;
else if(ch == '+' || ch == '-')
return 2;
else if(ch == '*' || ch == '/')
return 3;
}
double GetNumber(string str, int &i) {
double num = 0;
while(isdigit(str[i])) {
num = num * 10 + str[i] - '0';
i++;
}
return num;
}
double Calculate(double x, double y, char ch) {
double num = 0;
if(ch == '+')
num = x + y;
else if(ch == '-')
num = x - y;
else if(ch == '*')
num = x * y;
else if(ch == '/')
num = x / y;
return num;
}
int main() {
string str;
while(getline(cin, str)) {
stack<char> op;
stack<double> data;
op.push('#');
str += '$';
int i = 0;
while(i < str.size()) {
if(isdigit(str[i])) {
double nn = GetNumber(str, i);
data.push(nn);
} else {
if(Priority(op.top()) < Priority(str[i])) {
op.push(str[i]);
i++;
} else {
double y = data.top();
data.pop();
double x = data.top();
data.pop();
char ch = op.top();
op.pop();
data.push(Calculate(x, y, ch));
}
}
}
printf("%.0f\n", data.top());
}
return 0;
}
学习到的点:
1.获取数字(不是1位的)
double GetNumber(string str, int &i) { //注意是&i
double num = 0;
while(isdigit(str[i])) {
num = num * 10 + str[i] - '0';
i++;
}
return num;
}
其中isdigit() 的头文件 :#include<cctype>
2.%.0f 代表输出小数点后0位
%.nf 代表输出小数点后n位