之所以写这个,是因为最近在学习C++的过程中,C++primer 第五版 9.6的习题跟这个有关,在网上看看些人的思路,也就做出来了,正好写到博客里面。
原题如下:
使用 stack 处理括号化的表达式。当你看到一个左括号,将其记录下来。当你在一个左括号之后看到一个右括号,从 stack 中 pop 对象,直至遇到左括号,
将左括号也一起弹出栈。然后将一个值(括号内的运算结果)push 到栈中,表示一个括号化的(子)表达式已经处理完毕,被其运算结果所替代。
题目也给了思路,具体上代码:
#include "stdafx.h"
#include<iostream>
#include<queue>
#include<vector>
#include<string>
#include<stack>
using namespace std;
vector<string>prase(char *str) //分离每个符号
{
vector<string>tokens;
int len = strlen(str);
char *p = (char*)malloc((len + 1) * sizeof(char));
int i = 0, j = 0;
while (i < len) //去除空格
{
if (str[i] == ' ')
{
i++;
continue;
}
p[j++] = str[i++];
}
p[j] = '\0';
j = 0;
len = strlen(p);
while (j < len)
{
char temp[2] = { 0 }; //存储符号
string token;
switch (p[j])
{
case '+':
case '*':
case '/':
case '(':
case ')':
temp[0] = p[j];
temp[1] = '\0';
token = temp;
tokens.push_back(token);
break;
case '-':
if (p[j - 1] == ')' || isdigit(p[j - 1])) //不能使用--j,会死循环
{
temp[0] = p[j];
temp[1] = '\0';
token = temp;
tokens.push_back(token);
break;
}
else
{
temp[0] = '$';
temp[1] = '\0';
token = temp;
tokens.push_back(token);
break;
}
default:
i = j;
while (isdigit(p[i]))
i++;
char *operand = (char*)malloc((i - j + 1) * sizeof(char));
memset(operand, 0, i - j + 1);
memcpy(operand, p + j, i - j);
operand[i - j] = '\0';
token = operand;
tokens.push_back(token);
free(operand);
j = i - 1;
break;
}
j++;
}
free(p);
return tokens;
}
int priority(string opd)
{
int level;
if (opd == "$")
level = 3;
else if (opd == "*" || opd == "/")
level = 2;
else if (opd == "+" || opd == "-")
level = 1;
else if (opd == "(" || opd == ")")
level = 0;
return level;
}
void calculate(stack<int>& opdStack, string opt)
{
if (opt == "+")
{
int rOpd = opdStack.top();
opdStack.pop();
int lOpd = opdStack.top();
opdStack.pop();
int result = rOpd + lOpd;
opdStack.push(result);
}
else if (opt == "-")
{
int rOpd = opdStack.top();
opdStack.pop();
int lOpd = opdStack.top();
opdStack.pop();
int result = lOpd - rOpd;
opdStack.push(result);
}
else if (opt == "*")
{
int rOpd = opdStack.top();
opdStack.pop();
int lOpd = opdStack.top();
opdStack.pop();
int result = lOpd * rOpd;
opdStack.push(result);
}
else if (opt == "/")
{
int rOpd = opdStack.top();
opdStack.pop();
int lOpd = opdStack.top();
opdStack.pop();
int result = lOpd / rOpd;
opdStack.push(result);
}
else if (opt == "$")
{
int result = opdStack.top();
opdStack.pop();
result = -result;
opdStack.push(result);
}
}
int computationalExp(char *str)
{
vector<string>tokens = prase(str);
stack<int>opdStack;
stack<string>optStack;
for (int i = 0; i < tokens.size(); i++)
{
string token = tokens[i];
if (token == "+" || token == "-" || token == "*" || token == "/" || token == "$")
{
if (optStack.empty())
{
optStack.push(token);
}
else
{
int tokenPriority = priority(token);
string topOptStack = optStack.top();
int optPriority = priority(topOptStack);
if (tokenPriority > optPriority) //运算操作符优先于栈顶操作符,则入栈
{
optStack.push(token);
}
else
{//否则弹出操作符和操作数进行计算,直至当前操作符优先栈顶操作符时,入栈
while (tokenPriority <= optPriority)
{
calculate(opdStack, topOptStack);
optStack.pop();
if (optStack.size() > 0)
{
topOptStack = optStack.top();
optPriority = priority(topOptStack);
}
else
{
break;
}
}
optStack.push(token);
}
}
}
else if (token == "(")
{
optStack.push(token);
}
else if (token == ")")
{
while (optStack.top() != "(")
{
string topOpt = optStack.top();
calculate(opdStack, topOpt);
optStack.pop();
}
optStack.pop();//弹出"("
}
else
{
opdStack.push(stoi(token));//操作数入栈
}
}
while (optStack.size() != 0)
{
string topOpt = optStack.top();
calculate(opdStack, topOpt);
optStack.pop();
}
return opdStack.top();
}
int main()
{
char *str = "3+5-6*-9/3+(4+3*7)";
cout << computationalExp(str) << endl;
return 0;
}
如有啥问题,请多多指教。