Expression Evaluation (1) | C++ | Stack

1. Topic description

background:

Our textbook has introduced the expression evaluation algorithm, now we expand the function of the algorithm, and the operators required to be processed include: +, -, *, /, % (integer remainder), ^ (multiplication square),(,).

Require:

Using the operator priority algorithm, only integers are reserved for the intermediate results of the calculation.

enter:

The first row is an integer N. Indicates that there are N expressions below

The next N lines starting from the second line are N expressions composed of integers

output:

A total of N lines, each line is the calculation result of the corresponding expression.

If it is judged that the expression is wrong, then output: error.

If the divisor is 0 during the calculation, output: Divide 0.

Note on special circumstances:

In expressions, special care should be taken if operands appear negative (eg -8). For example:
10 plus -8 is expressed as: 10+-8.
10 minus -8 is expressed as: 10--8.

test input expected output time limit memory limit extra process
Test case 1 display as text
  1. 4↵
  2. 2^3↵
  3. 2^0↵
  4. 2^3^2↵
  5. 2^(3-1)^(10-8)↵
display as text
  1. 8↵
  2. 1↵
  3. 512↵
  4. 16↵
1 second 64M 0
Test case 2 display as text
  1. 11↵
  2. (2+8↵
  3. 2+8)↵
  4. 8/0↵
  5. 8/(8+5-13)↵
  6. 2^(2-5)↵
  7. 10-(80-30(/3*3+4↵
  8. 10-80-30)/3*3+4↵
  9. (2+8)(3+2)↵
  10. (2)3(8)↵
  11. 30(/3+3)+4↵
  12. 10(20-8)+2↵
display as text
  1. error.↵
  2. error.↵
  3. Divide 0.↵
  4. Divide 0.↵
  5. error.↵
  6. error.↵
  7. error.↵
  8. error.↵
  9. error.↵
  10. error.↵
  11. error.↵
1 second 64M 0
Test case 3 display as text
  1. 2↵
  2. 10(10)↵
  3. 14*10-(10)2↵
display as text
  1. error.↵
  2. error.↵
1 second 64M 0
Test case 5 display as text
  1. 14↵
  2. 18-32↵
  3. 18/4↵
  4. 18%3↵
  5. 10+20*4↵
  6. 10-20/4↵
  7. (18-3)*3↵
  8. 10*(10)↵
  9. (10+2)/(8-10)↵
  10. (2*3)/(5*2)↵
  11. 10-(80-30)/3*3+4↵
  12. (((2+8)*2-(2+4)/2)*2-8)*2↵
  13. (((8+2)*(4/2)))↵
  14. 10/0↵
  15. (10-80*2↵
display as text
  1. -14↵
  2. 4↵
  3. 0↵
  4. 90↵
  5. 5↵
  6. 45↵
  7. 100↵
  8. -6↵
  9. 0↵
  10. -34↵
  11. 52↵
  12. 20↵
  13. Divide 0.↵
  14. error.↵
1 second 64M 0

2. Points for attention in operation

Using the stack to process expressions, the specific operation process is not much to say, the foundation of the foundation.

Let me talk about a few problems I encountered in the process of writing, and remind my classmates (or younger students).

1. In terms of operating negative numbers, I use strings, so that when I read '-', I can directly read its previous digit without worrying about being erased in a new cycle. 

If a negative sign is read, and it is the first character of the string or its previous character is an operator, skip it directly.

When reading numbers, keep an eye out, if its previous digit is a negative sign, and its previous digit is an operator, then flag=-1.

2. The situation of error.

It may be an error if two consecutive operators such as **, *^, -% etc. are read.

If the exponent is negative during exponent operation, it is also an error.

If there is no '(' matching ')' in the stack, it is an error.

After the operation is completed, the stack of the storage operator is not empty, and it cannot be calculated, which is an error.

3、divide 0。

Output divide 0 when encountering /0 and %0. Compared with error, the divide 0 situation is much easier to write, don't forget it.


full code

#include<bits/stdc++.h> 
using namespace std;
//clt意为calculate,用来计算两个数的结果 
void clt(int *base, int ind, char op) {
	switch (op) {
		case '+': (*base) = (*base) + ind; break;
		case '-': (*base) = (*base) - ind; break;
		case '*': (*base) = (*base) * ind; break;
		case '/': (*base) = (*base) / ind; break;
		case '%': (*base) = (*base) % ind; break;
		case '^': (*base) = pow((*base),ind); break;
	}
}

//TypeDe判断是数字还是运算符,数字返回1,运算符返回0 
int TypeDe(char c) {
	if (c>='0' && c<='9') return 1;
	else 		   		  return 0;
}

//lvl意为level,定义单个运算符的优先级 
int lvl(char c) {
	switch (c) {
		case '(': return 0;
		case '+': case '-': return 1;
		case '*': case '/': case '%': return 2;
		case '^': return 3;
		case ')': return 4;
	}
}

//cmp意为compare,用来比较运算符之间的优先级 
int cmp(char op_top, char c) {
	int lvl(char);
	if (op_top=='^' && c=='^') return 0;
	if ( lvl(op_top)>=lvl(c) ) return 1;
	else 					   return 0;
}

int main(){
	
	int TypeDe(char); 
	void clt(int*, int, char);
	int cmp(char, char);
	
	int n;
	cin >> n;
	for (int i=0;i<n;i++) {
	
		stack<char> op;
		stack<int> data;
		string Formula;
		cin >> Formula;
		int p=0, len=Formula.length();
		while ( p<len ) {
			if (Formula[p]>='0' && Formula[p]<='9') {
				int flag=1, cnt=0;
				if ( (p==1 && Formula[0]=='-') || (p>1 && Formula[p-1]=='-' && TypeDe(Formula[p-2])==0 ) ) {
					flag = -1;
				}
				while (Formula[p]>='0' && Formula[p]<='9') {
					cnt = cnt*10 + Formula[p] - '0';
					p++;
				}
				data.push(cnt*flag);
			}
		
			else {
				if ( (p==0 && Formula[p]=='-') || (p>0 && Formula[p]=='-' && TypeDe(Formula[p-1])==0 ) ) 
					{  }
				else if ( (Formula[p]!='(') && (Formula[p-1]!=')') && (TypeDe(Formula[p])==0 && TypeDe(Formula[p-1])==0) ) {
					cout << "error." << endl;
					goto m;
				}
				else {
					if ( op.size() && ( (op.top()!='(' && Formula[p]==')') || (cmp(op.top(), Formula[p]))>0 ) && Formula[p]!='(') {
						while ( op.size() && ( (op.top()!='(' && Formula[p]==')') || (cmp(op.top(), Formula[p]))>0 ) && Formula[p]!='(') {
							int d = data.top();
							data.pop();
							if ( d==0 && (op.top()=='/' || op.top()=='%') ) {
								cout << "Divide 0." << endl;
								goto m;
							}
							else if ( d<0 && op.top()=='^' ) {
								cout << "error." << endl;
								goto m;
							}
							else clt(&data.top(), d, op.top());
							op.pop();
						}
					}
					if (Formula[p]==')' && op.size()==0) {
						cout << "error." << endl;
						goto m;
					}
					else    if (Formula[p]==')') {
								op.pop();
							}
							else {
								op.push(Formula[p]);
							}
				}
				p++;
			}
		}
		
		if (op.size()+1==data.size()) {
			while (op.size()) {
				int d = data.top();
				data.pop();
				if (d==0 && (op.top()=='/' || op.top()=='%')) {
					cout << "Divide 0." << endl;
					goto m;
				}
				else if ( d<0 && op.top()=='^' ) {
						cout << "error." << endl;
						goto m;
					}
				else clt(&data.top(),d,op.top());
				op.pop();
			}
			cout << data.top() << endl;
		}
		else cout << "error." << endl;
	
m:	;
	}
	 
	return 0;
}

Guess you like

Origin blog.csdn.net/m0_70241024/article/details/126985489