1: Preface
The so-called expression evaluation is to write a micro-calculator. For example, input: (1+9)* 2/2-1, output 9. For such problems, we usually use stack to simulate mathematical operations. In order to simplify the problem, before proceeding with the following analysis, let's make a convention here: this paper only discusses the four basic operations of +-*/(), and does not do exception handling for unexpected symbols (such as ^) and non-conforming mathematical expressions (such as 2*-1).
II: Thought and Analysis
_We use an array of characters (char s[1000]) to store mathematical expressions, and define a global variable g_pos to represent the subscripts of s [, starting from 0. Firstly, we define two stacks, optr and opnd, which store operators and operands respectively, and put operands directly into opnd when we encounter them.
(1) encounters a negative sign;
(2) encounter right parentheses;
(3) encounter left parentheses;
(4) encounter +-*/;
The first three situations are easy to understand, so let's talk about the fourth. We all know that the four operations are multiplied, divided and subtracted (for example, 2*3+1), so for each operator, we should compare the top symbol level of optr. If the symbol level is higher than the top symbol level of OPTR stack, do nothing and put it on the stack directly. If it is less than or equal, we need to extract the top two numbers of opnd stack and calculate them. There is a problem here. When we encounter the first operator, the OPTR is empty, and we need to compare the level with the top operator of the OPTR stack. What should we do then? To solve this problem, when we initialize optr, we put in a # and set it to the lowest level.
Seen here, you may still have a question, how to determine the sign - minus sign or minus sign? For example - 1 + 2 and 5 - 1 + 2.
_Analysis shows that there are only two cases of negative sign:
The left side of(1) is the left bracket, for example (-1+5*3);
The first character of the(2) string, such as -5*6-1.
In order to facilitate code writing, if there is a negative sign, add a number 0 to the arithmetic stack (which is why the bool value is_minus appears in the following code), that is, convert the expression, such as -1+2 to 0-1+2.
Three: Code
/** * * author Limer * data 2017-02-24 * mode C++ */ #include<iostream> #include<algorithm> #include<cstring> #include<stack> #include<cmath> using namespace std; char s[1000]; int g_pos;//Subscription of character array /* Character to Number */ double Translation(int & pos) { double integer = 0.0; //Integral part double remainder = 0.0; //Remainder part int c = 0; while (s[pos] >= '0'&&s[pos] <= '9') { integer *= pow(10, c); c++; integer += (s[pos] - '0'); pos++; } if (s[pos] == '.') { pos++; c = 1; while (s[pos] >= '0'&&s[pos] <= '9') { double t = s[pos] - '0'; t *= pow(0.1, c); c++; remainder += t; pos++; } } return integer + remainder; } /* Return operator level */ int GetLevel(char ch) { switch (ch) { case '+': case '-':return 1; case '*': case '/':return 2; case '(':return 0; case '#':return -1; }; } /* Operate on two numbers */ double Operate(double a1, char op, double a2) { switch (op) { case '+':return a1 + a2; case '-':return a1 - a2; case '*':return a1*a2; case '/':return a1 / a2; }; } /* Using two stacks to simulate computation */ double Compute() { stack<char> optr; //Operator stack stack<double> opnd; //Operand stack optr.push('#'); int len = strlen(s); bool is_minus = true; //Judging whether'-'is a minus sign or a minus sign for (g_pos = 0; g_pos < len;) { //1. minus sign if (s[g_pos] == '-'&&is_minus) //Minus sign { opnd.push(0); optr.push('-'); g_pos++; } //2. Right parentheses) else if (s[g_pos] == ')') { is_minus = false; g_pos++; while (optr.top() != '(') { double a2 = opnd.top(); opnd.pop(); double a1 = opnd.top(); opnd.pop(); char op = optr.top(); optr.pop(); double result = Operate(a1, op, a2); opnd.push(result); } optr.pop(); //Delete '' } //3. figures else if (s[g_pos] >= '0' && s[g_pos] <= '9') { is_minus = false; opnd.push(Translation(g_pos)); } //4. (Left parentheses) else if (s[g_pos] == '(') { is_minus = true; optr.push(s[g_pos]); g_pos++; } //5. + - * / Four else { while (GetLevel(s[g_pos]) <= GetLevel(optr.top())) { double a2 = opnd.top(); opnd.pop(); double a1 = opnd.top(); opnd.pop(); char op = optr.top(); optr.pop(); double result = Operate(a1, op, a2); opnd.push(result); } optr.push(s[g_pos]); g_pos++; } } while (optr.top() != '#') { double a2 = opnd.top(); opnd.pop(); double a1 = opnd.top(); opnd.pop(); char op = optr.top(); optr.pop(); double result = Operate(a1, op, a2); opnd.push(result); } return opnd.top(); } int main() { return 0; }
Turn to my personal blog: http://www.61mon.com/index.php/archives/180/