ica——布尔表达式

该博客介绍了如何对布尔表达式进行求值,例如使用V(真)和F(假),结合与(&)、或(|)和非(!)运算符来判断表达式的真假。示例给出了表达式(V | V) & F & (F | V)的结果为F。
描述

输入一个布尔表达式,请你输出它的真假值。 
比如:( V | V ) & F & ( F | V ) 
V表示true,F表示false,&表示与,|表示或,!表示非。 
上式的结果是F

输入
输入包含多行,每行一个布尔表达式,表达式中可以有空格,总长度不超过1000
输出
对每行输入,如果表达式为真,输出"V",否则出来"F"
样例输入
( V | V ) & F & ( F| V)
!V | V & V & !F & (F | V ) & (!F | F | !V & V)
(F&F|V|!V&!F&!(F|F&V))
样例输出
F
V
V
分析:
原理很简单,将中缀表达式转化为前缀表达式在计算,只是代码实现比较麻烦。
中缀转前缀的步骤如下:
  
(1) 首先构造一个 运算符栈(也可放置括号),运算符(以括号分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。
(2)从右至左扫描 中缀表达式,从右边第一个字符开始判断:
如果当前 字符是数字,则分析到数字串的结尾并将数字串直接输出。
如果是运算符,则比较 优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将 运算符直接入栈;否则将栈顶运算符 出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),再将当前运算符入栈。
如果是括号,则根据括号的方向进行处理。如果是右括号,则直接入栈;否则,遇左括号前将所有的运算符全部出栈并输出,遇右括号后将左右的两括号一起删除。
(3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆缀输出字符串。 中缀表达式也就转换为前缀表达式了。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
char calculate(char x, char y,char oper ){ // 计算 x oper y 
	bool a=(x=='V'),b=(y=='V'),ans;
	if(oper=='|')ans=(a||b);
	else if(oper=='&')ans=(a&&b);
	return ans?'V':'F';
}
char reverse(char x){
	if(x=='V')return 'F';
	return 'V';
}
int main(){
	string in;
	int i,j,len;
	
	while(getline(cin,in)){
		stack< char > Oper,num; //oper保存运算符,num保存运算结果 
		queue< char > s;  	//	s就是前缀表达式 
		len=in.length();
		i=len;
		in=" "+in;
		while(i>0){  // 从右往左,中缀表达式转 前缀表达式 
			if(in[i]==' '){
				i--;continue;
			}
			else if(isalpha(in[i]))s.push(in[i--]);
			else if(in[i]=='!')  	//最高级的运算,直接进入表达式 
				s.push(in[i--]);
			else{
				if(in[i]=='&'||in[i]=='|'||in[i]==')')  //低级运算,进栈 
				Oper.push(in[i--]);
				else if(in[i]=='('){  //一个括号结束,弹出中间的所有运算符 
					while(Oper.top()!=')'){
						s.push(Oper.top());
						Oper.pop();
					}
					Oper.pop();i--;
				}
			}
		}
	while(!Oper.empty())  	//栈中剩下的运算符 
		s.push(Oper.top()),Oper.pop();
	while(!s.empty()){   	//计算前缀表达式 
		char ch=s.front();s.pop();
		if(isalpha(ch))num.push(ch);
		else Oper.push(ch);
		if(!num.empty()&&!Oper.empty()&&Oper.top()=='!'){  //单目运算符‘!’; 
			char x=num.top();
			num.pop();Oper.pop();
			num.push(reverse(x));
		}
		else if(num.size()>=2&&!Oper.empty()){  	//双目运算符 
			char oper=Oper.top(),x,y;
			Oper.pop();
			x=num.top();num.pop();
			y=num.top();num.pop();
			num.push(calculate(x,y,oper));
		}
	}
	cout<<num.top()<<endl;
}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值