问题描述:一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,
如:#(7+15)*(23-28/4)#。
引入表达式起始、结束符是为了方便。编程利用“算符优先法”求算术表达式的值。
基本要求:从键盘读入一个合法的算术表达式,输出正确的结果;显示输入序列和栈的变化过程,操作数类型扩充到实数。
如计算例题:
结果为:91.9908
#include <bits/stdc++.h>
using namespace std;
void shishu(char a[],int &i,double &c)//检测后面是否有数字
{
double d=0.1;
c=a[i]-'0';
i++;
while('0'<=a[i]&&a[i]<='9')//小数点前操作
{
c=10*c+a[i]-'0';//进行进位操作
i++;
}
if(a[i]=='.')//小数点后操作
{
i++;
while('0'<=a[i]&&a[i]<='9')//进行每次加0.1的多少次方操作
{
c+=(a[i]-'0')*d;
d=0.1*d;
i++;
}
}
}
char youxian(int e1,char e[],char c)//符号优先级判断
{
if(c==')')
return '=';
if(e[e1]=='#')
return '<';
if(c=='(')
return '<';
if(e[e1]=='(')
return '<';
if(e[e1]=='^')
return '>';
if(c=='^')
return '<';
if((e[e1]=='s'||e[e1]=='l')&&(c!='s'&&c!='l'))
return '>';
if(c=='s'||c=='l')
return '<';
if(e[e1]=='*'||e[e1]=='/')//别弄错了/方向;
return '>';
if(c=='*'||c=='/')
return '<';
if(e[e1]=='+'||e[e1]=='-')
return '>';
}
void chuzan(double d[],int &d1,char e[],int &e1)//出栈操作
{
double a1,a2;
if(e[e1]=='s'||e[e1]=='l')//只要出实数栈顶一个数的操作符ln和sqrt
{
//cout"d1chuzan
a1=d[d1];
d1--;
cout<<a1<<"出栈";
d1++;
if(e[e1]=='s')
{
cout<<"sqrt出栈";
d[d1]=sqrt(a1);
}
else
{
cout<<"ln出栈";
d[d1]=log(a1);
}
e1--;
cout<<d[d1]<<"入栈";
//cout"schuazan
//cout"d1ruzan
}
else//实数栈顶两个数都要出的操作符
{
a2=d[d1];
d1--;
cout<<a2<<"出栈";
a1=d[d1];
d1--;
cout<<a1<<"出栈";
d1++;
if(e[e1]=='^')
{
cout<<"^出栈";
d[d1]=pow(a1,a2);
}
if(e[e1]=='+')
{
cout<<"+出栈";
d[d1]=a1+a2;
}
if(e[e1]=='-')
{
cout<<"-出栈";
d[d1]=a1-a2;
}
if(e[e1]=='*')
{
cout<<"*出栈";
d[d1]=a1*a2;
}
if(e[e1]=='/')
{
cout<<"/出栈";
d[d1]=a1/a2;
}
cout<<d[d1]<<"入栈";
e1--;
}
cout<<endl;
}
int main()
{
char a[100];//存储输入字符串
double d[100];//实数栈
char e[30];//符号栈
int d1,e1,i=0,flag;
double c;
char c1;
d1=e1=-1;
e1++;
e[e1]='#';//字符串肯定以#开始(题目可知),刚好可以作为栈底的标志
gets(a);
i++;//字符串肯定以#开始(题目可知),直接跳过a[0]
while(a[i]!='#')
{
flag=0;//作为标志判断是运算符还是实数
if('1'<=a[i]&&a[i]<='9')
{
shishu(a,i,c);
flag=1;//实数时flag=1;
}
else//运算符时
{
switch(a[i])
{
case 'l':
c1=a[i];
i=i+2;//为了方便ln化为符号l,后面肯定为n,直接跳过+2;
break;
case 's':
c1=a[i];
i=i+4;//为了方便sqrt化为符号s,后面肯定为qrt,直接跳过+4;
break;
default:
c1=a[i];
i++;
}
}
if(flag==1)
{
d1++;
d[d1]=c;
cout<<d[d1]<<"入栈"<<endl;
}
else
{
if( youxian(e1,e,c1)=='<')//c1的优先度高于运算符栈顶要入栈
{
e1++;
e[e1]=c1;
if(c1=='l')//用else if不知道怎么弄的报错
cout<<"ln入栈"<<endl;
if(c1=='s')
cout<<"sqrt入栈";
if(c1!='s'&&c1!='l')
cout<<c1<<"入栈";
}
else if(youxian(e1,e,c1)=='=')//表示运算符栈里一定有‘(’
{
while(e[e1]!='(')//一定得要找到运算符栈里面的‘(’
{
chuzan(d,d1,e,e1);
}
e1--;//chuzan'('
cout<<"(出栈";
}
else
{
while(youxian(e1,e,c1)=='>')//最重要
//每次一定得让要入栈的c1大于运算符栈的栈顶
//运算符出栈后与出栈后的栈顶再次比优先度大小
//最后才可以让运算符栈的优先度从栈底到栈顶依次增大
{
chuzan(d,d1,e,e1);
}
e1++;
e[e1]=c1;
if(c1=='l')
cout<<"ln入栈"<<endl;
if(c1=='s')
cout<<"sqrt入栈";
if(c1!='s'&&c1!='l')
cout<<c1<<"入栈";
}
}
}
while(e[e1]!='#')//以栈底‘#’作为结束标志,持续出栈
{
chuzan(d,d1,e,e1);
}
cout<<d[0]<<"出栈"<<",结果为"<<d[0]<<endl;//最后肯定就剩下一个数了
}