问题描述:
在计算机中,算术表达式由常量、变量、运算符和括号组成。由于不同的运 算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行,在程序设计时,借助栈实现。
表达式求值程序分析:
主要利用栈和已知的算符优先关系,实现对算术四则运算的求值,在求值中运用栈、运算栈、输入字符和主要操作的变化过程。该程序相当于一个简单的计算机计算程序,只进行简单的加减乘除和带括号的四则运算。
概要设计:
a先乘除后加减;
b从左到右计算;
c 先括号内,后括号外。
为了实现运算符有限算法,在程序中使用了两个工作栈。
分别是:运算符栈,操作数栈.
基本思想:
1.若运算符栈没有元素则运算符直接入栈
2.若运算符栈有元素,若栈顶运算符优先级小于将要入栈的运算符,则继续入栈,否则栈顶运算符出栈且进行相应的运算操作(至少执行一次运算操作)后再将要入栈的运算符入栈
3.左括号直接入栈不需要判断,虽然栈优先级最低
4.当操作符右括号时。若栈顶运算符是左括号,则栈顶运算符出栈且右括号不入栈;若栈顶运算符不是左括号则栈顶运算符出栈执行相应的运算操作,然后出栈左括号且该右括号不入栈 【注意:一般若栈顶元素不是左括号,出一次栈后,左括号就是栈顶元素了】
程序运算符优先级安排:
int priority(string opt)
{
int p = 0;
if (opt == "(")
p = 1;
if (opt == "+" || opt == "-")
p = 2;
if (opt == "*" || opt == "/")
p = 3;
return p;
}
运算例子:
(4+3*5-(4/4+1)-3*5)
=> (4+15-(4/4+1)-3*5
=> (19-(1+1))-3*5
=> (19-2)-3*5
=> 17-3*5
=> 17-15
=> 2
代码:
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <cstdlib>
using namespace std;
int priority(string opt)
{
int p = 0;
if (opt == "(")
p = 1;
if (opt == "+" || opt == "-")
p = 2;
if (opt == "*" || opt == "/")
p = 3;
return p;
}
void calculate(stack<int> &opdstack, string opt)
{
if (opt == "+")
{
int ropd = opdstack.top();
opdstack.pop();
int lopd = opdstack.top();
opdstack.pop();
int result = lopd + ropd;
opdstack.push(result);
}
if (opt == "-")
{
int ropd = opdstack.top();
opdstack.pop();
int lopd = opdstack.top();
opdstack.pop();
int result = lopd - ropd;
opdstack.push(result);
}
if (opt == "*")
{
int ropd = opdstack.top();
opdstack.pop();
int lopd = opdstack.top();
opdstack.pop();
int result = lopd * ropd;
opdstack.push(result);
}
if (opt == "/")
{
int ropd = opdstack.top();
opdstack.pop();
int lopd = opdstack.top();
opdstack.pop();
int result = lopd / ropd;
opdstack.push(result);
}
}
int calcuExpression(vector<string> vec)
{
stack<int> stack_opd;
stack<string> stack_opt;
for (auto i = 0; i != vec.size(); ++i)
{
string token = vec[i];
if (token == "+" || token == "-" || token == "*" || token == "/")
{
if (stack_opt.size() == 0)
stack_opt.push(token);
else
{
int token_p = priority(token);
string top_opt = stack_opt.top();
int opt_p = priority(top_opt);
if (token_p > opt_p)
stack_opt.push(token);
else
{
while (token_p <= opt_p)
{
stack_opt.pop();
calculate(stack_opd, top_opt);
if (stack_opt.size() > 0)
{
top_opt = stack_opt.top();
opt_p = priority(top_opt);
}
else
break;
}
stack_opt.push(token);
}
}
}
else if (token == "(")
stack_opt.push(token);
else if (token == ")")
{
while (stack_opt.top() != "(")
{
string top_opt = stack_opt.top();
calculate(stack_opd, top_opt);
stack_opt.pop();
}
stack_opt.pop();
}
else
stack_opd.push(atoi(token.c_str()));//函数返回一个指向正规C字符串的指针, 内容与本string串相同
}
while (stack_opt.size() != 0)
{
string top_opt = stack_opt.top();
calculate(stack_opd, top_opt);
stack_opt.pop();
}
return stack_opd.top();
}
int main()
{
vector<string> tokens = { "(", "4", "+", "3", "*", "5", "-", "(", "4", "/", "4", "+", "1", ")", ")", "-", "3", "*", "5" };
for (auto i = 0; i != tokens.size(); ++i)
cout << tokens[i] << " ";
cout << endl;
cout << calcuExpression(tokens) << endl;
system("pause");
return 0;
}
参考:
http://blog.csdn.net/fengzhanghao23/article/details/47380793
http://blog.163.com/fuchang_he/blog/static/110775491200922410042537/