qt 判断逻辑表达式

业务场景

用户需要设定规则,我们根据用户输入的数值判断是否符合规则。
示例一:
用户认为满足如下条件的属于合格品:

(width<62.15|height>9.278)&(area>5.86|width>6)

(数字我随便敲的)

现在来了一批样品,得到了属性width等的数值。要判断样品是否合规

拆解

这个问题本质上是判断这样的一串逻辑表达式

(63.2<62.15|553.14>37.278)&(1035.68>536.86|63.2>43)

不带括号

我们先从简单的入手:
没有括号的情况
表达式就剩下 < > | &运算符
其中< >优先级更高一些
仿照[LeetCode] Basic Calculator I II III 总结
给出如下解法:

#include<deque>

QString getNumStr(QString judgeValue,int i)
{
	//浮点数
	QString pattern("\\d+(\\.\\d+)");
	QRegExp rx(pattern);
	int pos = rx.indexIn(judgeValue, i);
	if (pos > -1)
	{
		QString value = rx.cap(0);
		QString temp = rx.cap(1);
		return value;
	}
	//整数
	pattern = "-?\\d+";
	rx.setPattern(pattern);
	pos = rx.indexIn(judgeValue, i);
	if (pos > -1)
	{
		QString value = rx.cap(1);
		return value;
	}
	return "";
}
bool cal(QString judgeValue)
{
	judgeValue.remove(QRegExp("\\s"));
	int i = 0;
	double temp, curNum = 1;
	QChar preSign; //之前的符号
	std::deque<double> numberStack;
	std::deque<QChar> signStack;
	while (i < judgeValue.size() + 1)
	{
		QChar cur = judgeValue.at(i);
		if (cur.isDigit())
		{
			QString value = getNumStr(judgeValue, i);
			if (!value.isEmpty())
			{
				i = i + value.size() - 1;
				curNum = value.toDouble();
			}
			i++;
			continue;
		}
		else //遇到符号了,判断之前的符号
		{
			switch (preSign.unicode())
			{
			case '>':
			{
				temp = numberStack.back();
				temp = temp > curNum;
				numberStack.pop_back();
				numberStack.push_back(temp);
				break;
			}
			case '<':
			{
				temp = numberStack.back();
				temp = temp < curNum;
				numberStack.pop_back();
				numberStack.push_back(temp);
				break;
			}
			case '&':
			{
				numberStack.push_back(curNum);
				signStack.push_back('&');
				break;
			}
			case '|':
			{
				numberStack.push_back(curNum);
				signStack.push_back('|');
				break;
			}
			case ' ':
				break;
			default:
				numberStack.push_back(curNum);
			}
			preSign = cur;
		}

		i++;
	}

	//

	if (!numberStack.empty())
	{
		double result = numberStack.front();
		numberStack.pop_front();
		while (!numberStack.empty())
		{
			double cur = numberStack.front();
			numberStack.pop_front();
			QChar sign = signStack.front();
			signStack.pop_front();
			if (sign == "|")
			{
				result = cur || result;
			}
			else
			{
				result = cur && result;
			}
		}
		return result;
	}
	else
	{
		return false;
	}

}

int main(int argc, char *argv[])
{
	cal(" 90.3< 62.15 | 36.12>9.278 & 69.214>5.86");
	return 0;
}

技巧总结:

  1. 计算表达式 63.2<62.15: 需要存储 第一个数字63.2,运算符,第二个数字。遍历字符串时,指针走到62.15,其实不好判断是第几个数字。所以这里的处理办法是:指针走到下一个运算符,即 63.2<62.15| 中的 ‘|’,第一个数字存储在栈里,第二个存储在当前数字 curNum 中,前运算符保存在preSign中。这是才计算表达式63.2<62.15
  2. 与leetcode题不同的是,加减法可以被转换成正负号,我这里不行,所以需要先把所有的 <>算出,表达式里只剩下 数字和 | &之后,从队列numberStack,signStack取出数字和符号,从左到右计算逻辑运算符

带括号

两者的区别在于,需要先把括号里面的内容算出来,并返回一个结果
思路
在这里插入图片描述
所以:

bool cal(QString judgeValue)
{
	judgeValue.remove(QRegExp("\\s"));
	int i = 0;
	double temp, curNum = 1;
	QChar preSign; //之前的符号
	std::deque<double> numberStack;
	std::deque<QChar> signStack;
	while (i < judgeValue.size() + 1)
	{
		QChar cur = judgeValue.at(i);
		if (cur.isDigit())
		{
			QString value = getNumStr(judgeValue, i);
			if (!value.isEmpty())
			{
				i = i + value.size() - 1;
				curNum = value.toDouble();
			}
			i++;
			continue;
		}
		else if(cur == '(')
		{
			int j = i, count = 0;
			for (; i < judgeValue.size(); i++) {
				if (judgeValue[i] == '(') count++;
				if (judgeValue[i] == ')') count--;
				if (count == 0) break;
			}
			curNum = cal(judgeValue.mid(j + 1, i - j - 1));
		}
		else //遇到逻辑符号了,判断之前的符号
		{
			switch (preSign.unicode())
			{
				case '>':
				{
					temp = numberStack.back();
					temp = temp > curNum;
					numberStack.pop_back();
					numberStack.push_back(temp);
					break;
				}
				case '<':
				{
					temp = numberStack.back();
					temp = temp < curNum;
					numberStack.pop_back();
					numberStack.push_back(temp);
					break;
				}
				case '&':
				{
					numberStack.push_back(curNum);
					signStack.push_back('&');
					break;
				}
				case '|':
				{
					numberStack.push_back(curNum);
					signStack.push_back('|');
					break;
				}
				case ' ':
					break;
				default:
					numberStack.push_back(curNum);
			}
			preSign = cur;
		}

		i++;
	}

	//

	if (!numberStack.empty())
	{
		double result = numberStack.front();
		numberStack.pop_front();
		while (!numberStack.empty())
		{
			double cur = numberStack.front();
			numberStack.pop_front();
			QChar sign = signStack.front();
			signStack.pop_front();
			if (sign == "|")
			{
				result = cur || result;
			}
			else
			{
				result = cur && result;
			}
		}
		return result;
	}
	else
	{
		return false;
	}

}

解法

总的解法就是:

  1. 客户输入(width > 100 & height > 300) | (area < 600)
  2. 获取属性值 {“width” : 321, “height” : 560 , “area”: 235}
  3. 利用字符串替换得到要计算的表达式: (321> 100 & 560 > 300) | (235< 600)
  4. 计算bool cal(QString judgeValue); 返回结果

搞定

### 回答1: 在Qt判断条件非符号是 `!`。它表示逻辑非,可以用于取反一个表达式的值。例如: ```cpp bool a = true; if (!a) { qDebug() << "a is false"; } ``` 在这个例子,`!a`的值为`false`,因为逻辑非操作取反了`a`的值。因此,程序会输出`a is false`。 ### 回答2: 在Qt判断条件非符号是 "!",也被称为逻辑非运算符。它用于取反一个表达式的值。如果一个表达式为真(true),则取非之后会变为假(false),反之亦然。逻辑非运算符通常用于条件语句和循环控制语句,以帮助我们进行条件判断和控制程序的流程。 例如,我们可以使用逻辑非符号来判断一个变量是否为空。比如有一个QString类型的变量str,我们可以使用"!"来判断它是否为空字符串,即: if (!str.isEmpty()) { // str不为空的处理逻辑 } else { // str为空的处理逻辑 } 在上面的代码,"!"用于判断str是否为空字符串。如果str不为空,则进入if语句块执行其内部的处理逻辑;如果str为空,则进入else语句块执行其内部的处理逻辑。 除了用于判断条件,逻辑非运算符还可以用于取反变量的布尔值。比如一个bool类型的变量isTrue为true,我们可以使用"!"来将其取反,即isTrue的值变为false。 总之,在Qt判断条件非符号"!"是用于取反一个条件表达式的值的运算符,用于帮助我们进行条件判断和控制程序的流程。 ### 回答3: Qt判断条件非符号是"!",它表示逻辑非操作符。在编程逻辑非是一种常用的运算符,通常用于取反操作。当使用"!"运算符对一个条件进行取反时,如果该条件为真,则结果为假;反之,如果该条件为假,则结果为真。在Qt,我们可以使用"!"运算符对条件进行取反,以进行逻辑判断。例如,如果我们有一个条件变量flag,当flag为真时执行某些操作,我们可以使用"!flag"来判断当flag为假时执行相应的代码。逻辑非操作符可以应用于各种数据类型,包括布尔型、整型、浮点型等。值得注意的是,在Qt使用逻辑非操作符时,应保证其作用对象的类型是适合的,否则可能会导致不可预测的结果。此外,在逻辑非运算过程,如果操作数本身不是布尔型,则会先进行类型转换,将其转换为布尔型再进行取反操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值