c表达评估员

好吧,我想在文本文件中有一个这样的字符串:

((( var1 AND var2 AND var3) OR var4) AND ((var5 OR var6) AND var7)) 

在将其解析为c程序并处理并正确设置变量后,它最终会看起来像这样:

 ((( 1 AND 0 AND 0) OR 1) AND ((0 OR 1) AND 1)) 

是否有任何有用的库用于评估表示为这样的一个字符串的表达式? 我以为我可以用字符串作为参数调用一个perl程序,它可以很容易地返回结果,但不确定C中是否有一个库可以做到这一点,或者是否有任何已知的算法可以解决这样的表达?

编辑:我实际上正在寻找的东西会吐出这个表达的答案,也许解析是一个坏词。 即1或0

在一个坚果壳中,它包含一堆随机表达式(已知为正确格式)的文件需要被评估为0或1.(上面评估为1,因为它导致(1和1)。

我试着为这个bool表达式评估问题编写最紧凑的C代码。 这是我的最终代码:

编辑:删除

这是增加的否定处理:

编辑:添加测试代码

 char *eval( char *expr, int *res ){ enum { LEFT, OP1, MID, OP2, RIGHT } state = LEFT; enum { AND, OR } op; int mid=0, tmp=0, NEG=0; for( ; ; expr++, state++, NEG=0 ){ for( ;; expr++ ) if( *expr == '!' ) NEG = !NEG; else if( *expr != ' ' ) break; if( *expr == '0' ){ tmp = NEG; } else if( *expr == '1' ){ tmp = !NEG; } else if( *expr == 'A' ){ op = AND; expr+=2; } else if( *expr == '&' ){ op = AND; expr+=1; } else if( *expr == 'O' ){ op = OR; expr+=1; } else if( *expr == '|' ){ op = OR; expr+=1; } else if( *expr == '(' ){ expr = eval( expr+1, &tmp ); if(NEG) tmp=!tmp; } else if( *expr == '\0' || *expr == ')' ){ if(state == OP2) *res |= mid; return expr; } if( state == LEFT ){ *res = tmp; } else if( state == MID && op == OR ){ mid = tmp; } else if( state == MID && op == AND ){ *res &= tmp; state = LEFT; } else if( state == OP2 && op == OR ){ *res |= mid; state = OP1; } else if( state == RIGHT ){ mid &= tmp; state = MID; } } } 

测试:

 #include  void test( char *expr, int exprval ){ int result; eval( expr, &result ); printf("expr: '%s' result: %i %s\n",expr,result,result==exprval?"OK":"FAILED"); } #define TEST(x) test( #x, x ) #define AND && #define OR || int main(void){ TEST( ((( 1 AND 0 AND 0) OR 1) AND ((0 OR 1) AND 1)) ); TEST( !(0 OR (1 AND 0)) OR !1 AND 0 ); } 

您可以在程序中嵌入lua ,然后调用它的解释器来评估表达式。

对于像这样的简单表达式来说,滚动自己的递归下降解析器很容易。

我有类似的程序实现recursive-decent解析器,所以我刷它,在这里。

  #include  #include  

#include #include

int doOR(int pOprd1,int pOprd2){
if(pOprd1 == -1)返回pOprd2;
返回pOprd1 || pOprd2;
}
int doAND(int pOprd1,int pOprd2){
if(pOprd1 == -1)返回pOprd2;
return pOprd1 && pOprd2;
}
int doProcess(char pOpert,int pOprd1,int pOprd2){
if(pOpert ==’0’)返回pOprd2;
if(pOpert ==’O’)返回doOR(pOprd1,pOprd2);
if(pOpert ==’A’)返回doAND(pOprd1,pOprd2);
puts(“Unknown Operator !!!”);
出口(-1);
}
int * doParse(char pStr,int pStart){
char C;
int i = pStart;
int值= -1;
char运算符=’0′;
for(;(C = pStr [i])!= 0; i ++){
if(C ==’0’){Value = doProcess(Operator,Value,0); 继续; }
if(C ==’1’){Value = doProcess(Operator,Value,1); 继续; }
if(C ==”)继续;
if(C ==’)’){
int aReturn;
aReturn = malloc(2 * sizeof aReturn);
aReturn [0] =价值;
aReturn [1] = i + 1;
返回aReturn;
}
if(C ==’(’){
int * aResult = doParse(pStr,i + 1);
Value = doProcess(Operator,Value,aResult [0]);
i = aResult [1];
if(pStr [i] == 0)中断;
继续;
}
if((C ==’A’)&&((pStr [i + 1] ==’N’)&&(pStr [i + 2] ==’D’))){
if((Operator ==’0’)||(Operator ==’A’)){
运算符=’A’;
i + = 2;
继续;
} else {
puts(“不允许混合运算符(AND)!!!”);
出口(-1);
}
}
if((C ==’O’)&&(pStr [i + 1] ==’R’)){
if((Operator ==’0’)||(Operator ==’O’)){
运算符=’O’;
i + = 1;
继续;
} else {
puts(“不允许混合运算符(OR)!!!”);
出口(-1);
}
}
printf(“未知字符:’%c(\”%s \“[%d])’!!!”,C,pStr,i);
出口(-1);
}
int * aReturn;
aReturn = malloc(2 * sizeof aReturn);
aReturn [0] =价值;
aReturn [1] = i;
返回aReturn;
}

这是一个测试代码:

 int main(void) { char* aExpr = "1"; int* aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "0"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "1 AND 0"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "1 AND 1"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "0 OR 0 OR 0"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "1 OR 0 OR 0"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "1 OR 1 OR 0"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "(1 OR 0)"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "(0 OR 0)"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); aExpr = "((( 1 AND 0 AND 0) OR 1) AND ((0 OR 1) AND 1))"; aResult = doParse(aExpr, 0); printf("%s = %d\n", aExpr, ((int*)aResult)[0]); free(aResult); puts("DONE!!!"); return EXIT_SUCCESS; } 

这很有趣:-D。

我相信Lex和Yacc仍然是这类简单解析任务的最佳工具。

不久之前,我为嵌入式系统上的命令行处理器和脚本语言编写了一个完整的C表达式求值程序(即使用C语法编写的求值表达式)。 我用这种算法描述作为起点。 您可以直接使用附带的代码,但我不喜欢实现,并从算法描述中编写了自己的代码。 它需要一些工作来支持所有C运算符,函数调用和变量,但这是一个明确的解释,因此是一个很好的起点,特别是如果你不需要那种完整性。

基本原则是对于使用堆栈和“反向波兰表示法”的计算机,表达式评估更容易,因此算法将具有相关优先顺序和括号的in-fix符号表达式转换为RPN,然后通过弹出操作数来评估它,执行操作和推送结果,直到没有剩余操作并且堆栈上剩下一个值。

原则上编写表达式解析器很容易,但需要花费相当多的精力。

这是我用Java编写的一个基本的 – 向下递归 – 下降表达式解析器: http : //david.tribble.com/src/java/tribble/parse/sql/QueryParser.java http://david.tribble.com/src /java/tribble/parse/sql/ExprLexer.java http://david.tribble.com/src/java/tribble/parse/sql/ExprLexer.java http://david.tribble.com/docs/tribble/parse /sql/package-summary.html

这可能不是您正在寻找的,但它会让您了解您的需求。