布尔表达式递归解法

                                          布尔表达式递归解法

先简单描述一下题目吧(简要摘抄!)

描述
您将要生成的程序的目标是评估布尔表达式,如下所示:

表达式:(V | V)&F&(F | V)其中V代表True,F代表False。表达式可以包括以下运算符:!不是,&是,| 对于或,也允许在操作分组中使用括号。

输入
表达式的长度是可变的,可以用任意数量的空格分隔;
输入文件中的表达式数量是可变的,每个表达式都以新行显示;

输出
对于每个测试表达式,打印“Expression”,然后打印其序列号“:”以及相应测试表达式的结果值。用换行分隔连续测试表达式的输出。

样例输入
( V | V ) & F & ( F| V)
!V | V & V & !F & (F | V ) & (!F | F | !V & V)
(F&F|V|!V&!F&!(F|F&V))

样例输出
Expression 1: F
Expression 2: V
Expression 3: V

一、思路分析

递归解法,采用和郭炜老师(他的MOOC)四则运算表达式同样的思路。

先给出我采用的布尔表达式递归逻辑

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
定义的递归思路不同,后面的解法也会稍有区别。有兴趣的可以看看其他的递归定义。

表达式的定义

这里定义表达式是由一系列 通过 | 运算组成的。

我在搜索资料时,也看到有人是将 &| 运算都放在表达式级别,而表达式直接由因子构成。

bool expression_value()
{
	bool result = term_value();
	while (1) 
	{
		char op=cin.peek();
		if (op == ' ') cin.get();//处理空格
		else 
		{
			if (op == '|')
			{
				cin.get();
				bool value = term_value();
				result |= value;

			}
			else break;
		}		
	}
	return result;
}

项的定义

这里定义项是由一系列 因子 通过 & 运算组成的。
如果将 & 定义到了表达式里,则没有 项 这一块。

bool term_value()
{
	bool result = factor_value();
	while (1)
	{
		char op = cin.peek();
		if (op == ' ') cin.get();
		else
		{
			if (op == '&')
			{
				cin.get();
				bool value = factor_value();
				result &= value;
			}
			else break;
		}
	}
	return result;
}

因子的定义

这里定义的因子分三种情况。

(1)逻辑值V或F。这是递归的出口,
(2)括号括起来的表达式。递归调用表达式
(3)取反的因子。递归调用因子自身

有的代码里单独定义了取反运算,我认为这是完全没有必要的。被取反的值一定在我们定义的三种因子类型里,换句话说,被取反的一定是一个因子,我们只需要调用因子自身即可。此外,我们也没必要考虑连续取反的情况了,它是涵盖在了因子的定义里的。

bool factor_value()
{
	bool result = 0;
	char factor = cin.peek();

	while (factor == ' ')
	{
		cin.get();
		factor = cin.peek();
	}
	switch (factor)
	{
		case '(':   // (表达式)
			cin.get();
			result = expression_value();
			cin.get();
			break;
		case '!':  //   !因子
			cin.get();
			result = !factor_value();
			break;
		case 'V':  //   V
			cin.get();
			result = true;
			break;
		case 'F':  //   F
			cin.get();
			result = false;
			break;
		default:
			break;
	}
	return result;
}


二、源代码

几乎码了一天,心累

// boolean expression.cpp 
//

#include <iostream>
#include <string.h>
using namespace std;


bool expression_value();//表达式
bool term_value();      //项
bool factor_value();    //因子

int main()
{
	int i = 1; 
	while (cin.peek()!=EOF)//文件结束符
	{
		while (cin.peek() == '\n' || cin.peek() == ' ') //处理无意义的回车或空格
			cin.get();

		cout<<"Expression "<<i++<<": "<< (expression_value() == true ? "V" : "F") << endl;
	}
	return 0;
}

bool expression_value()
{
	bool result = term_value();
	while (1) 
	{
		char op=cin.peek();
		if (op == ' ') cin.get();//处理空格
		else 
		{
			if (op == '|')
			{
				cin.get();
				bool value = term_value();
				result |= value;

			}
			else break;
		}		
	}
	return result;
}

bool term_value()
{
	bool result = factor_value();
	while (1)
	{
		char op = cin.peek();
		if (op == ' ') cin.get();
		else
		{
			if (op == '&')
			{
				cin.get();
				bool value = factor_value();
				result &= value;
			}
			else break;
		}
	}
	return result;
}

bool factor_value()
{
	bool result = 0;
	char factor = cin.peek();

	while (factor == ' ')
	{
		cin.get();
		factor = cin.peek();
	}
	switch (factor)
	{
		case '(':   // (表达式)
			cin.get();
			result = expression_value();
			cin.get();
			break;
		case '!':  //   !因子
			cin.get();
			result = !factor_value();
			break;
		case 'V':  //   V
			cin.get();
			result = true;
			break;
		case 'F':  //   F
			cin.get();
			result = false;
			break;
		default:
			break;
	}
	return result;
}


三、那一天我踩过的坑

只想说,真是太坑了。可在回过头来想,也没发现困难的地方,莫名的坑。

(1)空格要处理

这个其实不算坑,因为题目里说到了,注意一下就没问题了。在表达式、项和因子的处理过程中,都要处理好空格。

(2)文件结束符EOF的应用

大概是我没有读懂题目,之前在主程序里傻傻的用 while(1) 循环。

while (cin.peek()!=EOF)//文件结束符
	{
		while (cin.peek() == '\n' || cin.peek() == ' ') //处理无意义的回车或空格
			cin.get();

		cout<<"Expression "<<i++<<": "<< (expression_value() == true ? "V" : "F") << endl;
	}

顺便说一下我在内层里写的while循环,个人还是比较满意的。一方面是处理掉每行表达式末尾的 ‘\n’;另一方面,能避免单独的按回车键(或者空格+回车)就开始计算的情况,也就是说空白行会跳过。虽然网页上没有这个case,但这样处理一下个人觉得舒服。

(3)天坑

我的浏览器自动把题目翻译成中文了,我输出了long long time的:

表达式 1 :……
表达式 2 :……
…………
提交一直报错,几近奔溃,被自己蠢哭。
以后得小心,别被自己神坑。

我想获得一个同情的赞!!!!!!!!

发布了13 篇原创文章 · 获赞 7 · 访问量 596

猜你喜欢

转载自blog.csdn.net/hejnhong/article/details/104538437