1.实验内容
创建栈类,采用数组描述;计算数学表达式的值。 输入数学表达式,输出表达式的计算结果。数学表达式由单个数字和运算符“+”、“-”、“*”、“/”、“(”、“) ”构成,例如 2+3*(4+5)–6/4。
输入输出格式:
输入:
第一行一个整数n(1<=n<=100),代表表达式的个数。
接下来n行,每行一个表达式,保证表达式内的数字为单个整数,表达式内各运算符和数字间没有空格,且表达式的长度不超过2000。
输出:
每行表达式输出一个浮点数,要求保留两位小数,保证输入表达式合法。
2.测试结果
输入:
2
2+(1+6*9)*3
(-1)*4/2*9
输出:
167.00
-18.00
3.实现源代码
#include<iostream>
#include<string>
#include<cstdlib>
#include<iomanip>
using namespace std;
template<class T>
class stack
{
public:
stack(int initialCapacity=10)
{
if(initialCapacity<1)
exit(1);
arrayLength=initialCapacity;
element=new T[arrayLength];
stackTop=-1;
}
~stack()
{
delete []element;
}
bool empty() const
{
return stackTop==-1;
}
int size() const
{
return stackTop+1;
}
T& top()
{
if(stackTop==-1)
exit(1);
return element[stackTop];
}
void pop()
{
if(stackTop==-1)
exit(1);
element[stackTop--].~T();
}
void push(const T& theElement)
{
if(stackTop==arrayLength-1)
{
arrayLength*=2;
T newElement[arrayLength];
for(int i=0;i<arrayLength;i++)
newElement[i]=element[i];
delete []element;
element=newElement;
}
element[++stackTop]=theElement;
}
protected:
int stackTop;
int arrayLength;
T* element;
};
void calculate(stack<double>&n,stack<char>&c)
//将浮点数栈栈顶的两个元素与符号栈栈顶的元素进行运算,把结果保存到浮点数栈栈顶
{
if(c.top()=='(')
return;
double a,b;
a=n.top();
n.pop();
b=n.top();
n.pop();
switch(c.top())
{
case '+':
n.push(b+a);
break;
case '-':
n.push(b-a);
break;
case '*':
n.push(b*a);
break;
case '/':
n.push(b/a);
break;
default:
break;
}
c.pop();
}
void operate(string s,int length) //对一个字符串进行运算
{
bool flag=false; //flag为数字的负数标识
stack<double> n(length); //创建一个双精度浮点数栈
stack<char> c(length); //创建一个符号栈
for(int i=0;i<length;i++) //遍历表达式
{
if(s[i]>='0'&&s[i]<='9') //如果读取的是数字
{
int k=s[i]-'0'; //将数字字符转化为数
while(s[i+1]>='0'&&s[i+1]<='9')//读取接下来连续出现的数字合并为十进制数
{
k=10*k+(s[i+1]-'0');
i++;
}
if(flag) //如果有负数标识,取其相反数,重置标识
{
k=-k;
flag=false;
}
n.push(k); //将k压入数字栈
}
else //如果读取的不是数字
{
if((i==0||s[i-1]=='(')&&s[i]=='-') //如果读取到负号
{
flag=true;
continue;
}
switch(s[i])
{
case '+':
case '-':
//当读取的符号是加减号时,先将栈中左括号之后的表达式全部进行运算再进行此次加减运算
while(!c.empty()&&c.top()!='(')
calculate(n,c);
c.push(s[i]);
break;
case '*':
case '/':
if(c.empty()||c.top()=='('||c.top()=='+'||c.top()=='-'||c.top()=='*')
//当读取的符号是乘除号时,如果当前数字栈顶的数优先与此次乘除法进行运算,则直接把乘除号压入符号栈顶
c.push(s[i]);
else
//当读取的符号是乘除号时,如果当前数字栈顶是除号,则先将栈顶的两个数进行运算后再把乘除号压入符号栈顶
{
calculate(n,c);
c.push(s[i]);
}
break;
case '(': //当读取的符号是左括号时,直接压入符号栈顶
c.push(s[i]);
break;
case ')':
//当读取的符号是右括号时,对括号内表达式进行运算直到遇到左括号
while(c.top()!='(')
calculate(n,c);
c.pop(); //从符号栈中删除左括号
break;
default:
break;
}
}
}
while(!c.empty())
calculate(n,c);
cout<<setprecision(2)<<fixed<<n.top()<<endl;
}
int main()
{
int n;
cin>>n; //输入表达式个数
for(int i=0;i<n;i++)
{
string str;
cin>>str; //输入表达式
int len=str.length(); //记录表达式长度
operate(str,len); //计算并输出浮点数
}
return 0;
}