概述:上篇我主要介紹了用qt做計算器的整個流程,這次主要就是分析一下,計算器表示式計算的演算法部分。因為也找了很多別人寫的**,但大多都是只支援個位數的加減乘除,小數也不支援,所以就在原有框架上,修改,優化,讓其滿足我想要的功能。
1,表示式計算思路。
表示式資料操作符分割–>轉為逆波蘭表示式–>計算逆波蘭表示式值–>輸出結果。
2,表示式計算詳解。
(1)表示式資料操作符分割
首先我們得到了乙個字串表示式,我們將資料和操作符分割。
如:表示式—————> 「23+1.23-(2-5)*3」
分割後為「23」 「+」 「1.23」 「- 」「( 」「2」「 -」 「5」 「)」「*」 「3」,然後將其存入乙個qstring陣列,這樣資料,操作符分割就便於後面計算,辨別是資料還是操作符了。遍歷陣列,只要第乙個字元不是0-9就是操作符了。
下面是這部分**詳解:
/*將表示式的資料,操作符分割,依次存入mask_buffer陣列中*/
int calculator::mask_data(qstring expression, qstring *mask_buffer)
mask_buffer[k] = temp;
}else
}return k;
}
(2)轉為逆波蘭表示式。
既然用到逆波蘭表示式,首先了解一下什麼是逆波蘭表示式。我們正常的表示式是中綴表示式,逆波蘭就是將中綴表示式轉化為字尾表示式。我們就簡單粗暴一些,例子。
1+2*3-(2+5)———>中綴表示式。
1,2,3,*,+,2,5,+,- ———>字尾表示式。
中綴到字尾如何轉化呢,下面就是詳細的規則了:
首先我們定義乙個陣列a,堆疊b。陣列a用於儲存最後的字尾表示式,堆疊b就是乙個過渡器,幫助我們轉化,再定義操作符的優先順序,如+ - * / ( )。
從左到右遍歷整個表示式。
1,遇到數字加入陣列a。
2,遇到左括號直接入棧到b。
3,遇到右括號,堆疊b出棧,加入到陣列a中,直到遇到左括號,將左括號出棧但不加入陣列a中。
4,如果遇到的是運算子:
(1)當堆疊b為空,直接入棧到b。
(2)當堆疊不為空,當前運算子優先順序大於堆頂運算子優先順序,入棧到b。
(3)當堆疊不為空,當前運算子優先順序小於等於堆頂運算子優先順序,b出棧到a陣列中,直到堆頂運算子優先順序小於當前運算子優先順序,再將當前運算子入棧b。
5,當遍歷完整個表示式,堆疊b不為空,依次出棧加入到a陣列中。
下面詳細步驟轉化過程:
陣列a[100],堆疊b.
表示式:1+2*3-(2+5)
遍歷:"1" ------> a b
"+" ------> a b
"2" ------> a b
"*" ------> a b //"*"優先順序高於"+"
"3" ------> a b
"-" ------> a b //"-"優先順序不大於"*",不大於"+",*,+出棧到a
"(" ------> a b
"2" ------> a b
"+" ------> a b
"5" ------> a b
")" ------> a b //遇到右括號,+出棧到a中
a b //遍歷結束,b中不為空,"-"出棧到a中
下面是這部分原始碼:
/*獲取操作符優先順序*/
int calculator::priority(qstring data)
/*將獲取到的分割好的表示式陣列,轉化為逆波蘭表示式,存入陣列repolish中*/
int calculator::re_polish(qstring *mask_buffer,qstring *repolish,int length)
else
if(mask_buffer[j] == ")")
if(st2.top() == "(")
st2.pop();
}else
if(st2.empty() || priority(mask_buffer[j]) > priority(st2.top()))
st2.push(mask_buffer[j]);
else
st2.push(mask_buffer[j]);}}
while(!st2.empty())
return i;
}
(3)計算逆波蘭表示式值。
計算就比較簡單了,我們只需要維護乙個儲存資料的堆疊就行了,我們有乙個逆波蘭表示式陣列,上面得到的,再新建乙個堆疊st。遍歷整個逆波蘭表示式陣列,遇到數字直接壓棧到st中,遇到「+」,「-」,「*」,「/」,就取出st棧頂元素a,st.pop(),取下乙個棧頂元素b,st.pop()。計算數值對應操作符值(如操作符為+,b+a),將計算的值入棧到st中。直到表示式遍歷完,堆疊裡只剩乙個資料,就是最後的結果值,取出。
我們還是以 1,2,3,*,+,2,5,+,- 為例。
遍歷陣列a =
"1"------> st
"2"------> st
"3"------> st
"*"------> st //2*3 = 6
"+"------> st //1+6 = 7
"2"------> st
"5"------> st
"+"------> st //2+5 = 7
"-"------> st //7-7 = 0 即最後結果為0
下面是這部分原始碼:
/*計算逆波蘭表示式值並顯示*/
double calculator::repolish_calculat(qstring *repolish,int length)
else
else if(repolish[m] == "-")
else if(repolish[m] == "*")
else if(repolish[m] == "/")}}
}qstring res = qstring::number(st
.top(),'g',10);
ui->display->clear();
ui->put_data->settext(res);
return st
.top();
}
表示式計算器
早在上大學的時候,就想編寫乙個可以計算數學表示式的計算器,因為windowsxp自帶的計算器不支援表示式輸入,當要計算乙個算式時,不太方便。表示式計算器看似簡單,但要想把它做完善,不太容易,經過幾次改進之後,於一年前完成了這個小程式,雖然可能會有一些不足,不過也不打算再投入時間了,價值不大,只是拿來...
Qt之簡易計算器
寫之原因 本人是一名菜鳥,學了qt也就十天左右吧。學習一種對我來說比較新的語言,最好的學習方式就是去真刀真槍的幹一場!所以,閒來無事,就打算寫乙個小應用。思來想去,覺得還是寫乙個簡單的計算器吧,因為其他的涉及的還不是特別深,感覺自己能駕馭的就是計算器這種,簡單而實用的小應用。1 calculate....
QT實現簡易計算器
定義a用來儲存lineedit顯示內容 定義b用來儲存運算子等 ifndef widget h define widget h include qt begin namespace namespace ui qt end namespace class widget public qwidget e...