codevs2178 表达式运算Cuties

2 篇文章 0 订阅
1 篇文章 0 订阅

给出一个表达式,其中运算符仅包含+,-,*,/,^要求求出表达式的最终值

数据可能会出现括号情况 还有可能出现多余括号情况

数据保证不会出现>maxlongint的数据

数据可能回出现负数情况

输入描述 Input Description

仅一行,即为表达式

输出描述 Output Description

仅一行,既为表达式算出的结果

样例输入 Sample Input

(2+2)^(1+1)

样例输出 Sample Output

16

数据范围及提示 Data Size & Hint

表达式总长度<=30


题目分析,在计算过程中用codevs3066的方法有点小问题,修改为

将一个中序表达式转化成为后缀表达式方法

       首先维护的是两个栈,我们这里暂且称为S1和S2,S1中的结果最后存的就是逆波兰表达式,S2中将用于暂时存放运算符并且在最终形成逆波兰表达式的时候,该栈是会清空的。下面我们看看怎样具体的形成逆波兰表达式。

       在此首先定义一下运算符的优先级关系,从小到达排序,相同优先级没有用逗号隔开:(,+-,*\,负号,)。

       从左至右遍历一个给定的中序表达式,也就是我们常规的数学计算的表达式。

(1)如果遇到的是数字,我们直接加入到栈S1中;

(2)如果遇到的是左括号,则直接将该左括号加入到栈S2中;

(3)如果遇到的是右括号,那么将栈S2中的运算符一次出栈加入到栈S1中,直到遇到左括号,但是该左括号出栈S2并不加入到栈S1中;

(4)如果遇到的是运算符,包括单目运算符和双目运算符,我们按照下面的规则进行操作:

          (4-1)如果此时栈S2为空,则直接将运算符加入到栈S2中;

          (4-2)如果此时栈S2不为空,当前遍历的运算符的优先级大于(等于,等于删掉)栈顶运算符的优先级,那么直接入栈S2;

          (4-3)如果此时栈S2不为空,当前遍历的运算符的优先级小于(增加等于)栈顶运算符的优先级,则将栈顶运算符一直出栈加入到栈S1中,直到栈为空或者遇到一个运算符的优先级小于等于当前遍历的运算符的优先级,此时将该运算符加入到栈S2中;

(5)直到遍历完整个中序表达式之后,栈S2中仍然存在运算符,那么将这些运算符依次出栈加入到栈S1中,直到栈为空。

       按照上面的五条操作反复进行完成,那么栈S1中存放的就是逆波兰表达式。

然后是逆波兰表达式的计算方法.

转自http://www.nowamagic.net/librarys/veda/detail/2306

为了解释后缀表达式的好处,我们先来看看,计算机如何应用后缀表达式计算出最终的结果20的。

后缀表达式:9 3 1-3*+ 10 2/+

  • 规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

下面是详细的步骤:

1. 初始化一个空。此桟用来对要运算的数字进出使用。

2. 后缀表达式中前三个都是数字,所以9、3、1进栈。

3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。

4. 接着是数字3进栈。

5. 后面是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。

6. 下面是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。

7. 接着是10与2两数字进栈。

8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。

9. 最后一个是符号“+”,所以15与5出找并相加,得到20,将20进栈。

10. 结果是20出栈,栈变为空。

程序

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stack>
#include<cctype>
#include<iostream>
using namespace std;
struct node{
	int count;
	char opr;
}; 
stack<int>s2;
node s1[100];//操作符 
char a[100];

int len,top=0,oprnum=0;
int first[130];//存储++*/的优先级
int com(int x,int y,char opr ){
	int tmp;
	switch(opr){
		case '^':{tmp=(int)pow(x,y);break;}
		case '*':{tmp=x*y;break;}
		case '/':{tmp=x/y;break;}
		case '+':{tmp=x+y;break;}
		case '-':{tmp=x-y;break;}
	}
	return tmp;
}

int  comput(){
	stack<int>s3;
	for(int i=1;i<=top;i++){
		if(s1[i].opr==0)s3.push(s1[i].count);
		else{
			int x,y;
			char opr=s1[i].opr;
			x=s3.top();
			s3.pop();
			if(s3.empty())	s3.push(com(0,x,opr));
			else{
				y=s3.top();
				s3.pop();
				s3.push(com(y,x,opr));
		
			}	
		}
		
	}
	return s3.top();	
}

int main()
{ 
        
         first['+']=first['-']=2;
         first['*']=first['/']=3;
         first['^']=4;
		 first['(']=1;//
		 first[')']=1;//其实这两个优先级没使用,括号单独处理的.
   scanf("%s",a);
   
   len=strlen(a);
   a[len]='.';
   int tmp=0;
   bool f=false;
    for(int i=0;i<len;i++){ 
	      	
       if(a[i]>=48&&a[i]<=57){ //计算数字 
          
		  f=true;
          tmp=tmp*10+a[i]-'0';  
		  if(i==len-1) s1[++top].count=tmp;		
		  continue;
		}
        else{  
		    
			if(f)s1[++top].count=tmp;;	//遇到符号,前一个数字入栈 							
			f=false;
		    tmp=0;
		    if(s2.empty())s2.push(a[i]);//空栈,符号直接入栈 
		    else {
		    	if(a[i]=='('){s2.push(a[i]);continue;	}//左括号直接入栈 
		    	if(first[a[i]]>first[s2.top()])//高优先级直接入栈 
					s2.push(a[i]);
				else{
					if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/'||a[i]=='^'){//<=的优先级先出栈计算,再入栈 
						while(!s2.empty()&&first[a[i]]<=first[s2.top()]&&s2.top()!='('){
							s1[++top].opr=s2.top();
							s2.pop();
							++oprnum;
						}	//=-*/^结束											
						s2.push(a[i]);
					}
					if(a[i]==')'){//右括号,出栈到遇到左括号 
						while(!s2.empty()&&s2.top()!='('){
							s1[++top].opr=s2.top();
							s2.pop();
							++oprnum;
						}		//)结束
						if(!s2.empty()&&s2.top()=='(')s2.pop();		
					}					
				}//两种出战结束 
			}                           
        }//符号处理结束 
                    
    }
   
   while(!s2.empty()){//输入完成后剩余两种栈处理   		
		char opr=s2.top();
		if(opr=='('||opr==')'){
			s2.pop();
			continue;
		}
		s1[++top].opr=s2.top();
		s2.pop(); 
		++oprnum; 	
   }

   printf("%d\n",comput());
  return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、问题描述 在控制台下实现一个对算术表达式求值的模拟程序。 二、基本要求 该演示程序具有如下基本功能: (1) 表达式输入,以字符序列的形式从终端输入一个语法正确的数值表达式(float型),且表达式中只含有+、-、*、/、( 、)6 种运算符,输入格式如下: <变量><运算符><变量>……<回车> 例如表达式: 100+(15/3)*2 输入格式为: 100+(15/3)*2<回车> 注意: 输入的表达式中间不含空格。 (2) 表达式结果的输出,输出形式为: <表达式> = <结果> 例如表达式: 100+(15/3)*2 输出形式为: 100+(15/3)*2 = 110 注意: 此处的输出结果为整个表达式的数值结果。 (3) 数据合法性检验 主要是针对原表达式中除数为 0 的情况。 三、界面效果 表达式求值模拟程序 功能菜单: ============== [1] 输入表达式并求值 [0] 退出 ============== 请输入你的选择 (0~1):1 请输入一个表达式 : 100+(15/3)*2 计算结果如下: 100+(15/3)*2 = 110 请输入你的选择 (0~1):0 四、测试数据 (1) 8 = (2) 1+2+3+4 = (3) 88-1*5 = (4) 1024/4*8 = (5) 1024/(4*8) = (6) (20+2)*(6/2) = (7) 3-3-3 = (8) 80/(9-9) = (9) (6+2*(3+6*(6+6)) = (10) (((6+6)*6+3)*2+6)*2 = 五、实现提示 (1) 设置运算符栈和操作数栈辅助分析算符优先关系; (2) 在读入字符序列时,完成运算符和操作数的处理,以及相应运算; (3) 在识别处运算数的同时,要将其字符序列形式转化成 float 型数据形式; (4) 输入的字符序列中,操作数不一定是一位数,可能是多位数,如 16+32 ; (5) 使用 Lab3-1 实现的栈的 ADT 基本操作完成本次作业 ; (6) 在程序中会用到两类栈:操作数栈和运算符栈,分别为 float 型数据和字符型数据, 思考在同一个程序中如何处理两类不同的数据类型? (7) 算符之间的优先关系参考课本 P53 页表 3.1 。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值