if (pGetFirst()->data.type != POSTFIX) temp.Postfix();
Stack s; Type left, right;
for (ExpNode *p = temp.Next(); p != NULL; p = temp.Next())
{
switch (p->type)
{
case OPND:
s.Push(p->opnd); break;
case OPTR:
right = s.Pop(); left = s.Pop();
switch (p->optr)
{
case '+': s.Push(left + right); break;
case '-': s.Push(left - right); break;
case '*': s.Push(left * right); break;
case '/': if (right != 0) s.Push(left/right); else return 0; break;
// case '%': if (right != 0) s.Push(left%right); else return 0; break;
// case '^': s.Push(Power(left, right)); break;
default: break;
}
default: break;
}
}
return s.Pop();
}
private:
int isp(char optr)
{
switch (optr)
{
case '=': return 0;
case '(': return 1;
case '^': return 7;
case '*': return 5;
case '/': return 5;
case '%': return 5;
case '+': return 3;
case '-': return 3;
case ')': return 8;
default: return 0;
}
}
int icp(char optr)
{
switch (optr)
{
case '=': return 0;
case '(': return 8;
case '^': return 6;
case '*': return 4;
case '/': return 4;
case '%': return 4;
case '+': return 2;
case '-': return 2;
case ')': return 1;
default: return 0;
}
}
};
#endif
幾點說明
l 表達式用單鏈表儲存,你可以看到這個鏈表中既有操作數又有操作符,如果你看過我的《如何在一個鏈表中鏈入不同類型的對象》,這里的方法也是對那篇文章的補充。
l 輸入表達式時,會將原來的內容清空,并且必須按照中綴表示輸入。如果你細看一下中綴表達式,你就會發現,除了括號,表達式的結構是“操作數”、“操作符”、“操作數”、……“操作符(=)”,為了統一這個規律,同時也為了使輸入函數簡單一點,規定括號必須這樣輸入“0(”、“)0”;這樣一來,“0”就不能作為操作數出現在表達式中了。因為我沒有在輸入函數中增加容錯的語句,所以一旦輸錯了,那程序就“死”了。
l 表達式求值的過程是,先變成后綴表示,然后用后綴表示求值。因為原書講解的是這兩個算法,并且用這兩個算法就能完成中綴表達式的求值,所以我就沒寫中綴表達式的直接求值算法。具體算法說明參見原書,我就不廢話了。
l Calculate()注釋掉的兩行,“%”是因為只對整型表達式合法,“^”的Power()函數沒有完成。
l isp(),icp()的返回值,原書說的不細,我來多說兩句!健ū磉_式開始和結束標志)的棧內棧外優先級都是最低!ā瘲M庾罡,棧內次最低!瘲M獯巫畹停贿M棧。‘^’棧內次最高,棧外比棧內低!痢拢ァ瘲缺取甞’棧外低,棧外比棧內低!瘲缺取痢瘲M獾,棧外比棧內低。這樣,綜合起來,就有9個優先級,于是就得出了書上的那個表。