【离散数学】(联结词按优先级,3个变量及以下)真值表及范式(有源码c语言,拿来就用)


在这里插入图片描述
在这里插入图片描述

实验

实验内容

编程实现用真值表法求取含三个以内变量的合式公式的主析取范式和主合取范式。

实验要求

要求:

  • 从屏幕输入含三个以内变量的合式公式(其中 联结词按照从高到底的顺序出现)。

  • 规范列出所输合式公式的真值表。

  • 给出相应主析取和主合取范式。
    [外链图片转存中…(img-KttFRYgu-1719842214597)]

具体实现

具体实现可以参考以下思路:

改造联结词

在输入联结词时就会要求用!表示否定,&表示合取,|表示析取,>表示条件,-表示双条件。
我们就设计一个函数将这些联结词改造对应的数字,以便后面switch case操作(可以省略直接在case中判断符号就行)。

//! //联结词改造函数
char* conjuction(char a[], size_t len)//len表示字符串长度
{
	for (int i = 0; i < len; i++)
	{
		if (a[i] == '!')
			a[i] = '6';
		else if (a[i] == '&')
			a[i] = '2';
		else if (a[i] == '|')
			a[i] = '3';
		else if (a[i] == '>')
			a[i] = '4';
		else if (a[i] == '-')
			a[i] = '5';
	}
	return a;
}

联结词计算函数

对每个联结词对应的计算方法写成函数。

//|计算函数
char or1(char a, char b)
{
	if (a == '0' && b == '0')
		return '0';
	return '1';
}
//&计算函数
char and1(char a, char b)
{
	if (a == '1' && b == '1')
		return '1';
	return '0';
}
//!计算函数
char dif(char a)
{
	if (a == '0')
		return '1';
	return '0';
}
//条件判断函数
char con(char a, char b)
{
	if (a == '1' && b == '0')
		return '0';
	else
		return '1';
}
//双条件判断函数
char dou_con(char a, char b)
{
	if (a == b)
		return '1';
	else
		return '0';
}

总计算方法

我们还需要写一个函数将联结词计算方法串起来,并对合式公式进行计算。

用switch case来进行计算。

//计算函数
char count(char a[], size_t len, char b1, char b2,char b3)
{
	change(a, len, b1, b2,b3);

	for (int j = 0; j < len; j++)
	{
		if (a[j] >= '2')
		{
			int tem = (int)a[j] - 48;
			switch (tem)
			{
			case 2:
				a[j + 1] = and1(a[j - 1], a[j + 1]);
				break;
			case 3:
				a[j + 1] = or1(a[j - 1], a[j + 1]);
				break;
			case 4:
				a[j + 1] = con(a[j - 1], a[j + 1]);
				break;
			case 5:
				a[j + 1] = dou_con(a[j - 1], a[j + 1]);
				break;
			case 6:
				a[j + 1] = dif(a[j + 1]);
				break;
			default:
				break;
			}
		}
	}
	return a[len - 1];
}

改命题变元值

将命题变元传来是真假分别用1 0来表示,但我写的代码只能将命题变元用PQR表示,其他不行。

//改PQ值为1 0
void change(char a[], size_t len, char b1, char b2,char b3)
{
	for (int j = 0; j < len; j++)
	{
		if (a[j] == 'P')
			a[j] = b1;
		else if (a[j] == 'Q')
			a[j] = b2;
		else if (a[j] == 'R')
			a[j] = b3;
	}
}

命题变元个数判断函数

直接循环遍历然后记录出现次数就行。

//判断命题变元数量函数
int judgeNum(char a[], size_t len)
{
	int numP = 0;
	int numQ = 0;
	int numR = 0;
	int num = 0;
	for (int i = 0; i < len; i++)
	{
		if (a[i] == 'P')
			numP++;
		else if (a[i] == 'Q')
			numQ++;
		else if (a[i] == 'R')
			numR++;
	}
	if (numP > 0)
		num++;
	if (numQ > 0)
		num++;
	if (numR > 0)
		num++;
	return num;
}

打印函数

在写打印函数之前我们先来回顾一下如何根据真值表得出范式。

  • 主合取范式:真值结果为假F,变元如果为真就写为否定 !P,如果为假就不取否定。
  • 主析取范式:真值结果为真T,变元如果为假就写为否定!P,如果为真就不取否定。
//单变元打印
void onePrint(char a[], size_t len, char dis[], char pri[])
{
	printf("该合式公式真值表如下表示:\n");
	printf("P\t%s\n", a);
	char b[MAX];
	conjuction(a, len);
	char ret;
	strcpy(b, a);
	ret = count(a, len, '1', '1', '1');
	printf("1\t%c\n",ret);
	strcpy(a, b);
	ret = count(a, len, '0', '0', '0');
	printf("0\t%c\n",ret);
}
//双变元打印
void twoPrint(char a[], size_t len, char dis[], char pri[])
{
	printf("该合式公式真值表如下表示:\n");

	printf("P\tQ\t%s\n", a);
	char b[MAX];
	char ret;
	conjuction(a, len);
	strcpy(b, a);
	ret = count(a, len, '1', '1', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(!P|!Q)&");
	else if (ret == '1')
		strcat(dis, "(P&Q)|");
	printf("1\t1\t%c\n",ret);
	strcpy(a, b);
	ret = count(a, len, '1', '0', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(!P|Q)&");
	else if (ret == '1')
		strcat(dis, "(P&!Q)|");
	printf("1\t0\t%c\n",ret );
	strcpy(a, b);
	ret = count(a, len, '0', '1', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(P|!Q)&");
	else if (ret == '1')
		strcat(dis, "(!P&Q)|");
	printf("0\t1\t%c\n",ret);
	strcpy(a, b);
	ret = count(a, len, '0', '0', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(P|Q)&");
	else if (ret == '1')
		strcat(dis, "(!P&!Q)|");
	printf("0\t0\t%c\n",ret );
}
//三变元打印
void threePrint(char a[], size_t len, char dis[], char pri[])
{
	printf("该合式公式真值表如下表示:\n");
	printf("P\tQ\tR\t%s\n", a);
	char b[MAX];
	char ret;
	conjuction(a, len);
	strcpy(b, a);
	ret = count(a, len, '1', '1', '1');
	//计算范式
	if (ret == '1')
		strcat(dis, "(P&Q&R)|");
	else if (ret == '0')
		strcat(pri, "(!P|!Q|!R)&");
	printf("1\t1\t1\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '1', '1', '0');
	if (ret == '1')
		strcat(dis, "(P&Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(!P|!Q|R)&");
	printf("1\t1\t0\t%c\n",ret );
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '1', '0', '1');
	if (ret == '1')
		strcat(dis, "(P&!Q&R)|");
	else if (ret == '0')
		strcat(pri, "(!P|Q|!R)&");
	printf("1\t0\t1\t%c\n",ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '1', '0', '0');
	if (ret == '1')
		strcat(dis, "(P&!Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(!P|Q|R)&");
	printf("1\t0\t0\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '1', '1');
	if (ret == '1')
		strcat(dis, "(!P&Q&R)|");
	else if (ret == '0')
		strcat(pri, "(P|!Q|!R)&");
	printf("0\t1\t1\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '1', '0');
	if (ret == '1')
		strcat(dis, "(!P&Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(P|!Q|R)&");
	printf("0\t1\t0\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '0', '1');
	if (ret == '1')
		strcat(dis, "(!P&!Q&R)|");
	else if (ret == '0')
		strcat(pri, "(P|Q|!R)&");
	printf("0\t0\t1\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '0', '0');
	if (ret == '1')
		strcat(dis, "(!P&!Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(P|Q|R)&");
	printf("0\t0\t0\t%c\n",ret);
}
//主析取范式打印
void disPrint(char dis[], size_t disLen)
{
	printf("该合式公式的主析取范式:\n");
	for (int i = 1; i < disLen - 1; i++)
		printf("%c", dis[i]);
	printf("\n");
}
//主合取范式打印
void priPrint(char pri[], size_t priLen)
{
	printf("该合式公式的主合取范式:\n");
	for (int i = 1; i < priLen - 1; i++)
		printf("%c", pri[i]);
	printf("\n");
}

主函数中调用

调用思路如下:

  • 主函数中用一个字符数组来接收传来的合式公式。

  • 在调用命题变元判断函数来判断有几个命题变元。

  • 然后再根据命题变元个数调用对应的打印函数。

int main()
{
	printf("输入不超过三种命题变元(PQR表示)的合式公式(联结词优先级从高到低):\n");
	char a[MAX];
	char disNorForm[MAXX] ="0";//主析取范式
	char priConNorForm[MAXX]="0";//主合取范式
	scanf("%s", a);
	size_t len = strlen(a);
	size_t disLen;
	size_t priLen;
	int num = judgeNum(a,len);
	switch (num)
	{
	case 1:
		onePrint(a, len,disNorForm,priConNorForm);
		printf("该合式公式无主合取范式和主析取范式");
		break;
	case 2:
		twoPrint(a, len, disNorForm, priConNorForm);
		disLen = strlen(disNorForm);
		disPrint(disNorForm, disLen);
		priLen = strlen(priConNorForm);
		priPrint(priConNorForm, priLen);
		break;
	case 3:
		threePrint(a, len, disNorForm, priConNorForm);
		disLen = strlen(disNorForm);
		disPrint(disNorForm, disLen);
		priLen = strlen(priConNorForm);
		priPrint(priConNorForm, priLen);
		break;
	default:
		break;
	}
	
	return 0;
}

源码

源码呈上:

#include<stdio.h>
#include<string.h>
#define MAX 20
#define MAXX 40
//联结词改造函数
char* conjuction(char a[], size_t len);

//|计算函数
char or1(char a, char b);

//&计算函数
char and1(char a, char b);

//!计算函数
char dif(char a);
//条件判断函数
char con(char a, char b);
//双条件判断函数
char dou_con(char a, char b);
//改PQ值为1 0
void change(char a[], size_t len, char b1, char b2,char b3);
//计算函数
char count(char a[], size_t len, char b1, char b2,char b3);
//判断命题变元数量函数
int judgeNum(char a[], size_t len);
//单变元打印
void onePrint(char a[], size_t len,char dis[], char pri[]);


//双变元打印
void twoPrint(char a[], size_t len, char dis[], char pri[]);
//三变元打印
void threePrint(char a[], size_t len, char dis[], char pri[]);
//主合取范式打印
void priPrint(char pri[], size_t priLen);
//主析取范式打印
void disPrint(char dis[], size_t disLen);

int main()
{
	printf("输入不超过三种命题变元(PQR表示)的合式公式(联结词优先级从高到低):\n");
	char a[MAX];
	char disNorForm[MAXX] ="0";//主析取范式
	char priConNorForm[MAXX]="0";//主合取范式
	scanf("%s", a);
	size_t len = strlen(a);
	size_t disLen;
	size_t priLen;
	int num = judgeNum(a,len);
	switch (num)
	{
	case 1:
		onePrint(a, len,disNorForm,priConNorForm);
		printf("该合式公式无主合取范式和主析取范式");
		break;
	case 2:
		twoPrint(a, len, disNorForm, priConNorForm);
		disLen = strlen(disNorForm);
		disPrint(disNorForm, disLen);
		priLen = strlen(priConNorForm);
		priPrint(priConNorForm, priLen);
		break;
	case 3:
		threePrint(a, len, disNorForm, priConNorForm);
		disLen = strlen(disNorForm);
		disPrint(disNorForm, disLen);
		priLen = strlen(priConNorForm);
		priPrint(priConNorForm, priLen);
		break;
	default:
		break;
	}
	
	return 0;
}

//! //联结词改造函数
char* conjuction(char a[], size_t len)
{
	for (int i = 0; i < len; i++)
	{
		if (a[i] == '!')
			a[i] = '6';
		else if (a[i] == '&')
			a[i] = '2';
		else if (a[i] == '|')
			a[i] = '3';
		else if (a[i] == '>')
			a[i] = '4';
		else if (a[i] == '-')
			a[i] = '5';
	}
	return a;
}
//|计算函数
char or1(char a, char b)
{
	if (a == '0' && b == '0')
		return '0';
	return '1';
}
//&计算函数
char and1(char a, char b)
{
	if (a == '1' && b == '1')
		return '1';
	return '0';
}
//!计算函数
char dif(char a)
{
	if (a == '0')
		return '1';
	return '0';
}
//条件判断函数
char con(char a, char b)
{
	if (a == '1' && b == '0')
		return '0';
	else
		return '1';
}
//双条件判断函数
char dou_con(char a, char b)
{
	if (a == b)
		return '1';
	else
		return '0';
}
//改PQR值为1 0
void change(char a[], size_t len, char b1, char b2,char b3)
{
	for (int j = 0; j < len; j++)
	{
		if (a[j] == 'P')
			a[j] = b1;
		else if (a[j] == 'Q')
			a[j] = b2;
		else if (a[j] == 'R')
			a[j] = b3;
	}
}
//计算函数
char count(char a[], size_t len, char b1, char b2,char b3)
{
	change(a, len, b1, b2,b3);

	for (int j = 0; j < len; j++)
	{
		if (a[j] >= '2')
		{
			int tem = (int)a[j] - 48;
			switch (tem)
			{
			case 2:
				a[j + 1] = and1(a[j - 1], a[j + 1]);
				break;
			case 3:
				a[j + 1] = or1(a[j - 1], a[j + 1]);
				break;
			case 4:
				a[j + 1] = con(a[j - 1], a[j + 1]);
				break;
			case 5:
				a[j + 1] = dou_con(a[j - 1], a[j + 1]);
				break;
			case 6:
				a[j + 1] = dif(a[j + 1]);
				break;
			default:
				break;
			}
		}
	}
	return a[len - 1];
}
//判断命题变元数量函数
int judgeNum(char a[], size_t len)
{
	int numP = 0;
	int numQ = 0;
	int numR = 0;
	int num = 0;
	for (int i = 0; i < len; i++)
	{
		if (a[i] == 'P')
			numP++;
		else if (a[i] == 'Q')
			numQ++;
		else if (a[i] == 'R')
			numR++;
	}
	if (numP > 0)
		num++;
	if (numQ > 0)
		num++;
	if (numR > 0)
		num++;
	return num;
}
//单变元打印
void onePrint(char a[], size_t len, char dis[], char pri[])
{
	printf("该合式公式真值表如下表示:\n");
	printf("P\t%s\n", a);
	char b[MAX];
	conjuction(a, len);
	char ret;
	strcpy(b, a);
	ret = count(a, len, '1', '1', '1');
	printf("1\t%c\n",ret);
	strcpy(a, b);
	ret = count(a, len, '0', '0', '0');
	printf("0\t%c\n",ret);
}
//双变元打印
void twoPrint(char a[], size_t len, char dis[], char pri[])
{
	printf("该合式公式真值表如下表示:\n");

	printf("P\tQ\t%s\n", a);
	char b[MAX];
	char ret;
	conjuction(a, len);
	strcpy(b, a);
	ret = count(a, len, '1', '1', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(!P|!Q)&");
	else if (ret == '1')
		strcat(dis, "(P&Q)|");
	printf("1\t1\t%c\n",ret);
	strcpy(a, b);
	ret = count(a, len, '1', '0', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(!P|Q)&");
	else if (ret == '1')
		strcat(dis, "(P&!Q)|");
	printf("1\t0\t%c\n",ret );
	strcpy(a, b);
	ret = count(a, len, '0', '1', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(P|!Q)&");
	else if (ret == '1')
		strcat(dis, "(!P&Q)|");
	printf("0\t1\t%c\n",ret);
	strcpy(a, b);
	ret = count(a, len, '0', '0', '0');
	//存储范式值
	if (ret == '0')
		strcat(pri, "(P|Q)&");
	else if (ret == '1')
		strcat(dis, "(!P&!Q)|");
	printf("0\t0\t%c\n",ret );
}
//三变元打印
void threePrint(char a[], size_t len, char dis[], char pri[])
{
	printf("该合式公式真值表如下表示:\n");
	printf("P\tQ\tR\t%s\n", a);
	char b[MAX];
	char ret;
	conjuction(a, len);
	strcpy(b, a);
	ret = count(a, len, '1', '1', '1');
	//计算范式
	if (ret == '1')
		strcat(dis, "(P&Q&R)|");
	else if (ret == '0')
		strcat(pri, "(!P|!Q|!R)&");
	printf("1\t1\t1\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '1', '1', '0');
	if (ret == '1')
		strcat(dis, "(P&Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(!P|!Q|R)&");
	printf("1\t1\t0\t%c\n",ret );
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '1', '0', '1');
	if (ret == '1')
		strcat(dis, "(P&!Q&R)|");
	else if (ret == '0')
		strcat(pri, "(!P|Q|!R)&");
	printf("1\t0\t1\t%c\n",ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '1', '0', '0');
	if (ret == '1')
		strcat(dis, "(P&!Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(!P|Q|R)&");
	printf("1\t0\t0\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '1', '1');
	if (ret == '1')
		strcat(dis, "(!P&Q&R)|");
	else if (ret == '0')
		strcat(pri, "(P|!Q|!R)&");
	printf("0\t1\t1\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '1', '0');
	if (ret == '1')
		strcat(dis, "(!P&Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(P|!Q|R)&");
	printf("0\t1\t0\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '0', '1');
	if (ret == '1')
		strcat(dis, "(!P&!Q&R)|");
	else if (ret == '0')
		strcat(pri, "(P|Q|!R)&");
	printf("0\t0\t1\t%c\n", ret);
	strcpy(a, b);
	//计算范式
	ret = count(a, len, '0', '0', '0');
	if (ret == '1')
		strcat(dis, "(!P&!Q&!R)|");
	else if (ret == '0')
		strcat(pri, "(P|Q|R)&");
	printf("0\t0\t0\t%c\n",ret);
}
//主析取范式打印
void disPrint(char dis[], size_t disLen)
{
	printf("该合式公式的主析取范式:\n");
	for (int i = 1; i < disLen - 1; i++)
		printf("%c", dis[i]);
	printf("\n");
}
//主合取范式打印
void priPrint(char pri[], size_t priLen)
{
	printf("该合式公式的主合取范式:\n");
	for (int i = 1; i < priLen - 1; i++)
		printf("%c", pri[i]);
	printf("\n");
}

写的可能有点冗杂屎山读者见谅。

  • 151
    点赞
  • 124
    收藏
    觉得还不错? 一键收藏
  • 132
    评论
评论 132
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值