表達式求值(中綴表達式轉換爲後綴表達式)

        上一篇文章是後綴表達式求值,由於後綴表達式不是我們人類能接受的求值表達式,so本文爲中綴表達式轉換爲後綴表達式的方法。然後再結合上一篇逆波蘭表達式,我們就可以利用中綴表達式求值啦!!!!本文的代碼依然可以計算帶小數點,大於10的數字的表達式!


思路:

一、遇到數字,直接存入字符串中。

二、遇到的是表達式符號(+,-,*,/,(,)):

1、如果棧爲空,或者表達式爲左括號‘(’,直接壓入棧中;

2、做出棧操作,出棧元素存入c1,與待輸入的符號c2進行比較,如果c1的優先級高於c2,則將c1存到結果字符串結尾,跳轉到第1條,重新判斷!

三、比較完畢後,將棧中剩餘的元素彈出存到結果字符串的尾部!


關於棧的聲明與定義就不再贅述,直接進入代碼:

void toPolish()
{
	SqStack s;
	StackInit(&s);
	char c;
	char str[100];			//用於存儲後綴表達式的結果字符串
	int i=0;			//字符數組下標,初始化爲0


	printf("請輸入正確的中綴表達式,以#結束輸入。\n");
	
	scanf("%c",&c);


	while (c!='#')
	{
		if (isdigit(c) || c=='.')		
		{/*大於10的數位數之間不能有空格,所以先做判斷再循環,循環結束後加空格,結尾在賦'\0'*/
			while(isdigit(c) || c=='.')
			{
				str[i++]=c;
				scanf("%c",&c);
			}
			str[i++]=' ';
			str[i]='\0';
		}
		if(c=='#')break;	/*如果數字之後是#的話,此處判斷纔是大循環的結束之處,否則在循環結束後再輸入會造成死循環,不理解可以下斷點試試*/
		if (c=='(')		//右括號直接壓棧
		{
			Push(&s,c);
		}
		if (c==')')		//左括號則做出棧並賦給結果字符串中,再將有括號也彈出棧。
		{
			while(*(s.top)!='(')
			{
				Pop(&s,&str[i]);
				i++;
				str[i++]=' ';
				str[i]='\0';
			}
			char temp;
			Pop(&s,&temp);
		}
		if (c=='+' || c== '-' || c=='*' || c=='/')	//判斷是否爲符號,封裝起來也許更我,我沒做而已
		{
			if (s.top-s.base==0 || *(s.top)=='(')	//如果空棧或棧頂爲(,入棧
			{
				Push(&s,c);
			}
			else
			{
				char temp;		
				Pop(&s,&temp);
				if (judge(temp,c))		//重點,判斷棧頂和當前的符號優先級,並左相應操作,相關代碼在後面
				{
					str[i++]=temp;
					str[i++]=' ';
					str[i]='\0';
					continue;
				} 
				else
				{
					Push(&s,temp);
					Push(&s,c);
				}
			}
		}


		scanf("%c",&c);
	}


	while (s.top-s.base>0)		//把棧中剩餘元素賦給結果數組
	{
		Pop(&s,&str[i]);
		i++;
		str[i++]=' ';
		str[i]='\0';
	}


	str[i++]='#';
	str[i]='\0';


	puts(str);
	system("pause");
	return 0;
}


這個函數是用來判斷c1 與c2誰的優先級更高,true代表c1>c2,false代表c1<c2;

方法挺傻的,copy一下倒是蠻方便,呵呵!

//判斷表達式符號(+ - * /)c1,c2的優先級,有人用數組的方式左,反正就是個方法而已無所謂!
bool judge(char c1,char c2)
{
	switch(c1)
	{
	case '+':
		{
			switch(c2)
			{
			case '+':
				return true;
			case '-':
				return true;
			case '*':
				return false;
			case '/':
				return false;
			}
		}
	case '-':
		{
			switch(c2)
			{
			case '+':
				return true;
			case '-':
				return true;
			case '*':
				return false;
			case '/':
				return false;
			}
		}
	case '*':
		{
			switch(c2)
			{
			case '+':
				return true;
			case '-':
				return true;
			case '*':
				return true;
			case '/':
				return true;


			}
		}
	case '/':
		{
			switch(c2)
			{
			case '+':
				return true;
			case '-':
				return true;
			case '*':
				return true;
			case '/':
				return true;
			}
		}
	}
}

輸出結果:

小結:表達式求值就到此結束了,不論哪個版本的數據結構,算法的參考資料裏,學習棧時,表達式求值都是很經典的例子!它充分的利用了棧的原理進行操作!

當初剛接觸棧時,表達式求值對我來說簡直是個噩夢!過來再看,對棧的理解更深刻了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章