郁闷的C小加(三)(nyoj 409)

15 篇文章 0 订阅
5 篇文章 0 订阅

郁闷的C小加(三)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
聪明的你帮助C小加解决了中缀表达式到后缀表达式的转换(详情请参考“郁闷的C小加(一)”),C小加很高兴。但C小加是个爱思考的人,他又想通过这种方法计算一个表达式的值。即先把表达式转换为前缀和后缀表达式,再求值。这时又要考虑操作数是小数和多位数的情况。
输入
第一行输入一个整数T,共有T组测试数据(T<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数并且小于1000000。
数据保证除数不会为0。
输出
对于每组测试数据输出结果包括三行,先输出转换后的前缀和后缀表达式,再输出计算结果,结果保留两位小数。
样例输入
2
1+2=
(19+21)*3-4/5=
样例输出
+ 1 2 =
1 2 + =
3.00
- * + 19 21 3 / 4 5 =
19 21 + 3 * 4 5 / - =
119.20


中缀转前缀:

从后往前

得到一个操作符或者操作数。
如果是操作数就输入到数组,
如果是')'压栈,
如果是'(' 栈顶出栈直到栈顶为')',然后将')'也弹出
如果是运算符,优先级大于等于栈顶元素,压栈
优先级小于栈顶元素,反复出栈,并将出栈的元素输入到数组,直到优先级大于等于栈顶元素,并将此运算符压栈 
输入结束,就将栈里的元素全部出栈输入到数组,直到栈空。 


中缀转后缀:

从前往后

得到一个操作符或者操作数。
如果是操作数就输入到数组,
如果是'('压栈,
如果是')' 栈顶出栈直到栈顶为'(',然后将'('也弹出
如果是运算符,优先级大于栈顶元素,压栈
优先级小于等于栈顶元素,
反复出栈,并将出栈的元素输入到数组,直到优先级大于栈顶元素,并将此运算符压栈 
输入结束,就将栈里的元素全部出栈输入到数组,直到栈空。 


#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stack>
using namespace std;

char a[1010], b[1010], c[1010];//b后缀,c前缀 
int k = 0;
stack<char> s; 
stack<double> num;

int first(char ch)
{//优先级 
    switch(ch)
    {
	    case '+':
	    case '-':
			return 1;
	    case '*':
	    case '/':
			return 2;
	    default:
			return 0;
    }
}

void change1()
{//中缀转前缀 
	int i, len = strlen(a);
	char t;
	s.push('#');
	c[k ++] = '=';
	for(i = len - 2; i>= 0;)
	{
		if(isdigit(a[i]) || a[i] == '.')
		{
			c[k ++] = ' ';
			while(isdigit(a[i]) || a[i] == '.')
			{
				c[k ++] = a[i];
				i --;
			}		
		}
		else if(a[i] == ')')
		{
			s.push(a[i]);
			i --;
		}
		else if(a[i] == '(')
		{
			t = s.top();
			while(t != ')')
			{
				c[k ++] = ' ';
				c[k ++] = t;
				s.pop();
				t = s.top();	
			}
			s.pop();
			i --;
		}
		else
		{
			t = s.top();
			while(first(a[i]) < first(t))
			{
				c[k ++] = ' ';
				c[k ++] = t;
				s.pop();
				t = s.top();
			}
			s.push(a[i]);
			i --;
		}
	}
	t = s.top();
	while(t != '#')
	{
		c[k ++] = ' ';
		c[k ++] = t;
		s.pop();
		t = s.top();
	}
	c[k ++] = '\0';
} 

void change2()
{//中缀转换为后缀 
	int len = strlen(a);
	int i;
	s.push('#');
	for(i = 0; i < len - 1;)
	{
		if(isdigit(a[i]) || a[i] == '.')
		{
			while(isdigit(a[i]) || a[i] == '.')
			{
				b[k ++] = a[i];
				i++;
			}
			b[k ++] = ' ';
		}
		else if(a[i] == '(')
		{
			s.push(a[i]);
			i++;
		}
		else if(a[i] == ')')
		{
			while(s.top() != '(')
			{
				b[k ++] = s.top();
				s.pop();
				b[k ++] = ' ';
			}
			s.pop();
			i++;
		}
		else
		{
			char t = s.top();
			while(first(t) >= first(a[i]))
			{
				b[k ++] = t;
				b[k ++] = ' ';			
				s.pop();
				t = s.top();
			}
			s.push(a[i]);
			i++;
		}
	}
	char t = s.top();
	while(t != '#')
	{
		b[k ++] = t;
		s.pop();
		b[k ++] = ' ';
		t = s.top();
	}
	b[k ++] = '=';
	b[k ++] = '\0';
}

void g(char x)
{//计算 
	double a = num.top();
	num.pop();
	double b = num.top();
	num.pop();
	switch(x)
	{
		case'+':
			num.push(a + b);
			break;
		case'-':
			num.push(b - a);
			break;
		case'*':
			num.push(a * b);
			break;
		case'/':
			num.push(b / a);
			break;
	}
}

void count()
{//根据后缀式计算 
	int i, len = strlen(b);
	double temp = 0;
	for(i = 0; i < len - 1; )
	{
		if(isdigit(b[i]) || b[i] == '.')
		{
			int f = 0; 
			while(isdigit(b[i]) || b[i] == '.')
			{
				if(isdigit(b[i]))
				{
					temp = temp * 10 + (b[i] - '0');
					if(f != 0)
						f ++; 
				}
				else
					f = 1;
				i++; 
			}
			if(f != 0)
				temp = temp / pow(10, f - 1);
			//printf("%lf\n", temp);
			num.push(temp);
			temp = 0;
		}
		else if(b[i] == ' ')
		{
			i++;
		}
		else 
		{
			g(b[i]);
			i++;
		}
	}
}

int main (void)
{
	int n, i;
	scanf("%d", &n);
	while(n --)
	{
		scanf("%s", a);
		change1();
		k = 0;
		change2();
		count();		
		for(i = strlen(c) - 1; i >= 0; i--)
		{
			printf("%c", c[i]);
		}
		printf("\n");		
		printf("%s\n", b);
		printf("%.2lf\n", num.top());
		num.pop();
		k = 0;
	}
	return 0;
}




x1y2 x2y3 x3y1-x1y3-x2y1-x3y2 是计算角形面积的公式中的一部分。 在这个公式中,x1、x2、x3分别表示角形的个顶点的x坐标,y1、y2、y3分别表示角形的个顶点的y坐标。通过计算这个表达式的值,可以得到角形的面积。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [TetraCluster:使用并行Java 2库的Java并行程序。 该程序在群集并行计算机上运行,​​以从给定的点集中找到...](https://download.csdn.net/download/weixin_42171208/18283141)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [线性代数有个题,求正交变换x=Qy,化二次型f(x1,x2,x3)=8x1x2+8x1x3+8x2x3为标准型求出特征值](https://blog.csdn.net/weixin_39956182/article/details/115882118)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [nyoj-67-角形面积(S=(1/2)*(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2))](https://blog.csdn.net/weixin_30492601/article/details/99541033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值