中綴表達式轉(zhuǎn)后綴表達式,考試大現(xiàn)在就用這個方式再實現(xiàn)計算器..
表達式一旦轉(zhuǎn)換成后綴表達式再進行計算就簡單的不得了.Examda遇到一個符號就彈出離他最近的兩個操作數(shù)然后進行這個操作符指定的運算就ok了...運算完成后壓棧繼續(xù)掃描,依次重復...等到操作符沒有了.所有的運算也就結(jié)束了.結(jié)果也就出來了...不必再判斷優(yōu)先級的什么的了.括號什么的也一并省略...
其實在中綴轉(zhuǎn)后綴的時候就可以進行計算,表達式掃描完成,計算完成.
把代碼直接復制..修改..
opt.push('#');
int len = exp.length();
for (int i = 0; i < len;)
{
char ch = exp.at(i);
if (isalnum(ch))
{
long num = 0;
while (isalnum(ch)) //轉(zhuǎn)換為整數(shù)
{
num = (ch-'0') + num*10;
if (++i >= len)
break;
ch = exp.at(i);
}
opd.push(num); // 操作數(shù)入棧
}
else // 操作符就判斷并壓棧
{
if (ch == '(') // 左括號直接壓棧
opt.push(ch);
else if (ch == ')') // 有括號就彈棧到直到遇到左括號
{
ch = opt.top(); // 取得棧頂操作符
while(ch != '(') // 直到彈出左括號
{
OP(ch);
opt.pop();
ch = opt.top();
}
opt.pop(); // 彈出左括號
}
else
{
int thisPri = GetPri(ch); // 當前操作符優(yōu)先級
char prevOpt = opt.top(); // 上一個操作符
int prevPri = GetPri(prevOpt); // 上一個操作符優(yōu)先級
while (thisPri <= prevPri)
{ //輸出棧中的操作符直到遇到比當前的操作符優(yōu)先級更低的
OP(prevOpt);
opt.pop(); // 輸出后就彈出
prevOpt = opt.top();
prevPri = GetPri(prevOpt);
}
opt.push(ch); //當前操作符壓棧
}
i++;
}
}
char ch = opt.top(); // 表達式掃描完后把棧中剩余的操作符全部輸出
while (ch != '#')
{
OP(ch);
opt.pop();
ch = opt.top();
}
提示:輸出的地方換成了運算 OP(const char &ch); 完成運算
要明白一點.表達式掃描完成,有可能操作符是壓棧了而未進行運行,(這由具體的表達式?jīng)Q定),因此最后要把操作符棧彈空,完成全部的運算....則此時操作數(shù)棧中的的一個數(shù)就是運行結(jié)果了.
函數(shù)OP.實現(xiàn)如下. 參數(shù) ch 是操作符
void Caculator::OP(const char &ch)
{
long RightOperand = opd.top();
opd.pop();
long LeftOperand = opd.top(); // 這兩個操作數(shù)的順序不能錯
opd.pop();
switch(ch)
{
case '+':
LeftOperand += RightOperand;
break;
case '-':
LeftOperand -= RightOperand;
break;
case '*':
LeftOperand *= RightOperand;
break;
case '/':
if (RightOperand == 0) // 除數(shù)為 0
{
cout<<"大哥啊,除數(shù)為0了!"< system("pause");
exit(1);
}
else
LeftOperand /= RightOperand;
default:
cout<<"非法操作符!!----:"< system("pause");
exit(1);
}
opd.push(LeftOperand); // 把求得的值壓入堆棧
}
opd 是操作數(shù)棧,是一個類成員變量 .定義是 stack opd; // 只能進行整數(shù)的運算
簡單吧...
關鍵是把表達式轉(zhuǎn)換成后綴的...
這個實現(xiàn)中未對表達式是否合法進行判斷,所以非法的表達式會造成程序崩潰....表達式的檢查也可以在掃描的過程中完成的
表達式一旦轉(zhuǎn)換成后綴表達式再進行計算就簡單的不得了.Examda遇到一個符號就彈出離他最近的兩個操作數(shù)然后進行這個操作符指定的運算就ok了...運算完成后壓棧繼續(xù)掃描,依次重復...等到操作符沒有了.所有的運算也就結(jié)束了.結(jié)果也就出來了...不必再判斷優(yōu)先級的什么的了.括號什么的也一并省略...
其實在中綴轉(zhuǎn)后綴的時候就可以進行計算,表達式掃描完成,計算完成.
把代碼直接復制..修改..
opt.push('#');
int len = exp.length();
for (int i = 0; i < len;)
{
char ch = exp.at(i);
if (isalnum(ch))
{
long num = 0;
while (isalnum(ch)) //轉(zhuǎn)換為整數(shù)
{
num = (ch-'0') + num*10;
if (++i >= len)
break;
ch = exp.at(i);
}
opd.push(num); // 操作數(shù)入棧
}
else // 操作符就判斷并壓棧
{
if (ch == '(') // 左括號直接壓棧
opt.push(ch);
else if (ch == ')') // 有括號就彈棧到直到遇到左括號
{
ch = opt.top(); // 取得棧頂操作符
while(ch != '(') // 直到彈出左括號
{
OP(ch);
opt.pop();
ch = opt.top();
}
opt.pop(); // 彈出左括號
}
else
{
int thisPri = GetPri(ch); // 當前操作符優(yōu)先級
char prevOpt = opt.top(); // 上一個操作符
int prevPri = GetPri(prevOpt); // 上一個操作符優(yōu)先級
while (thisPri <= prevPri)
{ //輸出棧中的操作符直到遇到比當前的操作符優(yōu)先級更低的
OP(prevOpt);
opt.pop(); // 輸出后就彈出
prevOpt = opt.top();
prevPri = GetPri(prevOpt);
}
opt.push(ch); //當前操作符壓棧
}
i++;
}
}
char ch = opt.top(); // 表達式掃描完后把棧中剩余的操作符全部輸出
while (ch != '#')
{
OP(ch);
opt.pop();
ch = opt.top();
}
提示:輸出的地方換成了運算 OP(const char &ch); 完成運算
要明白一點.表達式掃描完成,有可能操作符是壓棧了而未進行運行,(這由具體的表達式?jīng)Q定),因此最后要把操作符棧彈空,完成全部的運算....則此時操作數(shù)棧中的的一個數(shù)就是運行結(jié)果了.
函數(shù)OP.實現(xiàn)如下. 參數(shù) ch 是操作符
void Caculator::OP(const char &ch)
{
long RightOperand = opd.top();
opd.pop();
long LeftOperand = opd.top(); // 這兩個操作數(shù)的順序不能錯
opd.pop();
switch(ch)
{
case '+':
LeftOperand += RightOperand;
break;
case '-':
LeftOperand -= RightOperand;
break;
case '*':
LeftOperand *= RightOperand;
break;
case '/':
if (RightOperand == 0) // 除數(shù)為 0
{
cout<<"大哥啊,除數(shù)為0了!"<
exit(1);
}
else
LeftOperand /= RightOperand;
default:
cout<<"非法操作符!!----:"<
exit(1);
}
opd.push(LeftOperand); // 把求得的值壓入堆棧
}
opd 是操作數(shù)棧,是一個類成員變量 .定義是 stack
簡單吧...
關鍵是把表達式轉(zhuǎn)換成后綴的...
這個實現(xiàn)中未對表達式是否合法進行判斷,所以非法的表達式會造成程序崩潰....表達式的檢查也可以在掃描的過程中完成的