智慧語音計算器(二)
阿新 • • 發佈:2018-12-06
這邊文章來介紹該專案的計算引擎模組。
#ifndef CALCULATORDEC_H #define CALCULATORDEC_H #include <qt5/QtCore/QString> #include <qt5/QtCore/QStack> #include <qt5/QtCore/QString> #include "ICalculator.h" class CalculatorDec : public ICalculator { public: CalculatorDec(); ~CalculatorDec(); boolexpression(const QString & exp); QString result(); private: QString calculate(const QString & exp); bool isDigit(char ch); bool isLeft(char ch); bool isDot(char ch); bool isRight(char ch); int judge(char c); double compute(char c,double a,double b); private: QString m_exp; QString m_result; }; #endif
bool expression(const QString & exp); QString result();
這兩個方法是重寫 ICalculator中的方法,當然也可以通過別的方式實現,我在這是為了更好的理解Virtual函式的思想。
下面是該類的具體實現
#include "QCalculatorDec.h" CalculatorDec::CalculatorDec() { m_exp = ""; m_result = ""; } CalculatorDec::~CalculatorDec() { } bool CalculatorDec::expression(const QString & exp) { bool ret = false; m_result = calculate(exp); ret = (m_result != "Error"); return ret; } QString CalculatorDec::result() { return m_result; } QString CalculatorDec::calculate(const QString & exp) { QString ret = "Error"; QByteArray ba = exp.toLatin1(); const char *str = ba.data(); QStack<double> stack_digit; QStack<char> stack_op; const char *p; for(p=str;*p;p++) { if(isDigit(*p)) { stack_digit.push(atof(p)); while(isDigit(*p)) p++; if(isDot(*p)) { p=p+1; while(isDigit(*p)) p++; } p--; // printf("%c\n",*p); } else { if(stack_op.isEmpty() || isLeft(*p)) { stack_op.push(*p); continue; } else { if(isRight(*p)) { while(!isLeft(stack_op.top())) { char b1 = stack_op.pop(); double a1 = stack_digit.pop(); double a2 = stack_digit.pop(); stack_digit.push(compute(b1,a1,a2)); } stack_op.pop(); } else { if(!isLeft(stack_op.top())) { if(judge(*p)<=judge(stack_op.top())) { char b2 = stack_op.pop(); double a3 = stack_digit.pop(); double a4 = stack_digit.pop(); stack_digit.push(compute(b2,a3,a4)); p--; continue; } else { stack_op.push(*p); } } else { stack_op.push(*p); } } } } } while(!stack_op.isEmpty()) { char b3 = stack_op.pop(); double a5 = stack_digit.pop(); double a6 = stack_digit.pop(); stack_digit.push(compute(b3,a5,a6)); } double ret1 = stack_digit.pop(); ret = QString::number(ret1,'f',2); return ret; } bool CalculatorDec::isDigit(char ch) { if(ch>='0' && ch<='9') return true; else return false; } bool CalculatorDec::isLeft(char ch) { if(ch=='(') return true; else return false; } bool CalculatorDec::isDot(char ch) { if(ch=='.') return true; else return false; } bool CalculatorDec::isRight(char ch) { if(ch==')') return true; else return false; } int CalculatorDec::judge(char c) { int ret = 0; if(c=='+' || c=='-') ret = -1; if(c=='*' || c=='/') ret = 0; return ret; } double CalculatorDec::compute(char c,double a,double b) { double ret = 0; if(c=='+') ret = b+a; if(c=='-') ret = b-a; if(c=='*') ret = b*a; if(c=='/') ret = b/a; return ret; }
說一下演算法設計思路,首先是用兩個棧來存放資料和符號(資料棧和符號棧)。
演算法(重點):
數字:數字無條件入棧
符號:
判斷符號棧是否為空,如果為空,則無條件入棧
如果不為空,
當前符號如果為右括號:
一直去彈符號棧,直到彈出第一個左括號。
當前符號如果不為右括號:
判讀棧頂元素是不是左括號
棧頂不是左括號
當前符號優先順序 <= 棧頂元素的優先順序,則計算。(出棧一個符號,出兩個數字,先出棧的數字是右運算元,後出棧的數字是左運算元)
當前符號優先順序 > 棧頂元素的優先順序,符號入棧。
棧頂是左括號
當前符號無條件入棧
迴圈結束:
判斷符號棧是否為空,如果為空,則資料棧的棧頂元素,就是最後的結果。
如果不空,一直計算,直到符號棧為空。