郁闷的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
-
哈哈哈,180行代码;
-
将中缀表达式转换为前缀表达式: 遵循以下步骤: (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2; (2) 从右至左扫描中缀表达式;。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 (3) 遇到操作数时,将其压入S2; (4) 遇到运算符时,比较其与S1栈顶运算符的优先级: (4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈; (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;//**************************************注意当运算级别相等的时候也要压进去,不弹出来,这点和转后缀不同,转后缀是运算级别相等的时候弹出来,出栈********************************************************** (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较; (5) 遇到括号时: (5-1) 如果是右括号“)”,则直接压入S1; (5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃; (6) 重复步骤(2)至(5),直到表达式的最左边; (7) 将S1中剩余的运算符依次弹出并压入S2; (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
-
前缀表达式的计算机求值: 从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。 例如前缀表达式“- × + 3 4 5 6”: (1) 从右至左扫描,将6、5、4、3压入堆栈; (2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈; (3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈; (4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。 可以看出,用计算机计算前缀表达式的值是很容易的。
-
将中缀表达式转换为后缀表达式: 与转换为前缀表达式相似,遵循以下步骤: (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2; (2) 从左至右扫描中缀表达式;。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 (3) 遇到操作数时,将其压入S2; (4) 遇到运算符时,比较其与S1栈顶运算符的优先级: (4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈; (4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况); (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较; (5) 遇到括号时: (5-1) 如果是左括号“(”,则直接压入S1; (5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃; (6) 重复步骤(2)至(5),直到表达式的最右边; (7) 将S1中剩余的运算符依次弹出并压入S2; (8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。 后缀表达式的计算机求值: 与前缀表达式类似,只是顺序是从左至右: 从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op
栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。 例如后缀表达式“3 4 + 5 × 6 -”: (1) 从左至右扫描,将3和4压入堆栈; (2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈; (3) 将5入栈; (4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈; (5) 将6入栈; (6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
-
第一行输入一个整数T,共有T组测试数据(T<10)。
-
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<iostream> using namespace std; int we(char a) { switch(a) { case '-' : case '+' : return 1; break; case '/' : case '*' : return 2; break; case '(' : return 0; break; default : return -1; } } int main() { int j,k,n,t,top,p; scanf("%d",&n); while(n--) { int you=-1,l=0; char s7[1010]; char s8[1010]; int f=0,k=0; char s[15]; char s2[1000+10],s3[1000+10],s1[1000+10]; double s4[10010]; memset(s4,0,sizeof(s4)); scanf("%s",s1); t=strlen(s1); int j=-1,top=0; for(int i=0; i<t; i++)//转化为后缀 { if((s1[i]>='0'&&s1[i]<='9')||s1[i]=='.') { s3[++j]=s1[i]; } else if(s1[i]=='(') { s2[++top]=s1[i]; } else if(s1[i]==')') { while(s2[top]!='(') { s3[++j]=' '; s3[++j]=s2[top]; --top; } --top; } else if(s1[i]=='/'||s1[i]=='*'||s1[i]=='-'||s1[i]=='+') { while(we(s1[i])<=we(s2[top])) { s3[++j]=' '; s3[++j]=s2[top]; --top; } s3[++j]=' '; s2[++top]=s1[i]; } } while(top>=1) { s3[++j]=' '; s3[++j]=s2[top]; --top; if(s2[1]=='(') break; } s3[++j]='\0'; for(int i=t-1; i>=0; i--)//转换为前缀 { if((s1[i]>='0'&&s1[i]<='9')||s1[i]=='.') { s7[++you]=s1[i]; } else if(s1[i]==')') { s8[++l]=s1[i]; } else if(s1[i]=='(') { while(s8[l]!=')') { s7[++you]=' '; s7[++you]=s8[l]; --l; } --l; } else if(s1[i]=='/'||s1[i]=='*'||s1[i]=='-'||s1[i]=='+') { while(we(s1[i])<we(s8[l])) { s7[++you]=' '; s7[++you]=s8[l]; --l; } s7[++you]=' '; s8[++l]=s1[i]; } } while(l>=1) { s7[++you]=' '; s7[++you]=s8[l]; --l; if(s8[1]==')') break; } s7[++you]='\0'; for(int i=you-1;i>=0;i--) { printf("%c",s7[i]); } printf(" =\n"); printf("%s =\n",s3); int p=0; k=0; for(int i=0; i<j; i++)//利用后缀表达式求值 { if(s3[i]>='0'&&s3[i]<='9'||s3[i]=='.') { s[k++]=s3[i]; f=1; continue; } if(f) { s[k]='\0'; s4[p++]=atof(s); f=0,k=0; } else if(s3[i]==' ') continue; else if(s3[i]=='+'||s3[i]=='-'||s3[i]=='*'||s3[i]=='/') { double we; double ni,ha; p=p-1; ni=s4[p]; ha=s4[--p]; if(s3[i]=='+') { we=ni+ha; s4[p++]=we; } if(s3[i]=='-') { we=ha-ni; s4[p++]=we; } if(s3[i]=='*') { we=ha*ni; s4[p++]=we; } if(s3[i]=='/') { we=ha/ni; s4[p++]=we; } } } printf("%.2lf\n",s4[p-1]); } return 0; }