1. Problem description
For a given expression, the expression can include constants, arithmetic operators (including: "+", "-", "*", "/", "%" (remainder operation), "^" (power operation), "!" (factorial operation)) and parentheses. Write a simple calculator to realize the calculation of the expression.
Basic requirements: input a correct expression from the keyboard, convert the expression into the corresponding suffix expression, and calculate the value of the suffix expression. For simple errors in the expression (for example, divisor cannot be zero, negative number cannot be factorial, etc.), prompt and error information can be given; Expressions can include variables represented by a single letter.
Improve requirements: on the basis of completing the basic requirements, it can support some non-standard expressions (e.g., 3-3 + - 6), support the number expressed by scientific counting method (e.g., 1997140000000 is expressed as: 1.99714E13), and have a simple calculator with graphical user interface
2. Demand analysis
Basic function of the software: input infix expression by keyboard. The program can convert the input infix expression into corresponding suffix expression and calculate the value of suffix expression. For simple errors in input, the program can give a prompt. This program supports the processing of a variety of operands including negative numbers, decimals, multi digits, etc. it can calculate expressions including addition, subtraction, multiplication, division, remainder, exponentiation and other operators, and judge whether the expression brackets match.
Input / output form: the user can use the console according to the input prompt.
Input form:
① Correct infix expression without letter variable;
② Infix expression with simple error.
Output form:
① For the correct infix expression, the converted suffix expression and the calculation result of the expression can be output;
② For infix expressions with simple errors, the program will automatically output error prompts and give error messages.
Test data requirements: you can enter a qualified infix expression or an expression containing simple errors. Expressions can include various types of constants and negative numbers, operators include (+, -, *, /,%, ^), and expressions can also include various parentheses.
3. Data structure to be used: stack
Operation method:
- In order to convert infix expression into suffix expression and calculate it, the function will first call the Fun function to detect whether the expression brackets match. If not, the main function will be returned. Scan infix expressions from left to right. When an operator is encountered, compare its priority with the operator at the top of the s1 stack. When an operand is encountered, press it into s2. When a bracket is encountered, if it is the left bracket '(', press it directly into s1. If it is the right bracket ')', pop up the operators at the top of the s1 stack in turn and press it into s2 until the left bracket 'is encountered (', pop up the left bracket from s1 and discard it (at this time, a pair of brackets are eliminated). Pop up the remaining operators in s1 and press them into s2, pop up the elements in s2 and output them, and reverse the output results to obtain the suffix expression. Scan from left to right, if it is a number, press them into the stack, pop up s1 and s2 in turn, and calculate s2 (+,, *, /) s1 and push it onto the stack.
Pseudo code:
ADT SeqStack
Data
The elements in the stack have the same type and last in first out characteristics, and the adjacent elements have precursor and successor relationships
Operation
SeqStack
Precondition: stack does not exist
Input: None
Function: initialization of stack
Output: None
Post condition: construct an empty stack
~ SeqStack
Precondition: stack already exists
Input: None
Function: destroy stack
Output: None
Post condition: release the storage space occupied by the stack
Push
Precondition: stack already exists
Input: element value x
Function: insert an element x at the top of the stack
Output: if the insertion is unsuccessful, an exception is thrown
Post condition: if the insertion is successful, an element is added to the top of the stack
Pop
Precondition: stack already exists
Input: None
Function: delete stack top element
Output: if the deletion is successful, the value of the deleted element is returned; otherwise, an exception is thrown
Post condition: if the deletion is successful, one element is reduced at the top of the stack
GetTop
Precondition: stack already exists
Input: None
Function: read the current stack top element
Output: if the stack is not empty, return the current stack top element value
Post condition: stack unchanged
Empty
Precondition: stack already exists
Input: None
Function: judge whether the stack is empty
Output: if the stack is empty, return 1; otherwise, return 0
Post condition: stack unchanged
End ADT
Code function realization:
#include <stdio.h> #include <iostream> #include <stdlib.h> #include <string.h> #include <windows.h> #include <math.h> #define pi 3.1415926 using namespace std; /***************************************************************************************************************************************/ /***Function definition section***/ void adorn(char adorn,int n);//Decoration function int fun(char *c1, int s, int e);//Determine whether the brackets match void PrintList(int top,float a[]);//Print calculation results char input();//Read data from keyboard char Change(char c1[]); //Converts infix expressions to suffix expressions and evaluates them int main();//Enables the system to call the main function within a function /***************************************************************************************************************************************/ /***************************************************************************************************************************************/ /***Define three strings to implement stack operations***/ char c1[1024];//Infix expression used to store input char c2[1024];//Stack the logarithm and operators used in the conversion process char c3[1024];//It is used to perform relevant operations after the elements are out of the stack, and re stack the final results /***************************************************************************************************************************************/ /***************************************************************************************************************************************/ /***Define global variables***/ float a[1024];// Output for final calculation results int count=0; /***************************************************************************************************************************************/ /***************************************************************************************************************************************/ /***Implementation of each sub function***/ void adorn(char adorn,int n)//Decoration function { for(int i=0;i<n;i++) { putchar(adorn);//Judge through the Classl code. If it is a number, convert the Classl code - 48 into characters } putchar('\n'); //Force the addition of \ n at the end of the string to facilitate the calculation of the number in the string } int fun(char *c1, int s, int e)//Judge whether parentheses match (1 matches; 0 does not match) { char L; char R; while((s<=e)) { switch(c1[s]) { case '(': L = c1[s]; R = ')'; break; case '[': L = c1[s]; R = ']'; break; case '{': L = c1[s]; R = '}'; break; case ')': return 0; case ']': return 0; case '}': return 0;//If the input string is above characters, 0 is returned default: L = '\0'; break; } if(c1[s] == L) { int p = 1; int q=0; int x = s+1;//t is the next character of s while((x<=e)) // Search for matching closing parentheses { if(c1[x] == L) p++; if(c1[x] == R) q++; if(q>p) return 0; if(p == q) // Then match the parentheses in the matched parentheses { if(fun(c1, s+1, x-1) == 0) // Recursive call, matching inwards from the outermost parentheses return 0; s=x; break; } x++; } if(p>q) return 0; } s++; } return 1;//Returns 1 on both matches } void PrintList(int top,float a[])//Print calculation results { cout<<"The calculation result is:"<<endl; if(a[top]>1000||a[top]<0.001) //Scientific counting method printf("%.3E\n",a[top]); else if(a[top]<=1000||a[top]>=0.001) printf("%.8f\n",a[top]); adorn('-',90); } char input()//Read data from keyboard { int count=0; int i; int j; int m; int n; int top=0; int v=-1; int u=0; fflush(stdin); gets(c1);//Enter c1 } char Change(char c1[])//Converts infix expressions to suffix expressions and evaluates them { fflush(stdin); int count=0; int i; int j; int m; int n; int top=0; int v=-1; int u=0; int k=strlen(c1); int r= fun(c1, 0, k-1); if(r != 1) { printf("**Brackets do not match, please re-enter**: \n"); loop: input(); if(*c1=='#') { main();//Return main function } else { Change(c1); } } else { for(i=0;i<k;i++)//Perform suffix expression conversion on the input array { switch(c1[i]) { case '(': c2[++top]=c1[i]; break; case '+': case '-': while(top>0 && c2[top]!='(')//Judge whether the elements at the top of the stack are parentheses, and if the stack is not empty, take the first two elements out of the stack and operate, and put the operation results back into the stack { c3[++v]=c2[top]; c3[++v]=' '; top--; } c2[++top]=c1[i]; //When the stack is empty or encounters ("), put" - "directly into the stack break; case '*': case '/': while(top>0 && c2[top]!='(' && c2[top]!='+' && c2[top]!='-')//consider order { c3[++v]=c2[top]; c3[++v]=' '; top--; } c2[++top]=c1[i]; break; case '%': while(top>0 && c2[top]!='(' && c2[top]!='+' && c2[top]!='-')//consider order { c3[++v]=c2[top]; c3[++v]=' '; top--; } c2[++top]=c1[i]; break; case '^': while(top>0 && c2[top]!='(' && c2[top]!='+' && c2[top]!='-')//consider order { c3[++v]=c2[top]; c3[++v]=' '; top--; } c2[++top]=c1[i]; break; case '!': while(top>0 && c2[top]!='(' && c2[top]!='+' && c2[top]!='-')//consider order { c3[++v]=c2[top]; c3[++v]=' '; top--; } c2[++top]=c1[i]; break; case ')': while(c2[top]!='('){ c3[++v]=c2[top]; c3[++v]=' '; top--; } top--; break; default: c3[++v]=c1[i]; if(c1[i+1]>'9' || c1[i+1]<'0') c3[++v]=' '; break; } } while(top>0 && c2[top]!='(') { c3[++v]=c2[top]; c3[++v]=' '; top--; } cout<<"The suffix expression is:"<<endl; puts(c3); top=0; float sum; k=strlen(c3); for(i=0;i<k;i++) { if(c3[i]==' ') { ; } else if(c3[i]=='+') { sum=a[top-1]+a[top]; a[--top]=sum; } else if(c3[i]=='-') { sum=a[top-1]-a[top]; a[--top]=sum; } else if(c3[i]=='*') { sum=a[top-1]*a[top]; a[--top]=sum; } else if(c3[i]=='/') { if(a[top]==0) { cout<<"**Input error, divisor cannot be 0, please re-enter**: "<<endl; goto loop; } else { sum=a[top-1]/a[top]; a[--top]=sum; } } else if(c3[i]=='%') { if(a[top]==0) { cout<<"**Input error, the remainder cannot be 0, please re-enter**: "<<endl; goto loop; } else { int sum1=a[top-1]*10; int sum2=a[top]*10; sum=(sum1%sum2)/10; a[--top]=sum; } } else if(c3[i]=='^') { sum=pow(a[top-1],a[top]); a[--top]=sum; } else if(c3[i]=='!') { if(a[top]<0) { cout<<"**Input error, negative number has no factorial, please re-enter**: "<<endl;//Prompt and re-enter input(); goto loop; } else { float sum=1; for(int j=1;j<=a[top];j++) { sum=sum*j; } a[top]=sum; } } else { int m=0; while(c3[i]>='0' && c3[i]<='9') { m=10*m+c3[i]-'0'; i++; } a[++top]=m; } } PrintList(top,a); } } /***************************************************************************************************************************************/ /***************************************************************************************************************************************/ /***Main function part***/ int main() { system("cls");//Realize the DOS function of the starter, clear the contents on the display screen, and make the DOS prompt to the upper left corner of the screen while(1) { fflush(stdin);//Clear buffer value int count=0; int i; int j; int m; int n; int top=0; int v=-1; int u=0; adorn('-',90); cout<<"**Please enter the infix expression to be evaluated,Enter directly. Note that the system only recognizes English symbols**: " <<endl; cout<<"If you want to exit this interface, please enter'#’Key "< < endl; input(); if(*c1=='#') { break; } else { Change(c1); } } } /***************************************************************************************************************************************/