I always want to be a calculator that comes with Windows, you can enter the entire expression and then evaluate.
This program requires readers to have some knowledge of compilation.
For example, the program process is explained. Assuming the required value is -25 * (56 15) # (where ## is used as the end flag of the expression). First, the expression is analyzed, which allows the character to be {0, 1, 2, 3, 4, 5, 6, 7, 8, 9., , -, *, /, (,), #} analysis The results produce two types of words: operators and operands. Operators include: { , -, *, /, (,)} operands include int and double types. The word sequence produced above is {-25, *, (, 56, , 15,)}. These words also need to be saved.
The lexical analysis is correct after the resulting word sequence is analyzed.
Definition E is an expression, n is a constant (considered to a terminal). The generation of expressions can be represented as follows:
E à n
E à (e)
E à e e
E à e-e
E à e * e
E à e / e
Eliminate the generation of the left (e_ is the new symbol):
E-> NE_
E -> (e) e_
E _-> ee_
E _-> - EE_
E _-> * EE_
E _-> / ee_
E _-> null (empty string)
A grammar analyzer that can be recursively constructed according to this feature. The specific details are not described, you can read the source code.
After the syntax analysis is correct, you can ask for value, and use an operand stack and operator stack when evaluating, and an operator priority table (the priority between the operator), the specific details can be read.
/*stack.h*/template
Class Cstack
{
PUBLIC:
Cstack ()
{
HEAD = New Node;
HEAD-> next = NULL;
}
Void Push (T Data) {node * Tem; Tem = head-> next; head-> next = new node; head-> next-> next = tem; head-> next-> data = data;}
Bool Pop (T & DATA) {if (Head-> Next) {data = head-> next-> data; node * tex; delete head-> next; head-> next = tex; Return True;} else returnaf;
Bool gettop (t & data) {if (head-> next) {data = head-> next-> data; return true;} returnaf
Virtual ~ cstack () {node * pnode = head; node * te; while (pnode) {tem = pnode-> next; delete pnode; pnode = teem;}}
Protected: struct node {t data; node * next;}; node * head;
}
Class priorityTable {
INT ** PTABLE; PUBLIC: PriorityTable () {INT I, J; PTABLE = NULL; TABLESIZE = 7; PTABLE = New Int * [TableSize]; for (i = 0; i PTABLE [I] [J] = 1; PTable [4] [5] = PTable [6] [6] = 0; PTABLE [0] [2] = ptable [0] [3] = PTABLE [0] [4] = -1; PTABLE [1] [ 2] = ptable [1] [3] = ptable [1] [4] = -1; ptable [2] [4] = -1; ptable [3] [4] = -1; for (j = 0; J <5; J ) PTABLE [4] [J] = -1; for (j = 0; J <5; J ) PTABLE [6] [J] = -1;} ~ PriorityTable () {for (int i = 0; i INT ChartoIndex (CHAR CH) {Switch (CA) {CASE ' ': Return 0; Case '-': Return 1; Case '*': Return 2; Case '/': Return 3; Case '(': Return 4; Case ')': return 5; Case '#': return 6; default: return -1;}} int Compare (const char FirstOper, const char SecondOper) {int FirstIndex = CharToIndex (FirstOper); int SecondIndex = CharToIndex (SecondOper); if (!! FirstIndex = && SecondIndex -1 = -1) return pTable [FirstIndex] [SecondIndex] Return-2;} Int Compare (int X, int y) {if (x> = 0 && x = 0 && y Return PTABLE [X] [Y]; Return -2; } } // Fortest.cpp: Defines the entry point for the console application.// #define maxwordnum 100 # Define MaxWordLength 100 class WordAnalyse {protected: char Words [MaxWordNum] [MaxWordLength]; int WordsAttribute [MaxWordNum]; int CurrentWordNum; char * pCurrentLocation; char * pLastLocation; bool bResult; bool WordType; char Expression [100]; public: WordAnalyse (char * chExpression ) {INT I, J; for (i = 0; i { For (j = 0; J Words [i] [j] = '/ 0'; Wordsattribute [i] = 0; } Currentwordnum = 0; PcurrentLocation = NULL; STRCPY (Expression, "("); STRCAT (Expression, Chexpression); PcurrentLocation = Expression 1; PlastLocation = Expression; BRESULT = Wordsanalyse (); WordType = isallDouble (); } INT getWordNum () {Return CurrentWordNum;} char * getWord (int index) {if (index> = currentwordnum) Return Null; else returnem [index];} INT getWordAttribute (int index) {if (index> = currentwordnum) return -100; return WordSattribute [index]; Bool getResult () {return bresult;} Bool typeisdouble () {return wordtype;} protected: Bool isalldouble () {for (int i = 0; i {IF (Wordsattribute [i] == 1 ||! Strcmp (Words [i], "/")) Return true;} Return False; Bool Wordsanalyse () {while (* pcurrentlocation! = '/ 0') if (! generateword ()) Return False; Return true;} Bool IsNumber (CHAR CH) {IF (CH> = '0' && Ch <= '9') Return True; Return False;} Bool generateWord () {if (* pcurrentlocation == ') DO {pcurrentlocation ;} while (* pcurrentlocation =='); switch (* pcurrentlocation) {case ' ': case '*': Case '/': case '(': case ')': case '#': Words [CurrentWordNum] [0] = * pCurrentLocation; WordsAttribute [CurrentWordNum] = 2; CurrentWordNum ; pLastLocation = pCurrentLocation; pCurrentLocation ; return true; case '-': if (* PlastLocation! = '(') // - Number of binocular operators {Words [currentwordnum] [0] = * pcurrentlocation; WordSattribute [currentwordnum] = 2;} else // - for single-purpose operator {Words [ CurrentWordNum] [0] = '0'; WordSattribute [currentwordnum] = 0; CURRENTNUM ; Words [currentwordnum] [0] = '-'; WordSattribute [CurrentWordNum] = 2; CURRENTWORDNUM ; plastLocation = pcurrentlocation; pcurrentlocation ; returntrue; case '0': Case '1': Case '2': Case '3': Case '4': Case '5': Case '6': Case '7' : Case '8': Case '9': INT I; I = 0; Do {Words [CurrentWordNum] [i ] = * pcurrentlocation; plastlocation = pcurrentlocation; pcurrentlocation ;} while (isnumber (* pcurrentlocation)); if (* pcurrentlocation == '.') {Words [currentwordnum] [i ] = * PCurrentLocation; pCurrentLocation ; if return false (IsNumber (* pCurrentLocation)!); While (IsNumber (* pCurrentLocation)) {Words [CurrentWordNum] [i ] = * pCurrentLocation; pLastLocation = pCurrentLocation; pCurrentLocation ;} WordsAttribute [CurrentWordNum] = 1 CurrentWordNum ; return true;} else {currentwordnum ; returntrue;} default: return false;} returnaf } #include "wordanalyse.h" class SyntaxAnalyse {bool bResult; int WordIndex; public: SyntaxAnalyse () {bResult = true; WordIndex = 0;} bool Analyse (WordAnalyse * pWords); protected: void E (WordAnalyse * pWords); void E_ (WordAnalyse * pWords); // void n (Wordanalyse * PWORDS); Bool syntaxanalyse ::== false * pwords {ix (pwords-> getResult () == false) Return False; E (PWORDS); if (WordIndex } Void syntaxanalyse :: e (Wordanalyse * pwords) {if (pwords-> getword (wordindex), "(") == 0) {WordIndex ; E (PWORDS); if (strcmp (pwords-> getWord (WordIndex) , ")") == 0) {WordIndex ; E_ (PWORDS);} else {bresult = false; return;}} else if (pwords-> getWordAttribute (WordIndex)! = 2) {WordIndex ; E_ (PWORDS); } Else {brest = false; return;}} Void syntaxanalyse :: e_ (Wordanalyse * Pwords) {// char TEM [100] = "/ 0"; // STRCPY (TEM, Words.GetWord (WordIndex)); // char Operator = Tem [0]; IF ( Strcmp (WordInds-> getWord (WordIndex), " ") == 0 || strcmp (pwords-> getword (wordindex), "-") == 0 || strcmp (PWORDS-> getWord (WordIndex), "* ") == 0 || Strcmp (PWORDS-> getWord (WordIndex)," / ") == 0) {WordIndex ; E (PWORDS); E_ (PWORDS);} else return;} #include" stack.h " #include "CompareTable.h" #include "SyntaxAnalyse.h" class CalExpression {public: CalExpression (char * Expression); int GetValueType (); int GetIntResult (); double GetDoubleResult (); bool GetResult (); int Calculate () protected: int Operate (CHAR OPERATOR, INT FIR, INT Sec); Double Operate (Char Operator, Double FIR, DOUBLE Sec); protected: PriorityTable MyTable; Wordanalyse Mywords; Syntaxanalyse Mysyntax; Protected: Bool Bresult; Int Nresult; Double Dresult; Int ValyType; Calexpression :: Calexpression: mywords (express = false; nresult = 0; DRESULT = 0; valueetype = -1;} Bool Calexpression :: getResult () {Return BRESULT;} INT CALEXPIEPE :: getValueType () {Return ValueType; INT CALEXPRESSION :: Operate (CHAR OPERATOR, INT FIR, INT Sec) {switch (operator) {case ' ': Return FIR Sec; Case '-': Return FIR - Sec; CASE '*': Return FIR * SEC Case '/': returnifer / sec;} return 0;} Double Calexpression :: Operate (Char Operator, Double FIR, Double Sec) {Switch (Operator) {CASE ' ': Return FIR Sec; Case '-': Return FIR - Sec; Case '*': Return FIR * SEC Case '/': return FIR / sec;} Return 0;} int CaleXpression :: getInetResult () {Return NResult;} Double Calexpression :: getDoubleresult () {Return Dresult; INT CALEXPRESSION :: Calculate () {BRESULT = FALSE; NRESULT = 0; DRESULT = 0; valueType = -1; If (! mysyntax.Analyse (& mywords)) Return ValueType = -1; if (mywords.typeisdouble ()) {cstract CHARSTACK; Cstack ValuestAck; Charstack.push ('#'); int WordIndex = 0; char Top; charstack.gettop (TOP); while (! ("#") == 0 && TOP == '#')) {If (Mywords.GetWordAttribute (WordIndex)! = 2) {Double Value = ATOF (Mywords.GetWord (WordIndex)); ValueStack.push (Value); WordIndex ;} else {switch (MyTable. Compare (Top, (Mywords.GetWord (WordIndex) [0])) {case -1: charstack.push ((Mywords.GetWord) (WordIndex) [0]); WordIndex ; Break; Case 0: charstack.pop; WordIndex ; Break; Case 1: {Double NfirNum, Nsecnum, NResult; Char Operator; Valuestack.Pop (nsecnum ); ValueStack.POP (nfirnum); charstack.pop (operator); NRESULT = Operate (Operator, nfirnum, nsecnum); Valuestack.push (NRESULT); Break;}} charstack.gettop (TOP); Valuestack.gettop (Dresult); valueetype = 1; returnit 1;} else {cstract CHARSTACK; Cstack ValuestAck; Charstack.push ('#'); Int WordIndex = 0; Char Top; Charstack.gettop (TOP); While (! ("MYWORDS.GETWORD (WordIndex)," # ") == 0 && TOP == '#')) {If (Mywords.GetWordAttribute (WordIndex)! = 2) {INT Value = ATOI (Mywords.GetWord (WordIndex)); Valuestack.push (Value); WordIndex ;} else {switch (MyTable. Compare (Top, (Mywords.GetWord (WordIndex) [0])) {case -1: charstack.push ((Mywords.GetWord) (WordIndex) [0]); WordIndex ; Break; Case 0: charstack.pop; WordIndex ; Break; Case 1: {Int nfirnum, nsecnum, nresult; char Operator; valueStack.pop (nsecnum ); ValueStack.POP (nfirnum); charstack.pop (operator); NRESULT = Operate (Operator, nfirnum, nsecnum); Valuestack.push (NRESULT); Break;}} charstack.gettop (TOP); Valuestack.gettop (nresult); valueetype = 0; return 0; }