栈可以用来实现表达式的计算 分别用两个栈来存储运算符合运算数,默认#变成表达式的结束操作,现在运算符栈中放入一个#建,以便于后面的匹配,然后遍历
字符串,若是运算符,则与运算符的头元素进行比较,优先级高,则运算数拿出两个,与运算符的头元素进行运算,随后入运算数的栈,在这里没搞明白为什么这个】
遍历到的字符串不用入运算符的栈,若是等于,则表示括号匹配,运算符里面出一个元素,若是小于,则运算符入栈,总体就是这么一个流程
#include<iostream>
#include<stack>
#include<string>
#include<cstring>
using namespace std;
stack<char>Optr;//用于寄存运算符
stack<double>Opnd;//用于寄存操作数或运算结果,运算结果有可能是浮点数
string Exepression;//用于存放表达式
//比较运算符的优先级
char Compare(char a, char b) //返回两算符a和b的优先级关系
{
if ('#' == a)
if ('#' == b)
return '=';
else
return '<';
if ('+' == a || '-' == a)
if ('*' == b || '/' == b || '(' == b)
return '<';
else
return '>';
if ('*' == a || '/' == a)
if ('(' == b)
return '<';
else
return '>';
if ('(' == a)
if (')' == b)
return '=';
else
return '<';
}
//用于计算数值,随后放回栈中
double Calculate(double a, double b, char fuHao) {
switch (fuHao)
{
case '+':return a + b;
case '-':return a - b;
case '*':return a * b;
case '/':return a / b;
default:
break;
}
}
//在字符串中找是不是数字还是运算符
bool isOptr(char c) {
//下面这种字符串从未用过,先敲着再说
//static string operator("+-*/()#");
//if (operator.find(c) == string::npos)
//return false;//找到末尾都没有找到,就是数字
//return true;是算符 *以上这段是从别人那里抄来的,因此自己大意还没搞明白
if (c == '+' || c == '-' || c == '/' || c == '*')
return true;
return false;
}
//用于计算的过程 核心代码 用于求值的过程
double EvaluateExpression() {
//表达式的末尾是‘#’,表示结束
int i = 0, j = 0, num = 0;
while (Exepression[i] != '#' || Optr.top() != '#') {
//如果不是运算符,则计算出数字
if (!isOptr(Exepression[i])) {
num = 0;
while (!isOptr(Exepression[i])) {
num *= 10;
num += Exepression[i] - '0';
++i;
}
Opnd.push(num);
}
else {
switch (Compare(Optr.top(), Exepression[i])) {
//若是<,则运算符优先级较低,将符号放进运算符栈中
case '<':
Optr.push(Exepression[i]);
++i;
break;
//若是等号的话,则脱括号
case '=':
Optr.pop();
++i;
break;
//若是>的话,则把数字栈的头两个值给拿出来,进行计算,随后再把计算好的结果放进数字栈中
case'>':
double a = Opnd.top();
Opnd.pop();
double b = Opnd.top();
Opnd.pop();
//这里在除法的时候会出错,因为a-b是先a在栈里,所以,应该顺序换一下
Opnd.push(Calculate(b, a, Optr.top()));
Optr.pop();
break;
}
}
}
//最后放入#已进行匹配,来匹配运算符的结束
Optr.push('#');
double res = Opnd.top();
Opnd.pop();
return res;
}
int main() {
//先在运算符数组中放入一个运算符#以便与最后的进行匹配,最后输入的字符串也要输入#
cin >> Exepression;
Optr.push('#');
cout << EvaluateExpression();
return 0;
}
先贴上自己的代码,但有bug,以后再改
然后贴上正确的代码
#include <iostream>
#include <string>
#include <cstring>
#include <stack>
using namespace std;
stack<int> opnd; //操作数栈
stack<char> optr; //算符栈
char expression[100]; //用于盛放表达式
char Compare(char a, char b); //返回两算符a和b的优先级关系
int Calculate(int a, int b, char op); //返回计算结果
int EvaluateExpression(); //求值过程
bool IsOptr(char c); //是否是算符
int main()
{
optr.push('#'); //在表达式最左边增设一个'#'构成整个表达式的一对'#'
while(scanf("%s", expression) != EOF)
cout<<"Result:"<<EvaluateExpression()<<endl;
return 0;
}
char Compare(char a, char b) //返回两算符a和b的优先级关系
{
if('#' == a)
if('#' == b)
return '=';
else
return '<';
if('+'==a || '-'==a)
if('*'==b || '/'==b || '('==b)
return '<';
else
return '>';
if('*'==a || '/'==a)
if('(' == b)
return '<';
else
return '>';
if('(' == a)
if(')' == b)
return '=';
else
return '<';
}
int Calculate(int a, int b, char op) //返回计算结果
{
switch(op)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
case '/':
return a/b;
}
}
bool IsOptr(char c)
{
static string oprator("+-*/()#");
if(oprator.find(c) == string::npos)
return false; //不是算符
return true; //是算符
}
int EvaluateExpression() //求值过程
{
int i=0, num=0;
while(expression[i]!='#' || optr.top()!='#')
{
if(!IsOptr(expression[i]))
{ //不是算符,则是操作数
num = 0;
while(!IsOptr(expression[i]))
{ //求得此操作数
num *= 10;
num += expression[i]-'0';
++i;
}
opnd.push(num);
}
else
{
switch(Compare(optr.top(), expression[i]))
{
case '<':
optr.push(expression[i]);
++i;
break;
case '=':
optr.pop();
++i;
break;
case '>':
int a = opnd.top(); opnd.pop();
int b = opnd.top(); opnd.pop();
opnd.push(Calculate(b, a, optr.top())); //注意这里a和b的顺序
optr.pop();
break;
}
}
}
optr.push('#'); //在表达式最左边增设一个'#'构成整个表达式的一对'#'
int res=opnd.top();
opnd.pop();
return res;
}
很奇怪的是在vs上面竟然不能运行,但在DEV上能运行