1.由于工作需求要实现一个函数,接收一个布尔表达式计算出其结果。例如:
string exp = "(true | false )& false"
因为c++ 与java 均是静态语言,不支持这种动态的表达式, 有些方案是把 表达式写入到一个文件里面,然后编译成可执行文件,吊起然后再返回结果, 这种效率低。想了想 其实自己也可以实现一个代码解析器然后计算出结果不久ok了吗? 于是乎自己写了一个能计算 | & ! 表达式的方法, 并且支持() , 允许里面有多个空格。话不多说直接上代码了, 有什么问题欢迎留言
java 代码:
private static int logicExp(String exp, int idx, boolean onlyFirstValue) {
boolean left = true, right = false;
int op = 0; // 0:none; 1:or; 2:and
loop:
while (idx < exp.length()) {
switch (exp.charAt(idx++)) {
case '(':
idx = logicExp(exp, idx, false);
if (op == 0)
left = idx < 0;
else
right = idx < 0;
idx &= 0x7fff_ffff;
break;
case ')':
break loop;
case '!':
idx = logicExp(exp, idx, true);
if (op == 0)
left = idx >= 0;
else
right = idx >= 0;
idx &= 0x7fff_ffff;
break;
case '|':
switch (op) {
case 0:
op = 1;
break;
case 1:
left |= right;
break;
case 2:
left &= right;
op = 1;
break;
}
break;
case '&':
switch (op) {
case 0:
op = 2;
break;
case 1:
idx = logicExp(exp, idx, true);
right &= idx < 0;
idx &= 0x7fff_ffff;
break;
case 2:
left &= right;
break;
}
break;
case 't':
if (op == 0)
left = true;
else
right = true;
break;
case 'f':
if (op == 0)
left = false;
else
right = false;
break;
}
if (onlyFirstValue)
break;
}
if (op == 1)
left |= right;
else if (op == 2)
left &= right;
return left ? idx | 0x8000_0000 : idx;
}
/**
* 求表达式的值
* @param exp
* @return
*/
public static boolean logicExp(String exp) {
String strExp = exp.replace(" ", "");
strExp = exp.replace(" ", "");
strExp = exp.replace("true", "t");
strExp = exp.replace("false", "f");
return logicExp(strExp, 0, false) < 0;
}
c++代码:
#include <iostream>
#include <string>
using namespace std;
int findEnd(string exp, int beg, int end) {
int index = beg + 1;
if (exp[beg] == '(' || ('!' == exp[beg] && '(' == exp[beg+1])) {
int i = 1;
index = '!' == exp[beg] ? beg + 2 : beg + 1;
while (i > 0) {
if (exp[index] == '(')
i++;
else if (exp[index] == ')')
i--;
index++;
}
}
else if (exp[beg] == '!') {
index = beg + 2;
}
else {
index = beg + 1;
}
return index < end ? index : 0;
}
/**
* 把表达式 布尔运算
*
* @param expression 要计算的表达式 例如: ((f|f)&!f)|t t (t|f)&!f
* @param beg 开始索引
* @param end 结束索引
* @return 计算结果 ture or false
*/
bool boolExpr(string expression, int beg, int end) {
if (1 == end - beg && ('f' == expression[beg])) return false;
if (1 == end - beg && ('t' == expression[beg])) return true;
int endi = findEnd(expression, beg, end);
if (expression[beg] == '!') {
if (0 == endi)
return !boolExpr(expression, beg + 1, end);
}
else if (expression[beg] == '(') {
if (0 == endi)
return boolExpr(expression, beg + 1, end - 1);
else if ('|' == expression[endi])
return boolExpr(expression, beg + 1, endi - 1) || boolExpr(expression, endi + 1, end);
else if ('&' == expression[endi])
return boolExpr(expression, beg + 1, endi - 1) && boolExpr(expression, endi + 1, end);
}
if ('|' == expression[endi])
return boolExpr(expression, beg, endi) || boolExpr(expression, endi + 1, end);
else if ('&' == expression[endi])
return boolExpr(expression, beg, endi) && boolExpr(expression, endi + 1, end);
return true;
}
int main()
{
string str = "(true|false)& false";
auto iter_t = str.find("true");
while (str.npos != iter_t)
{
str = str.replace(iter_t, 4, "t");
iter_t = str.find("true");
}
auto iter_f = str.find("false");
while (str.npos != iter_f)
{
str = str.replace(iter_f, 5, "f");
iter_f = str.find("false");
}
auto iter_s = str.find(" ");
while (str.npos != iter_s)
{
str = str.replace(iter_s, 1, "");
iter_s = str.find("false");
}
cout <<str.c_str()<< endl;
bool ret = boolExpr(str, 0, str.length());
return 0;
}