简述
输入一个0和1组成的表达式去判断真假,无论如何输入的总是一个表达式,并且都存在一个“运算符”优先级的问题,自然而然地会想到之前用栈写的表达式求值。
此处放下链接:
对于复合命题,常用的命题联结词有(按照优先级顺序排列)有:
非、合取、析取、蕴含词、等值词
简单复习一下:
非:
1的非就是0 0的非就是1
合取:
1 and 1=1 1 and 0=0 0 and 0=0
析取:
1 or 1=1 1 or 0=1 0 or 0=0
蕴含:
a蕴含b时,只有 a真b假才为假,其它均为真
等值:
a等值b时,只有ab同真同假为真,其它为假
准备工作
大方向实际就是表达式求值的方法,只需要在几个方面进行修改即可
1.整数处理:
在表达式求值中,由于是一个字符一个字符地处理,所以,对于位数大于1的整数,需要利用一个函数去处理之后再入栈并进行后续运算,但是在这里比较简单,因为0表示假,1表示真,只有1位数
2.运算符处理:
对于运算符优先级,我们仿照表达式求值中的加减乘除,依次重新定义五大命题联结词,在此处,我们定义:^表示非,*表示合取,+表示析取,-表示蕴含,=表示等值。
根据它们优先级,去绘制一个优先级表格,并写入函数“precede(char a,char b)”中:
代码实现
//大写字母表示命题
//整型代替布尔型 0假1真
//表达式就后面有#号,前面不用
//命题联结词优先级:
//非 ^ 合取* 析取 + 蕴含- 等值 = 支持使用括号
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define OK 2
#define OVERFLOW 0
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int Status;
int my_and(int A,int B)//合取
{
return A&&B;
}
int my_or(int A,int B)//析取
{
return A||B;
}
int my_not(int A)//非
{
return !A;
}
int implied(int A,int B)//蕴含
{
return !A||B;
}
int exclusive_or(int A,int B)//异或
{
return (A&&!B)||(!A&&B);
}
int equivalent(int A,int B)//等值
{
return (A&&B)||(!A&&!B);
}
typedef struct NumStackNode{
int data;
struct NumStackNode* next;
}NumStackNode,*NumStackNodePtr;
typedef struct{
NumStackNodePtr top;
NumStackNodePtr bottom;
}NumStack,*NumStackPtr; //数字栈 存放0或1代替命题真值
typedef struct CharStackNode{
char data;
struct CharStackNode *next;
}CharStackNode,*CharStackNodePtr;
typedef struct{
CharStackNodePtr top;
CharStackNodePtr bottom;
}CharStack,*CharStackPtr; //字符栈 存放命题联结词
NumStackPtr NumInitStack(void);//初始化数字栈
CharStackPtr CharInitStack(void);//初始化字符栈
Status NumGetTop(NumStackPtr S,int* e);//取数字栈栈顶
Status CharGetTop(CharStackPtr S,char* e);//取字符栈栈顶
Status NumPush(NumStackPtr S,int e);//数字栈入栈
Status CharPush(CharStackPtr S,char e);//字符栈入栈
Status NumPop(NumStackPtr S,int *e);//数字栈出栈
Status CharPop(CharStackPtr S,char *e);//字符栈出栈
Status isOPTR(char c);//判断是不是联结词
char Precede(char c1,char c2);//比较优先级
int Operate(int a,char sign,int b);//运算
bool EvaluateExpression();//表达式求值
int main()
{
bool flag;
printf("输入表达式:");
flag=EvaluateExpression();
if(flag)
printf("真");
else
printf("假");
return 0;
}
NumStackPtr NumInitStack(void)
{
NumStackPtr S=(NumStackPtr)malloc(sizeof(NumStack));
S->bottom=S->top=(NumStackNodePtr)malloc(sizeof(NumStackNode));
if(S->bottom==NULL)exit(OVERFLOW);
else return S;
}
CharStackPtr CharInitStack(void)
{
CharStackPtr S=(CharStackPtr)malloc(sizeof(CharStack));
S->bottom=S->top=(CharStackNodePtr)malloc(sizeof(CharStackNode));
if(S->bottom==NULL)exit(OVERFLOW);
else return S;
}
Status NumGetTop(NumStackPtr S,int *e)
{
if(S->bottom==S->top) return ERROR;
*e=S->top->data;
return OK;
}
Status CharGetTop(CharStackPtr S,char *e)
{
if(S->bottom==S->top) return ERROR;
*e=S->top->data;
return OK;
}
Status NumPush(NumStackPtr S,int e)
{
NumStackNodePtr pNew=(NumStackNodePtr)malloc(sizeof(NumStackNode));
pNew->data=e;
pNew->next=S->top;
S->top=pNew;
return OK;
}
Status CharPush(CharStackPtr S,char e)
{
CharStackNodePtr pNew=(CharStackNodePtr)malloc(sizeof(CharStackNode));
pNew->data=e;
pNew->next=S->top;
S->top=pNew;
return OK;
}
Status NumPop(NumStackPtr S,int *e)
{
if(S->bottom==S->top) return ERROR;
*e=S->top->data;
NumStackNodePtr p=S->top;
S->top=S->top->next;
free(p);
p=NULL;//避免野指针
}
Status CharPop(CharStackPtr S,char *e)
{
if(S->bottom==S->top) return ERROR;
*e=S->top->data;
CharStackNodePtr p=S->top;
S->top=S->top->next;
free(p);
p=NULL;//避免野指针
}
//非 ^ 合取* 析取+ 蕴含- 等值 = 优先级从左到右
Status isOPTR(char c)
{
if(c=='^'||c=='*'||c=='+'||c=='-'||c=='('||c==')'||c=='#'||c=='=')
return TRUE;
else return FALSE;
}
char Precede(char c1,char c2)
{
switch(c1)
{
case '^':
if(c2=='(')
return '<';
else
return '>';
case '*':
if(c2=='('||c2=='^')
return '<';
else
return '>';
case '+':
if(c2=='('||c2=='^'||c2=='*')
return '<';
else
return '>';
case '-':
if(c2=='('||c2=='^'||c2=='*'||c2=='+')
return '<';
else
return '>';
case '=':
if(c2=='='||c2==')'||c2=='#')
return '>';
else
return '<';
case '(':
if(c2==')')
return '=';
else
return '<';
case ')':
return '>';
case '#':
if(c2=='#')
return '=';
else
return '<';
default:
printf("格式错误\n");
return ERROR;
}
}
int Operate(int a,char sign,int b)//仅包含了双目运算符,不包含非操作,非操作将单独分类
{
switch(sign)
{
case '*':
return my_and(a,b);
case '+':
return my_or(a,b);
case '-':
return implied(a,b);
case '=':
return equivalent(a,b);
}
}
bool EvaluateExpression()
{
NumStackPtr OPND=NumInitStack();
CharStackPtr OPTR=CharInitStack();
CharPush(OPTR,'#');
char c=getchar();
char temp1; CharGetTop(OPTR,&temp1); char sign;int temp;
int a,b;
while(c!='#'||temp1!='#')
{
if(!isOPTR(c))//不是运算符则进栈
{
NumPush(OPND,c-'0');
c=getchar();
}
else
{
CharGetTop(OPTR,&temp1);
switch(Precede(temp1,c))
{
case '<':
CharPush(OPTR,c);
c=getchar();
break;
case '=':
CharPop(OPTR,&temp1);
c=getchar();
break;
case '>':
CharPop(OPTR,&sign);
if(sign=='^')
{
NumPop(OPND,&a);
NumPush(OPND,my_not(a));
}
else
{
NumPop(OPND,&a);
NumPop(OPND,&b);
NumPush(OPND,Operate(a,sign,b));
}
break;
}
}
CharGetTop(OPTR,&temp1);
}
NumGetTop(OPND,&temp);
if(temp)
return true;
else
return false;
}