南京邮电大学离散数学实验一利用真值表求主析取范式和主合取范式

使用C语言实现,利用了堆栈的数据结构。为了避免拿来即用,主函数不全。希望能帮到真正需要的同学。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define msize 50
typedef struct stack{
	int top;
	int maxSize;
	char *element;
}Stack;
/*函数功能:初始化堆栈
  函数参数:堆栈的地址
  函数返回值:ERROR表示初始化失败,OK表示初始化成功
*/
void CreateStack(Stack *s)
{
	s->maxSize=msize;
	s->element=(char *)malloc(sizeof(char)*msize);
	s->top=-1;
}
/*函数功能:判断堆栈是否为空
  函数参数:堆栈的地址
  函数返回值:返回1表示堆栈空,返回0表示堆栈非空
*/
int IsEmpty(Stack *s)
{
	return s->top==-1;
}
/*函数功能:判断堆栈是否已满
  函数参数:堆栈的地址
  函数返回值:返回1表示堆栈已满,返回0表示堆栈未满
*/
int IsFull(Stack *s)
{
	return s->top==s->maxSize-1;
}
/*函数功能:获取栈顶元素的值
  函数参数:堆栈的地址
  函数返回值:栈顶元素
*/
char TopElem(Stack *s)
{
	if(IsEmpty(s))
		return '\0';
	return s->element[s->top];
}
/*函数功能:向栈中输入元素
  函数参数:堆栈的地址,新栈顶元素的值
  函数返回值:返回1表示输入成功,返回0表示输入失败
*/
int Push(Stack *s,char x)
{
	if(IsFull(s))
		return 0;
	s->top++;
	s->element[s->top]=x;
	return 1;
}
/*函数功能:删除栈顶元素
  函数参数:堆栈的地址
  函数返回值:返回1表示删除成功,返回0表示删除失败
*/
int Pop(Stack *s)
{
	if(IsEmpty(s))
		return 0;
	s->top--;
	return 1;
}
/*函数功能:清空栈中元素
  函数参数:堆栈的地址
  函数返回值:无
*/
void Clear(Stack *s)
{
	s->top=-1;
}
/*函数功能:检查输入的式子是否有非法字符
  函数参数:字符指针
  函数返回值:返回1表示式子合法,返回0表示式子非法
*/
int IsLegal(char *s)
{
	int i=0;
	char c;
	if(strlen(s)>50)
		return 0;
	for(;i<strlen(s);i++){
		c=s[i];
		if(!((c>='A'&&c<='Z')||c=='!'||c=='&'||c=='|'
			  ||c=='>'||c=='='||c=='('||c==')' ))
			  return 0;
	}
	return 1;
}
/*函数功能:获取某个运算符的栈外优先级
  函数参数:字符变量
  函数返回值:该字符变量的栈外优先级
*/
int ICP(char c)
{
	if(c=='(')
		return 4;
	else if(c=='!')
		return 3;
	else if(c==')')
		return 1;
	else if(c=='#')
		return 0;
	else
		return 2;
}
/*函数功能:获取某个运算符的栈内优先级
  函数参数:字符变量
  函数返回值:该字符变量的栈内优先级
*/
int ISP(char c)
{
	if(c=='(')
		return 1;
	else if(c=='!')
		return 3;
	else if(c==')')
		return 4;
	else if(c=='#')
		return 0;
	else
		return 2;
}
/*函数功能:将输入的式子元素通过栈转化为后缀表达式
  函数参数:两个字符指针
  函数返回值:无
*/
void ToPostfix(char *infix,char *postfix)
{
	int i,j;
	Stack s;
	CreateStack(&s);
	Push(&s,'#');
	j=0;
	for(i=0;i<strlen(infix);i++){
	    if(infix[i]>='A'&&infix[i]<='Z')
			postfix[j++]=infix[i];/*如果是操作数则直接输出*/
		else if(infix[i]==')'){      /*如果是左括号则连续出栈直到栈顶为右括号*/
			while(TopElem(&s)!='('){
		          postfix[j++]=TopElem(&s);
				  Pop(&s);
		    }
			Pop(&s);
		}
		else if(ICP(infix[i])<=ISP(TopElem(&s))){  /*如果操作符优先级小于栈顶元素优先级,则连续出栈直到大于,并将操作符入栈*/
				while(ICP(infix[i])<=ISP(TopElem(&s))&&ISP(TopElem(&s))!=0){
					  postfix[j++]=TopElem(&s);
					  Pop(&s);
				}
				Push(&s,infix[i]);
			}
		else
			Push(&s,infix[i]);/*如果操作符优先级大于栈顶元素,则直接入栈*/	
	}
	Clear(&s);
}
/*函数功能:检查某个变量是否重复出现
  函数参数:字符指针
  函数返回值:返回1说明重复,返回0说明不重复
*/
int IsRepeat(char *str,char c)
{
	int i=0;
	for(;i<strlen(str);i++)
		if(str[i]==c)
			return 1;
	return 0;
}
/*函数功能:计算表达式中的变元个数,同时打印这些变元
  函数参数:字符指针,整形指针
  函数返回值:字符指针的地址
*/
char* GetVariable(char *fix,int *n)
{
	char *temp=(char *)malloc(sizeof(char)*20);
	int i=0;
	int j=0;
	for(;i<strlen(fix);i++)
		if(fix[i]>='A'&&fix[i]<='Z'&&IsRepeat(temp,fix[i])!=1)
			temp[j++]=fix[i];
	printf("            对应真值表\n");
	for(i=0;i<j;i++)
	printf("   %c   ",temp[i]);
	*n=j;
	return temp;
}
/*函数功能:根据变元个数生成真值表
  函数参数:二维数组首地址,变元个数
  函数返回值:无
*/
void CreateTrueList(char **t,int n)
{
	int i=0;
	int j=0;
	int k=0;
	int row=pow(2,n);
	int col=n;
	for(;i<n;i++)
		for(j=0;j<row-1;j+=pow(2,n-i-1)){
		   for(k=j;k<j+pow(2,n-i-1);k++)
			   t[k][i]='T';
		   j=k;
		}
}
/*函数功能:初始化真值表全为F
  函数参数:二维数组首地址,变元个数
  函数返回值:二维数组首地址
*/
char ** IniTrueList(char **t,int n)
{
	int i=0;
	int row=pow(2,n);
	int col=n;
	int j=0;
    t=(char **)malloc(sizeof(char *)*row);/*创建长为2^n次方的指针数组*/
	for(;i<row;i++){
	    t[i]=(char *)malloc(sizeof(char)*(n+1));
	}
	for(i=0;i<row;i++)
		for(j=0;j<col;j++)
			t[i][j]='F';
	return t;
}
/*函数功能:打印真值表
  函数参数:二维数组首地址,变元个数
  函数返回值:无
*/
void PrintTrueList(char **t,int n)
{
	int i=0;
	int j=0;
	for(;i<pow(2,n);i++){
		for(j=0;j<n+1;j++)
		     printf("   %c   ",t[i][j]);
		printf("\n");
	}	
}
/*函数功能:将变元的真值代入后缀表达式中
  函数参数:指向二维真值表行的一级指针,待赋值的后缀表达式、变元数
  函数返回值:无
*/
void TrueListAssign(char *t,char *postfix,int n)
{
	int i=0;
	int count=0;
	char a[101]={0};
	for(i=0;postfix[i]!='\0';i++)
		if(!IsRepeat(a,postfix[i])&&postfix[i]>='A'&&postfix[i]<='Z'){
			a[count]=postfix[i];
		    count+=2;
		}
	count=0;
	for(i=1;count<n;i+=2){
	    a[i]=t[count++];
	}
	for(i=0;i<2*n;i+=2)
		for(count=0;postfix[count]!=0;count++)
			if(postfix[count]==a[i])
				postfix[count]=a[i+1];
	
}
/*函数功能:根据后缀表达式的操作符,来对已入栈的操作数进行计算
  函数参数:栈,后缀表达式
  函数返回值:无
*/
void Operation(Stack *s,char op)
{
	char a=0,b=0;
	if(op=='!')
		if(TopElem(s)=='T'){
			Pop(s);
			Push(s,'F');
			return ;
		}
		else{
			Pop(s);
			Push(s,'T');
			return ;
		}
	if(op=='&'){
		a=TopElem(s);
		Pop(s);
		b=TopElem(s);
		Pop(s);
		if(a=='T'&&b=='T')
			Push(s,'T');
		else
			Push(s,'F');
		return ;
	}
	if(op=='|'){
		a=TopElem(s);
		Pop(s);
		b=TopElem(s);
		Pop(s);
		if(a=='F'&&b=='F')
			Push(s,'F');
		else
			Push(s,'T');
		return ;
	}
	if(op=='>'){
		a=TopElem(s);
		Pop(s);
		b=TopElem(s);
		Pop(s);
		if(a=='F'&&b=='T')
			Push(s,'F');
		else
			Push(s,'T');
		return ;
	}
	if(op=='='){
		a=TopElem(s);
		Pop(s);
		b=TopElem(s);
		Pop(s);
		if((a=='T'&&b=='T')||(a=='F'&&a=='F'))
			Push(s,'T');
		else
			Push(s,'F');
		return ;
	}
}
/*函数功能:根据后缀表达式计算真值情况,并将结果存储在真值表中
  函数参数:二维数组,后缀表达式
  函数返回值:无
*/
void CalcuPostfix(char *postfix,char **t,int n)
{
	Stack s;
	int i=0;
	int j=0;
	char temp[50]={0};
	for(i=0;i<strlen(postfix);i++)
		temp[i]=postfix[i];
	CreateStack(&s);
	for(i=0;i<pow(2,n);i++){
		TrueListAssign(t[i],postfix,n);/*把第i行真值表中变元的值代入后缀表达式中*/
	    for(j=0;postfix[j]!='\0';j++)
			if(postfix[j]=='T'||postfix[j]=='F')/*如果是变元,则直接入栈*/
				Push(&s,postfix[j]);
			else
				Operation(&s,postfix[j]);/*如果是联结词,则对栈内元素进行运算*/
	t[i][n]=TopElem(&s);/*将运算结果储存在真值表中*/
	strcpy(postfix,temp);
	Pop(&s);
	}

}
/*函数功能:打印主析取范式
  函数参数:真值表,变元表,变元数目
  函数返回值:无
*/
void PrintPDNF(char **t,char *v,int n)
{
	int i=0;
	int j=0;
	int count=0;
	printf("主析取范式为:");
	for(;i<pow(2,n);i++)
	if(t[i][n]=='T'){
		printf("(");
		for(j=0;j<n;j++){
			if(t[i][j]=='T')
			    printf("%c",v[j]);
			else
				printf("!%c",v[j]);
		if(j!=n-1)printf("∧");
		}
		printf(")");
		count++;
		if(count!=pow(2,n-1))
			printf("∨");
	}
	printf("\n");
}
/*函数功能:打印主合取范式
  函数参数:真值表,变元表,变元数目
  函数返回值:无
*/
void PrintPCNF(char **t,char *v,int n)
{
	int i=0;
	int j=0;
	int count=0;
	printf("主合取范式为:");
	for(;i<pow(2,n);i++)
	if(t[i][n]=='F'){
		printf("(");
		for(j=0;j<n;j++){
			if(t[i][j]=='F')
			    printf("%c",v[j]);
			else
				printf("!%c",v[j]);
		if(j!=n-1)printf("∨");
		}
		printf(")");
		count++;
		if(count!=pow(2,n-1))
			printf("∧");
	}
	printf("\n");
}
/*函数功能:用于重新输入前清空字符串
  函数参数:字符指针
  函数返回值:无
*/
void ClearString(char *s)
{
	int i=0;
	while(s[i]!='\0')
		s[i++]='\0';
}
int main()
{
	char a[51]={0};
	char b[51]={0};
	int n=0;
	char *variable=NULL;
	char **TrueList=NULL;
	gets(a);
	a[strlen(a)]='#';
	variable=GetVariable(a,&n);
	TrueList=IniTrueList(TrueList,n);
	CreateTrueList(TrueList,n);
	ToPostfix(a,b);
	a[strlen(a)-1]='\0';
	printf("%s  \n",a);
	CalcuPostfix(b,TrueList,n);
	PrintTrueList(TrueList,n);
	PrintPDNF(TrueList,variable,n);
	PrintPCNF(TrueList,variable,n);
	printf("按任意键结束程序....");
	getchar();
	return 0;
}

有问题可以私信我哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值