公式字符串求值
题目描述
给定一个字符串str,str表示一个公式,公式里可以有整数,加减乘除和左右括号,返回公式的计算结果(注意:题目中所有运算都是整型运算,向下取整,且保证数据合法,不会出现除0等情况)。
输入描述:
输出一行字符串,代表 s t r ( 1 ≤ l e n g t h s t r ≤ 1000 ) str(1 \leq length_{str} \leq 1000) str(1≤lengthstr≤1000)(保证str计算的结果不会出现除零,int溢出等情况)。
输出描述:
输出一个整数,代表表达式的计算结果。
示例1
输入
48*((70-65)-43)+8*1
输出
-1816
示例2
输入
3+1*4
输出
7
题解:
表达式求值,一般是将中缀表达式转为后缀表达式,然后在后缀表达式中,使用两个栈,一个保存操作符,一个保存数字,从前往后进行计算即可。
本题也可以这样做,在将中缀表达式转为后缀表达式过程中,需要注意的是运算符的优先级,其中 “(” 优先级最低,其次是 加减 运算符,优先级最高的是 乘除 运算符。
注意:此题会出现负数,遇到 ‘-’ 运算符需要特判一下。
代码:
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1010;
char s[N];
int nums[N];
char ops[N];
int k1, k2;
int grade( char op ) {
if (op == '(') return 1;
if (op == '+' || op == '-') return 2;
if (op == '*' || op == '/') return 3;
return 0;
}
void calc( char op ) {
int y = nums[ k1-- ];
int x = nums[ k1-- ];
int z;
if ( op == '+') z = x + y;
else if ( op == '-' ) z = x - y;
else if ( op == '*' ) z = x * y;
else z = x / y;
nums[ ++k1 ] = z;
}
int solve() {
k1 = k2 = -1;
int top = 0, val = 0;
for (int i = 0; s[i]; ++i) {
if ( s[i] >= '0' && s[i] <= '9' ) {
val = val * 10 + (s[i] & 15);
if ( s[ i+1 ] >= '0' && s[ i+1 ] <= '9' ) continue;
nums[ ++k1 ] = val;
val = 0;
}
else if ( s[i] == '(' ) ops[ ++k2 ] = s[i];
else if ( s[i] == ')' ) {
while ( ops[k2] != '(' ) calc( ops[ k2-- ] );
k2--;
}
else {
if ( s[i] == '-' ) {
if ( i == 0 || s[ i-1 ] == '(' ) {
val = 0, ++i;
while ( s[i] >= '0' && s[i] <= '9' )
val = val * 10 + (s[ i++ ] & 15);
nums[ ++k1 ] = -val;
val = 0, --i;
continue;
}
}
while ( k2 >= 0 && grade( ops[k2] ) >= grade( s[i] ) )
calc( ops[ k2-- ] );
ops[ ++k2 ] = s[i];
}
}
while ( k2 >= 0 ) calc( ops[ k2-- ] );
return nums[0];
}
int main( void )
{
scanf("%s", s);
printf("%d\n", solve());
return 0;
}