1. 程式人生 > >NYOJ 35-表示式求值

NYOJ 35-表示式求值

表示式求值

時間限制:3000 ms  |  記憶體限制:65535 KB 難度:4
描述
ACM隊的mdd想做一個計算器,但是,他要做的不僅僅是一計算一個A+B的計算器,他想實現隨便輸入一個表示式都能求出它的值的計算器,現在請你幫助他來實現這個計算器吧。
比如輸入:“1+2/4=”,程式就輸出1.50(結果保留兩位小數)
輸入
第一行輸入一個整數n,共有n組測試資料(n<10)。
每組測試資料只有一行,是一個長度不超過1000的字串,表示這個運算式,每個運算式都是以“=”結束。這個表示式裡只包含+-*/與小括號這幾種符號。其中小括號可以巢狀使用。資料保證輸入的運算元中不會出現負數。
資料保證除數不會為0
輸出
每組都輸出該組運算式的運算結果,輸出結果保留兩位小數。
樣例輸入
2
1.000+2/4=
((1+2)*5+1)/4=
樣例輸出
1.50
4.00

用兩個棧實現,一個存運算子一個存結果,如果遇到數字則壓入存結果的棧,如果是左括號,則直接壓入運算子的棧,如果是運算子,則比較一下如果存運算子的棧棧定元素的優先順序高於或者等於當前運算子的優先順序,則彈出兩個數字和一個運算子進行運算,結果再存到結果的棧裡,直到棧定的運算子低於當前讀入的運算子或者遇到 ( ,則把當前的運算子壓棧,需要注意的是)和=的處理方式和+ - 一樣,但不同的是 + - 在彈棧完成後會把當前的運算子 + 或者- 壓棧,而 )和=則不會壓棧,只會抵消一個(,所以有一個小技巧就是在運算前就壓入一個(來抵消最後=的壓入,否則很容易在=處理時棧空而報錯

 
#include<stdio.h>
#include<stack>
#include<stdlib.h>
using namespace std;

stack<double> stack_num;
stack<char> stack_ch;
char str[1003];
char number[100];
void calculate_1()
{
	char ch;
	double num1, num2;
	ch = stack_ch.top();
	while(ch != '(')
	{
		num1 = stack_num.top();
		stack_num.pop();
		num2 = stack_num.top();
		stack_num.pop();
		switch(ch)
		{
		case '*':
			num2 *= num1;
			break;
		case '/':
			num2/= num1;
			break;
		case '+':
			num2 += num1;
			break;
		case '-':
			num2 -= num1;
			break;
		}
		stack_num.push(num2);
		stack_ch.pop();
		ch = stack_ch.top();	
	}
}
void calculate_2()
{
	char ch;
	double num1, num2;
	ch = stack_ch.top();
	while(ch == '*' || ch == '/')
	{
		num1 = stack_num.top();
		stack_num.pop();
		num2 = stack_num.top();
		stack_num.pop();
		switch(ch)
		{
		case '*':
			num2 *= num1;
			break;
		case '/':
			num2/= num1;
			break;
		}
		stack_num.push(num2);
		stack_ch.pop();
		ch = stack_ch.top();	
	}
}
int main()
{
	int num;
	int k;
	double n;
	scanf("%d", &num);
	getchar();
	while(num--)
	{
		k = 0;
		gets(str);
		stack_ch.push('(');
		int i;
		for(i = 0; str[i];i++)
		{
			if(str[i] >= '0' && str[i] <= '9' || str[i] == '.')
			{
				number[k++] = str[i];
				continue;
			}
			number[k] = 0;
			if(number[0] != 0)
			{
				n = atof(number);
				number[0] = 0;
				stack_num.push(n);
			}
			k = 0;
			switch(str[i])
			{
			case '+':
				calculate_1();
				stack_ch.push('+');
				break;
			case '-':
				calculate_1();
				stack_ch.push('-');
				break;
			case '*':
			case '/':
				calculate_2();
			case '(':
				stack_ch.push(str[i]);
				break;
			case ')':
			case '=':
				calculate_1();
				stack_ch.pop();				
				break;
			}
		}
		printf("%.2lf\n", stack_num.top());
		stack_num.pop();
	}
	return 0;
}