牛客一位大神写的,看了一下午才看懂,核心是递归算法,记录下注释
给定一个字符串描述的算术表达式,计算出结果值。
输入字符串长度不超过100,合法的字符包括”+, -, *, /, (, )”,”0-9”,字符串内容的合法性及表达式语法的合法性由做题者检查。本题目只涉及整型计算。
输入描述:
输入算术表达式
输出描述:
计算出结果值
示例1
输入:
-3*(7-2)-5
输出:
-20
#include <string>
#include <iostream>
#include <stack>
using namespace std;
int pos = 0;
int result(const string& input)
{
int num = 0;
char opt = '+'; //输入的第一个数字如果为正数,则默认为+运算符
stack<int> stk; //初始化stack容器
int len = input.size(); //获取输入字符串长度
//从左往右开始遍历字符串
while (pos < len)
{
//如果是 '(',[pos]右移一位,递归,直到下一个')'
if (input[pos] == '(')
{
pos++;
num = result(input); //接')'处跳出并返回的递归结果,继续运算
}
//
while (pos < len && isdigit(input[pos]))
{
//遍历到连续数字,从左往右每个数字依次传入。传入第一个数字时,num为第一个数,传入第二个数字时,num*10 并加上第二个数字。
//以后每次传入数字时都是上次的num*10加上新数字,知道遍历到非数字为止。并且每次位置右移一次
num = num * 10 + input[pos] - '0'; //输入的数字字符-48转为ascii的十进制数字,'0'是ascii码的48,换成ascii码的0
pos++;
}
//只有+-*/和( )6种,( )已经做了单独处理
//这里执行的是上次被赋值的运算符,本次如果遍历到,则还未赋值,在opt执行完后才会赋值
switch (opt)
{
case '+':
{
stk.push(num); //直接塞进去
break;
}
case '-':
{
stk.push(-num); //直接塞进去
break;
}
case '*':
{
stk.top() *= num; //顶部元素*num
break;
}
case '/':
{
stk.top() /= num; //顶部元素/num
break;
}
}
num = 0;
opt = input[pos]; //此时才将之前可能遍历到的运算符赋值给opt
//递归中遇到')'直接跳出循环,临时执行下面的stack容器操作,计算并返回本次小括号递归的值,执行'('之前的运算
if (input[pos] == ')')
{
pos++;
break;
}
pos++;
}
//执行运算,把本次的stk里面元素全部累加
int sum = 0;
while (!stk.empty())
{
sum += stk.top();
stk.pop();
}
return sum;
}
int main()
{
string str;
cin >> str;
cout << result(str);
return 0;
}