/*问题描述:
一个逻辑表达式如果对于其变元的任一种取值都为真,则称为重言式;反之,如果对于其变元的任一种取值都为假,则称为矛盾式;然而,更多情况下,既非重言式,也非矛盾式。
逻辑表达式从终端输入,长度不超过一行。逻辑运算符包括“|”,“&”,“~”,分别表示或、与和非,运算优先程度递增,但可以由括号改变,即括号内的运算优先。逻辑变元为大写字母。表达式中任何地方都可以包含多个空格符。
若是重言式或矛盾式,则显示“True forever”或“False forever”,否则显示“Statisfactible”以及变量名序列,供用户输入各变量名的值,程序然后显示表达式的值?*/
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define stack_size_normal 100
#define bianliang_max 20
#define str_max 60
int zuhe[bianliang_max];/* 变量的取值组合数组定义; */
int N;/* 变量个数; */
/* 根据表达式建立的二叉树的结点定义; */
typedef struct btdnode{
char data;
struct btdnode *lchild;
struct btdnode *rchild;
}*bitree;
/* 识别表达式使用的堆栈定义,它存放的都是树的结构; */
typedef struct lnode_optr{
struct btdnode **base; /* 栈中的元素都是树的结点结构; */
struct btdnode **top;
int stacksize;
}sqstack;
/* 用于产生变量的各种取值组合; */
void creatzuhe(int n)
{
int i,num=0,j=0,e;
int temp[bianliang_max];
for(i=0;i<N;i++)
zuhe[i]=0;
while(n)
{
e=n%2;
num++;
temp[j++]=e;
n=n/2;
}
j=j-1;
num=N-num;
while(j>=0)
{
e=temp[j--];
zuhe[num++]=e;
}
}
/* 自底向上地根据运算符地优先级来建立分子树函数;当逻辑表达式读完后-子根zigen就是一棵完整的二叉树 */
int k=0;/* 建树的标志,k=1表示第一次建立分子树,要对左右孩子的指针域处理 */
void create(bitree zigen,bitree l,bitree r)
{
zigen->lchild=l;
zigen->rchild=r;/* 分树的链接 */
if(l&&r)
{
if((int)(l->data)>=65&&(int)(l->data)<=90)
{
l->lchild=NULL;
l->rchild=NULL;
}
if((int)(r->data)>=65&&(int)(r->data)<=90)
{
r->lchild=NULL;
r->rchild=NULL;
}
}
}
/* 逻辑运算符的优先级判别; */
char youxianji(char lie,char hang)
{
int i,j;
char bijiao[7][7]={' ','|','&','~','(',')','#','|','>','<','<','<','>','>','&','>','>','<','<','>','>','~','>','>','>','<','>','>','(','<','<','<','<','=',' ',')','>','>','>',' ','>','>','#','<','<','<','<',' ','='};
for(i=0;i<7;i++)
if(bijiao[0][i]==lie)
break;
for(j=0;j<7;j++)
if(bijiao[j][0]==hang)
break;
return bijiao[j][i];
}
/* 对操作符栈和变量堆栈的操作; */
void creatstack(sqstack st)
{
st.base=(bitree*)malloc(stack_size_normal*sizeof(struct btdnode));
if(!st.base) exit(0);
st.top=st.base;
st.stacksize=stack_size_normal;
}
void push(sqstack st,bitree e)
{
if(st.top-st.base<st.stacksize)
*(st.top++)=e;
else exit(0);
}
void pop(sqstack st,bitree e)
{
if(st.top==st.base) ;
{ e=*(--st.top);
exit(0);}
}
void gettop(sqstack st,bitree e)
{
if(st.top==st.base);
{e=*(st.top-1);
exit(0) ; }
}
/* 重言式的识别函数; */
void creattree(char s[],bitree tree)
{
sqstack variable; /* 变量栈; */
sqstack logic; /* 逻辑运算符栈; */
bitree logic_di,variables,logics,e,a,b,theta,kuohao;/* 定义栈中的元素; */
creatstack(variable);
creatstack(logic);
logic_di=(bitree)malloc(sizeof(struct btdnode));
if(!logic_di) exit(0);
logic_di->data='#';
push(logic,logic_di);
while(*s!=NULL)
{
if((int)(*s)>=65&&(int)(*s)<=90)
{
variables=(bitree)malloc(sizeof(struct btdnode));
if(!variables) exit(0);
variables->data=*s;
push(variable,variables);
}
else if((int)(*s)>90||(int)(*s)<65)
{
gettop(logic,e);/* 取运算符栈的栈顶元素进行优先级比较 */
switch(youxianji(*s,e->data))
{
case '<': /* 栈顶的运算符优先级低,逻辑运算符进栈 */
logics=(bitree)malloc(sizeof(struct btdnode));
if(!logics) exit(0);
logics->data=*s;
push(logic,logics);
break;
case '=':/* 脱括号并接受下一个字符; */
pop(logic,kuohao);break;
case '>':pop(logic,theta);/* 弹出逻辑运算符 */
pop(variable,a);/* 弹出变量 */
b=NULL;
if(theta->data!='~')
pop(variable,b);
/* 建树的函数调用 */
k=k+1;
create(theta,b,a);
push(variable,theta);/* 将临时的根作为新的变量压入变量栈中; */
if(*s!='#'&&*s!=')')
{
logics=(bitree)malloc(sizeof(struct btdnode));
if(!logics) exit(0);
logics->data=*s;
push(logic,logics);
}
else s=s-1;
break;
}
}
s++;
}
tree=theta;
}
/* 根据变量的取值组合并利用逻辑表达式的性质对树进行求值 */
int value_tree(bitree tree)
{
if(!tree) return 0; /* 遇到空的结点; */
else if(tree->data!='|'&&tree->data!='&'&&tree->data!='~')/* 找到的是变量; */
return zuhe[(int)(tree->data-65)];
else if((int)(tree->data)<65||(int)(tree->data)>90) /* 找到的是运算符; */
switch(tree->data)
{
case '|': return(value_tree(tree->lchild)||value_tree(tree->rchild));
case '&': return(value_tree(tree->lchild)&&value_tree(tree->rchild));
case '~': return(!value_tree(tree->rchild));
}
}
/* 用户设定变量的一种取值; */
void user()
{
int i;
printf("请依次输入你的变元取值");
for(i = 65;i < 65 + N;i ++)
{
printf("%c=",i);
scanf("%c",&zuhe[i-65]);
}
}
main()
{
int SUM=0,l;/* 用于累加变量的每种组合的逻辑表达式的结果;可以作为逻辑表达式类别判别的根据 */
int h,sum=(int)(pow(2,N)),N;
char str[str_max],string[str_max],*pstr;
int loop=20,choice,i=0,choose;
bitree Tree;
while(loop)
{
pstr=str;
i=0;
printf("请输入逻辑表达式的变量个数\n");
scanf("%d",&N);
/* 变量组合的总数; */
printf("请输入逻辑表达式的表达式 (或用'|',与用'&'和非用'~')\n");
scanf("%c",&str);
/* 重言式的正确读取; */
for(;*pstr!=NULL;pstr++)
if(*pstr!=' ')
string[i++]=*pstr;
string[i]='#';
string[i+1]='\0';
printf("************ 请选择你要的操作 **********\n") ;
printf("************ 1 逻辑表达式的判别(不显示各种取值组合的结果) **********\n") ;
printf("************ 2 逻辑表达式的判别(并显示各种取值组合的结果) **********\n") ;
printf("************ 3 逻辑表达式的求值(根据拥护的取值) **********\n") ;
printf("请选择你要的操作: \n");
scanf("%d",&choose);
switch(choose)
{
case 1:/* 对变量的不同组合依次调用重言式二叉树的求值函数;并判别重言式的类别; */
creattree(string,Tree);/* 建立重言式的二叉树; */
for(loop=0;loop<sum;loop++)
{
creatzuhe(loop);/* 产生变量取值组合; */
SUM+=value_tree(Tree);
}
string[i]='\0';
if(SUM==0)
printf("逻辑表达式:%s 是矛盾式\n",string);
if(SUM==sum)
printf("逻辑表达式:%s 是重言式\n",string);
if (SUM>0&&SUM<sum)
printf("逻辑表达式:%s 即不是重言式也,不是矛盾式\n",string);
break;
case 2:creattree(string,Tree);/* 建立重言式的二叉树; */
printf("逻辑表达式变量的预算结果\n");
printf("---------------------------------------------\n");
printf("| \n");
for(l=65;l<65+N;l++)
printf("%-4c",l);
printf("逻辑表达式的值");
printf(" |\n");
printf("---------------------------------------------\n");
for(loop=0;loop<sum;loop++)
{
creatzuhe(loop);/* 产生变量取值组合; */
SUM+=value_tree(Tree);
printf("| ");
for( h=0;h<N;h++)
printf("%-4d",zuhe[h]);
printf("%8d",value_tree(Tree));
printf(" |\n");
printf("-------------------------------------------\n");
}
string[i]='\0';
if(SUM == 0)
printf("逻辑表达式:%s 是矛盾式.\n",string);
else if(SUM == sum)
printf("逻辑表达式:%s 是重言式.\n",string);
else
printf("逻辑表达式: %s","不是重言式也不是矛盾式\n",string);
break;
case 3:
creattree(string,Tree);
user();
printf("逻辑表达式的值为%d",value_tree(Tree));
break;
}
printf("是否继续进行运算?是按1/否按0:");
scanf("%d",&choice);
if(choice==0)
exit(0);
loop--;
}
}