上一篇文章是後綴表達式求值,由於後綴表達式不是我們人類能接受的求值表達式,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;
}
}
}
}
輸出結果:
小結:表達式求值就到此結束了,不論哪個版本的數據結構,算法的參考資料裏,學習棧時,表達式求值都是很經典的例子!它充分的利用了棧的原理進行操作!
當初剛接觸棧時,表達式求值對我來說簡直是個噩夢!過來再看,對棧的理解更深刻了!