1. 程式人生 > >計算中綴表示式(實數,四則運算與括號)(雙棧)

計算中綴表示式(實數,四則運算與括號)(雙棧)

        之前寫過這方面的演算法,用的思想是先將中綴表示式轉化為字尾表示式,再計算。本文采用直接計算中綴表示式的方法,用兩個棧分別儲存,運算子和數值。另外在處理括號問題時,拋開之前增大優先順序的繁瑣方法,直接把括號當做一條新的式子,計算後返回一個值到原式,這也算是遞迴思想。最後,此次把資料域擴充到實數域。

       瑕疵:程式碼沒有考慮除以0和一些不符合的情況,即輸入的式子都是符合運演算法則的。因為只是想體現演算法的核心,沒有必要搞得太繁瑣,需要的時候再加就是了。

#include<iostream>
#include<stack>
#include<string>
using namespace std;
const int power[6]={2,1,0,1,0,2};//四則運算的優先順序,分別對應*,+, ,-, ,/ 
double tqn(char s[],int &i)//提取數字 
{
	double result=0;
	int j;
	while(s[i]!='.'&&s[i]!='+'&&s[i]!='-'&&s[i]!='*'&&s[i]!='/'&&s[i]!='('&&s[i]!=')'&&s[i]!='\0')//整數部分 
	{
		result=result*10+s[i]-'0';
		i++;
	}
	if(s[i]=='.')//小數部分 
	{
		i++;
		for(j=10;s[i]!='+'&&s[i]!='-'&&s[i]!='*'&&s[i]!='/'&&s[i]!='('&&s[i]!=')'&&s[i]!='\0';j=j*10,i++)
		{
			result+=(double(s[i]-'0'))/j;
		}
	}
	i--;//考慮到原來的函式存在i自增,所以這裡要退一位 
	return result;
}
void calcular(stack<double> &num,stack<char> &op)//計算當前能計算的式子,就是暫時符合運演算法則的部分 
{
	double a,b;
	while(!op.empty())//直到當前沒有運算子剩餘,即只剩下一個結果值 
	{
		b=num.top();
		num.pop();
		a=num.top();
		num.pop();
		switch(op.top())
		{
		case '+':num.push(a+b);break;
		case '-':num.push(a-b);break;
		case '*':num.push(a*b);break;
		case '/':num.push(a/b);break;
		}
		op.pop();
	}
}
double play(char s[],int &i,char flag)//操作式子 ,flag是式子結束標識 
{
	double result=0;
	stack<double> num;
	stack<char> op;
	int j;
	for(;s[i]!=flag;i++)
	{
		if(s[i]>='0'&&s[i]<='9')//遇到數字即提取 
			num.push(tqn(s,i));
		else
		{
			if(s[i]=='(')//遇到括號即當成一個新的式子 
			{
				i++;
				num.push(play(s,i,')'));//括號的結束標識為')' 
			}
			else
			{
				if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')//遇到運算子 
				{
					if(op.empty())//空即入 
						op.push(s[i]);
					else
					{
						if(power[s[i]-42]<power[op.top()-42])//當前運算子優先順序小於上一個運算子的優先順序,即前面的可以計算了 
						{
							calcular(num,op);
						}
						op.push(s[i]);//插入當前運算子 
					}
				}
			}
		}
	}
	calcular(num,op);//計算剩下的 
	result=num.top();
	num.pop();
	return result;
}
int main()
{
	int i;//列舉下標 
	double result;
	char s[1000];
	stack<char> op;//運算子棧 
	stack<double> num;//數值棧 
	while(cin.getline(s,1000))
	{
		i=0;
		result=play(s,i,'\0');
		cout<<result<<endl;
	}
	return 0;
}