一、实验目的
1、 掌握栈结构的定义与实现;
2、 掌握栈结构的使用。
二、实验内容
1、题目描述:
创建栈类,采用数组描述;计算数学表达式的值。 输入数学表达式,输出表达式的计算结果。数学表达式由单个数字和运算符“+”、“-”、“”、“/”、“(”、“) ”构成,例如 2+3(4+5)–6/4。
输入输出格式:
输入:
第一行一个整数n(1<=n<=100),代表表达式的个数。
接下来n行,每行一个表达式,保证表达式内的数字为单个整数,表达式内各运算符和数字间没有空格,且表达式的长度不超过2000。
输出:
每行表达式输出一个浮点数,要求保留两位小数,保证输入表达式合法。
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
template<class T>
void changelength(T *a,int oldlength,int newlength){
T* temp=new T[newlength];
int number=newlength<oldlength?newlength:oldlength;
for(int i=0;i<number;i++){
temp[i]=a[i];
}
delete []a;
a=temp;
}
template<class T>
class arrayStack{
private:
int stackTop;//栈顶
int arrayLength;//容量
T *stack;//元素数组
public:
arrayStack(int initialCapacity=10);
~arrayStack(){
delete []stack;}
bool empty() const {
return stackTop==-1;}
int size() const{
return stackTop+1;}
T&top(){
if(stackTop==-1)
cout<<"empty";
return stack[stackTop];
}
void pop();
void push(const T&theElement);
};
template<class T>
arrayStack<T>::arrayStack(int inintialCapacity){
if(inintialCapacity<1){
cout<<"must be >1";
exit(0);
}
arrayLength=inintialCapacity;
stack=new T[arrayLength];
stackTop=-1;
}
template<class T>
void arrayStack<T>::pop(){
if(stackTop==-1)
cout<<"empty";
stack[stackTop--].~T();
}
template<class T>
void arrayStack<T>::push(const T&theElement){
if(stackTop==arrayLength-1){
changelength(stack,arrayLength,2*arrayLength);
arrayLength=2*arrayLength;
}
stack[++stackTop]=theElement;
}
void calculate(arrayStack<double> &n, arrayStack<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(a+b);
break;
case '-':
n.push(b-a);
break;
case '*':
n.push(a*b);
break;
case '/':
n.push(b/a);
break;
default:break;
}
c.pop();//将运算完的符号弹出栈
}
void operate(string s,int length) {
bool tag=false; //用来判断输入-的是否为负号
arrayStack<double> n(length); //声明一个数字栈
arrayStack<char> c(length); //声明一个字符栈
for(int i=0;i<length;i++){
//遍历输入的表达式
if(s[i]==' ') continue; //如果输入的如果是空格,跳过
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(tag){
//判断是否为负数
k=-k;
tag=false; //读到一个负数,标识符归零
}
n.push(k); //将读入的数字压到数字栈
}else{
//读到的是字符
if((i==0||s[i-1]=='(')&&s[i]=='-'){
//-号前面为(或者-号为第一个代表-为负号而不是减号
tag=true;
continue;
}
switch(s[i]){
case '+':
case '-':
if(c.empty()||c.top()=='(') c.push(s[i]);//如果符号栈为空或者栈顶元素为(,+、-直接压入栈
else{
calculate(n,c); //+-运算符优先级最低,对之前运算先运算
if(!c.empty()&&c.top()!='(') calculate(n,c);
c.push(s[i]); //将读到的符号压入栈
}
break;
case '*':
case '/':
if(c.empty()||c.top()=='(') c.push(s[i]);//如果符号栈为空或者栈顶元素为(,*/直接压入栈
else if(c.top()=='+'||c.top()=='-') c.push(s[i]);//如果前一个运算符为+或-,*/直接压入栈
else if(c.top()=='*'||c.top()=='/'){
//前一个运算符为*或/可以直接运算
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 s; //将输入的表达式存到一个字符串中
int length; //记录字符串长度
cin>>s; //输入表达式
length=s.length();
operate(s,length);
}
return 0;
}