該項目目標是設計開發一個支持連續計算的包括括號(
)
,求餘%
四則運算+
-
*
/
的計算器 Calculator 以及貸款計算功能 Mortgage。
本程序爲本人初學一週QT所做,才疏學亦淺,程序中絕對有意想不到的蜜汁bug😆(逃)歡迎你們評論區交流丫。
項目下載地址css
經過單擊按鈕,輸入並完成如4+5.21+6
或 5*(8+16)-2
相似的連續計算,並將運算結果顯示在輸出文本框 lineEdit
中,計算的式子移至上方的 label
中。
支持負數,小數運算,而且精度爲小數點後五位。支持簡單的錯誤性檢驗。 CE
清空 Del
後退 More
切換至貸款計算。兩個界面,貸款計算界面不作過多贅述。c++
Calculator
界面)界面設計部分如圖由數組
label
(顯示計算的式子)
lineedit
(顯示結果或者當前輸入的式子)
以及各個按鈕組成。ide
建立按鈕的時候由於數目有點多,因此咱們能夠用數組保存建立的按鈕 指針
,後面就能夠直接用 索引
對按鈕進行操控。函數
QT支持用 css
渲染元素。如label->setStyleSheet("font-size:12px;color:grey;border-bottom:1px solid #f1f1f1;border-radius:5px;text-align:right;");
佈局
//from widget.cpp setFixedSize(400,450); //固定窗口大小 setWindowIcon(QIcon(":/icon.png")); //設置icon QLineEdit* lineedit = new QLineEdit(this); //建立 lineedit 對象 lineedit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); //將該對象設爲寬高可擴展 QLabel* label = new QLabel(this); label->setText("請在下方輸入要計算的式子..."); //設置文本內容 QString btnstr[22] = {"(", ")", "%", "CE", "Del", "7", "8", "9", "+", "-", "4", "5", "6", "*", "/", "1", "2", "3", "More", "=", "0", "." }; auto that = this; QPushButton* btn[22]; //建立22個按鈕並用數組儲存,而且綁定相應的槽函數。方便後面佈局(偷懶 for(int i=0; i<22; i++){ btn[i] = new QPushButton(that); btn[i]->setText(btnstr[i]); btn[i]->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(btn[i],&QPushButton::clicked,that,[=](){ that->input(btnstr[i], lineedit, label); }); } //設置樣式,美化 btn[4]->setStyleSheet("color:red;"); btn[18]->setStyleSheet("color:yellow;"); int cyellow[9] = {0,1,2,3,8,9,13,14}; for(int i=0; i<9; i++) btn[cyellow[i]]->setStyleSheet("color:#38d6d5;"); lineedit->setStyleSheet("color:#333;font-size:21px;font-weight:bolder;border:1px dashed #f1f1f1;border-radius:5px;text-align:right;"); label->setStyleSheet("font-size:12px;color:grey;border-bottom:1px solid #f1f1f1;border-radius:5px;text-align:right;"); lineedit->setAlignment( Qt::AlignRight); label->setAlignment( Qt::AlignRight); setStyleSheet("QPushButton {font-size:20px;font-weight:bold;color:ligrhtgrey;background-color: rgba(255, 255, 255, 0%);border:1px solid grey;border-radius:5px;} QPushButton:hover, QLabel:hover {font-size:25px;} Widget {background:qlineargradient(spread:pad,y1:1,y2:0,stop:0 #79f4f3,stop:1 #f8fefe);}"); setWindowTitle("Calculator"); //設置佈局 QGridLayout* computelayout = new QGridLayout(this); computelayout->addWidget(label, 0, 0, 1, 5); computelayout->addWidget(lineedit, 1, 0, 1, 5); computelayout->addWidget(btn[0], 2, 0, 1, 1); computelayout->addWidget(btn[1], 2, 1, 1, 1); computelayout->addWidget(btn[2], 2, 2, 1, 1); computelayout->addWidget(btn[3], 2, 3, 1, 1); computelayout->addWidget(btn[4], 2, 4, 1, 1); computelayout->addWidget(btn[5], 3, 0, 1, 1); computelayout->addWidget(btn[6], 3, 1, 1, 1); computelayout->addWidget(btn[7], 3, 2, 1, 1); computelayout->addWidget(btn[8], 3, 3, 1, 1); computelayout->addWidget(btn[9], 3, 4, 1, 1); computelayout->addWidget(btn[10], 4, 0, 1, 1); computelayout->addWidget(btn[11], 4, 1, 1, 1); computelayout->addWidget(btn[12], 4, 2, 1, 1); computelayout->addWidget(btn[13], 4, 3, 1, 1); computelayout->addWidget(btn[14], 4, 4, 1, 1); computelayout->addWidget(btn[15], 5, 0, 1, 1); computelayout->addWidget(btn[16], 5, 1, 1, 1); computelayout->addWidget(btn[17], 5, 2, 1, 1); computelayout->addWidget(btn[18], 5, 3, 2, 1); computelayout->addWidget(btn[19], 5, 4, 2, 1); computelayout->addWidget(btn[20], 6, 0, 1, 2); computelayout->addWidget(btn[21], 6, 2, 1, 1);
首先先將每一個按鈕都綁定對應的 槽函數this
//from widget.cpp for(int i=0; i<22; i++){ btn[i] = new QPushButton(that); btn[i]->setText(btnstr[i]); btn[i]->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(btn[i],&QPushButton::clicked,that,[=](){ //這裏 that->input(btnstr[i], lineedit, label); }); }
用戶按下 =
按鈕後,利用按鈕的信號和槽調用 input()
函數.net
//from widget.cpp void Widget::input(QString word, QLineEdit* lineedit, QLabel* label) { if(word == "="){ if(linetxt == "") label->setText("不能爲空哦..."); // 首先判斷表達式是否合法 else compute(lineedit, label); //合法,跳轉到計算函數 } else if (word == "More") { //切換貸款計算界面 this->hide(); emit calchangewindow(); } else if (word == "CE") { //清空 linetxt = ""; labeltxt = ""; label->setText(""); lineedit->setText(linetxt); } else if (word == "Del") { //後退 QString tmp = ""; for (int i=0; i < linetxt.length()-1; i++) tmp += linetxt[i]; linetxt = tmp; lineedit->setText(linetxt); } else { linetxt+=word; //輸入爲字符 lineedit->setText(linetxt); } }
計算時咱們須要先將 中綴表達式
轉化爲 後綴表達式
。設計
中綴表達式就是咱們平常生活中正常使用的那種形如:a+b*c
指針
後綴表達式就是形如abc*+
,操做符在數字後面;
爲何有後綴表達式呢?
由於中綴表達式便於人們的理解與計算
可是後綴表達式更方便計算機的運算(如二叉樹、堆棧的方法計算)
所以在讀取一箇中綴表達式後,咱們得辦法將他轉化爲後綴表達式。
那麼怎麼轉化爲後綴表達式呢?
咱們能夠用這種方法將中綴表達式轉化爲後綴表達式。
如下是節選自項目 backans.cpp
的實現將中綴表達式轉化後綴表達式的函數
//from backans.cpp string getback(string str)//獲取後綴表達式的函數 { char* middle = new char[100]; char* tmp = middle; char* isFirst = tmp; for (int i=0; i<str.length(); i++) { *tmp = str[i]; //將 middle 所指向的字符串內容賦值爲傳入的 str ,同時保持 middle 指向首地址不變 tmp++; } char* back = new char[100]; //同上 char* backend = back; stack<char> s; s.push('#'); while (*middle) { if( ((middle == isFirst)&& *middle == '-' && Number(*(middle+1))) || ( *(middle-1) == '(' && *middle == '-' && Number(*(middle+1))) || Number(*middle)) { *back = *middle; //判斷是否爲負數 back++, middle++; } else { if (Number(*(back - 1))) *back++ = ' '; //若是前一位是數字的話添加空格 用以區分 if (*middle == ')')//若是右括號的話,輸出全部操做符直到遇到左括號,並拋棄相對應的一堆括號 { while (s.top() != '(' && s.top() != '#') { *back = s.top(); s.pop(); back++; *back++ = ' '; } middle++; s.pop();//拋棄左括號 } else if (*middle == '(')//遇到左括號,則進入棧 { s.push(*middle); middle++; } else if (priority(*middle) > priority(s.top()))//若是棧內的操做符優先級高於棧外的優先級,則入棧 { s.push(*middle); middle++; } else if (priority(*middle) <= priority(s.top())) //若是棧內的操做符優先級低於或等於棧外的優先級,輸出棧內的符號,併入棧棧外的符號 { while (priority(*middle) <= priority(s.top()) && s.top() != '#') { *back = s.top(); back++; //直到棧內的操做符爲空 或者 低於棧外的優先級 s.pop(); *back++ = ' '; } s.push(*middle); middle++; } } } while (isOpe(s.top()))//中綴表達式遍歷完成,可是=棧中還有符號存在,一一出棧輸出 { if (Number(*(back - 1))) *back++ = ' '; *back = s.top(); qDebug("%c",*back); s.pop(); if(s.top() != '#'){ back++; *back++ = ' '; } } string tmpresult = ""; //後面這些因爲某些蜜汁bug而作出的一些處理。。。請無視充滿了妥協 string result = ""; int address = 0; for (;backend<=back;backend++) tmpresult += *backend; while(Number(tmpresult[address]) || isOpe(tmpresult[address]) || tmpresult[address] == ' ') result += tmpresult[address++]; return result; }
轉化爲後綴表達式後怎麼計算結果呢?
咱們能夠用這種方法將後綴表達式求值。
而後將結果打印至 lineEdit
即完成計算啦!
如下是節選自項目 backans.cpp
的實現計算後綴表達式的函數
//from backans.cpp long double backans::result(string str) { string back = getback(str); stack<long double> s; for (int i=0; i<back.length(); ) { if(!isOpe(back[i]) || (back[i] == '-' && Number(back[i+1]) )){ //將數字依次入棧 s.push(turnnum(back, i)); while (back[i] != ' ') i++; i++; } else { long double a = s.top(); s.pop(); long double b = s.top(); s.pop(); s.push(Cauculate(back[i], b, a));//遇到符號時,取棧頂的第二個數和第一個數求解,併入棧 i+=2; } } while (s.size() >= 2)//最終棧內存在的數大於2時,繼續計算,直到只剩下一個數 { long double a = s.top(); s.pop(); long double b = s.top(); s.pop(); s.push(Cauculate(back[back.length()-1], b, a)); } //返回這個數字,既是最終結果 return s.top(); }
以上就是所有內容啦,但願能幫到您嘿嘿🤭
項目壓縮包下載地址:https://files-cdn.cnblogs.com/files/Trump-He/Calculator.zip