您的位置:首页 > 编程语言 > C语言/C++

c/c++表达式求值,即包含加减乘除以及括号的式子(栈)

2017-03-02 17:33 609 查看
首先要了解前缀表达式,中缀表达式,后缀表达式

其实三者的区别用一句话就可概括,中缀表达式是给人算的,前缀,后缀表达式是给计算机计算的

它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。

举例:
(3 + 4) × 5 - 6 就是中缀表达式
- × + 3 4 5 6 前缀表达式
3 4 + 5 × 6 - 后缀表达式

中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。

虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。

下面附上将中缀表达式转换成后缀表达式的过程(因为我不会转成前缀表达式,好吧主要是懒得学两种)

首先将中缀表达式装换为后缀表达式

0.首先声明两个栈s1,s2,具体用处代码中有解释

1.从左到右开始扫中缀表达式,如果遇到数字直接压入s2栈中

1.2,如果遇见左括号,直接压入s1栈中

1.3如果遇见’*‘||‘/‘||’+‘||’-‘,检查s1中是否为空,如果为空或者栈顶为左括号直接压入栈s1,否则如果此运算符的优先级高于s1栈顶的优先级(注意是高于),则入栈,否则将s1栈的运算符压入s2中,知道符合要求。

2,扫完中缀表达式后,如果s1栈不为空,则全部依次压入s2中

3.再将s2中的元素逆序输出。

下面是计算后缀表达试

0.准备一个栈ans

1.0,将后缀表达式从左往右扫,如果为数字则压入ans中

1.1,如果为运算符+ *,则将ans栈顶和次栈顶弹出,进行运算,然后将结果在压入栈ans

1.2,如果运算符* /,则将根据次栈顶,栈顶的顺序进行运算,然后压入栈

2,扫完后,ans栈顶为答案

下面是c++代码,其实风格是c   --.--  这个版本对输入没有进行优化,也就是说只能输入1位的整数,如果想输入负数和小数,s1,s2的栈类型改为string类就行了,再做些细节的处理orz

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<vector>
#include<iostream>
#include<sstream>
using namespace std;
stack<char>s1;//在装换为后缀表达式时,s1用于储存运算符。在计算后缀表达式时,用于储存运算数
stack<char>s2;//在转换为后缀表达式时,s2用于储存临时的后缀表达式,在计算后缀表达式时。用于储存运算符;
string middle;//中缀表达式的存储
string behind;//后缀表达式的存储
void input()
{
cout<<"请输入表达式:(此版本为简单版本,不支持小数的输入,只支持一位数,只支持非负整数的四则运算以及括号)"<<endl;
cin>>middle;
}
int trans_middle_to_behind()//将中缀表达式装换为后缀表达式
{
int len=middle.size();
// cout<<len<<endl;
for(int i=0;i<len;i++)
{
if(middle[i]>='0'&&middle[i]<='9')
{
s2.push(middle[i]);
}
else if(middle[i]=='(')
s1.push(middle[i]);
else if(middle[i]=='+'||middle[i]=='-')
{
if(s1.empty()||s1.top()=='(')
{
s1.push(middle[i]);
}
else
{
while(!s1.empty()&&s1.top()!='(')
{
s2.push(s1.top());
s1.pop();
}
s1.push(middle[i]);
}
}
else if(middle[i]=='*'||middle[i]=='/')
{
if(s1.empty()||s1.top()=='('||s1.top()=='+'||s1.top()=='-')
s1.push(middle[i]);
else if(!s1.empty()&&s1.top()=='*'||s1.top()=='/')
{
while(!s1.empty()&&s1.top()=='*'||s1.top()=='/')
{
s2.push(s1.top());
s1.pop();
}
s1.push(middle[i]);
}
}
else if(middle[i]==')')
{
while(s1.top()!='(')
{
s2.push(s1.top());
s1.pop();
}
s1.pop();
}
else
{
return 1;
}
}
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
// cout<<"wokao"<<endl;
return 0;
}
double cal()//计算后缀表达式的值
{
int len=s2.size();
// cout<<len<<endl;
for(int i=len-1;i>=0;i--)
{
// cout<<s2.top()<<endl;
if(s2.top()>='0'&&s2.top()<='9')
behind[i]=(s2.top()-'0');
else
behind[i]=s2.top();
s2.pop();
}
// cout<<"wofan"<<endl;
stack<double>ans;
for(int i=0;i<len;i++)
{
if(behind[i]>=0&&behind[i]<=9)
ans.push((double)behind[i]);
else
{
double tmp;
if(behind[i]=='+')
{
tmp=0.0;
tmp+=(double)ans.top();
ans.pop();
tmp+=(double)ans.top();
ans.pop();
ans.push(tmp);
}
else if(behind[i]=='*')
{
tmp=1.0;
tmp*=(double)ans.top();
ans.pop();
tmp*=(double)ans.top();
ans.pop();
ans.push(tmp);
}
else if(behind[i]=='/')
{
tmp=(double)ans.top();
ans.pop();
tmp=(double)ans.top()/tmp;
ans.pop();
ans.push(tmp);
}
else
{
tmp=(double)ans.top();
ans.pop();
tmp=(double)ans.top()-tmp;
ans.pop();
ans.push(tmp);
}
}
}
return ans.top();
}
int main()
{
input();
while(trans_middle_to_behind())
{
cout<<"输入有误,请重新输入:"<<endl;
input();
}
cout<<cal()<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息