离散数学实验一 利用真值表法求取主析取范式以及主合取范式的实现

实验原理

使用的数据结构和存储结构:

  • 栈(中缀转后缀并计算)
  • 数组(存放真值表)
  • map(存放命题变元以及对应的真假值)
#include<iostream>
#include <string>
#include <map>
#include <stack>
#define MAX 100

using namespace std;

map<char,bool> statements;			//存储命题变元
int Prio(char ch);
string Trans(string str);
bool Judge(string str);
void Output(string wff,string suffix);

int main()
{
	string wff,suffix;
	cout << " 由于命题逻辑的一些符号不在ASCII表中,所以做以下规定:" << endl;
	cout << "	! :否定" << endl;
	cout << "	* :合取" << endl;
	cout << "	+ :析取" << endl;
	cout << "	> :单条件" << endl;
	cout << "	- :双条件" << endl;
	cout << "请输入合式公式:";
	cin >> wff;
	suffix = Trans(wff);
	Output(wff,suffix);
	return 0;
}

int Prio(char ch)				//定义联结词优先级
{
	if (ch == '!')
		return 4;
	if (ch == '*')
		return 3;
	if (ch == '+')
		return 2;
	if (ch == '>')
		return 1;
	if (ch == '-') 
		return 0;
	if (ch == '(')
		return -1;
	return 0;
}

string Trans(string str)
{
	string suffix;
	stack<char> stk;
	for (int  i = 0; i < str.length(); i++)
	{
		if (isalpha(str[i]))
			statements[str[i]]=0;
	}
	for (int i = 0; i < str.length(); i++)
	{
		if (statements.count(str[i]))		//操作数直接写入后缀表达式
			suffix+=str[i];
			
		else
		{
			if (stk.empty())
				stk.push(str[i]);
			else if (str[i] == '(')									//'('直接入栈		
				stk.push(str[i]);
			else if (str[i] == ')')							//当遇到')'时弹出栈中元素加入后缀表达式直到'('弹出为止
			{
				while (stk.top() != '(')
				{
					suffix += stk.top();
					stk.pop();
				}
				stk.pop();								//'('不需要加入后缀表达式
			}
			else
			{
				while (!stk.empty() && Prio(str[i]) <= Prio(stk.top()))			//当所遇到的操作符的优先级小于或等于栈顶元素的优先级时
				{
					suffix += stk.top();								//取出栈顶元素放入后缀表式,并弹出该栈顶元素
					stk.pop();
				}
				stk.push(str[i]);
			}
		}
	}
	while (!stk.empty())		//最后,如果栈不空,则弹出所有元素并放入后缀表式
	{
		suffix += stk.top();
		stk.pop();
	}
	return suffix;
}

bool Judge(string str)
{
	stack<bool> stk;		//用来计算真假值
	bool a, b;
	for (int i = 0; i < str.length(); i++)
	{
		if (statements.count(str[i]))			//命题直接入栈
			stk.push(statements[str[i]]);
		else
		{
			switch (str[i])
			{
			case '!':
				a = stk.top();
				stk.pop();
				stk.push(!a);
				break;
			case'*':
				a = stk.top();
				stk.pop();
				b = stk.top();
				stk.pop();
				stk.push(a * b);
				break;
			case'+':
				a = stk.top();
				stk.pop();
				b = stk.top();
				stk.pop();
				stk.push(a + b);
				break;
			case'>':
				a = stk.top();
				stk.pop();
				b = stk.top();
				stk.pop();
				stk.push(a + !b);
				break;
			case'-':
				a = stk.top();
				stk.pop();
				b = stk.top();
				stk.pop();
				stk.push((!a + b) * (a + !b));
				break;
			}
		}
	}
	return stk.top();
}

void Output(string wff,string suffix)
{
	string pdnf, pcnf,state;
	int n = statements.size();
	int truthTable[MAX][MAX];
	for ( auto iter = statements.begin(); iter !=statements.end(); iter++)
	{
		state += iter->first;							
		cout << iter->first << '\t';
	}
	cout << wff << endl;
	for (int i = 0; i < pow(2,n); i++)
	{
		int tmp = i;
		int j = n - 1;
		for (auto it = statements.rbegin(); it !=statements.rend(); it++)			//10->2进制对其进行赋值(倒叙)
		{
			truthTable[i][j] = it->second = tmp % 2;
			tmp /= 2;
			j--;
		}
		truthTable[i][n] = Judge(suffix);
	}
	for (int i = 0; i < pow(2, n); i++)			//拼接主析取和主合取范式
	{
		if (truthTable[i][n])
			pdnf += '(';
		else
			pcnf += '(';
		for (int j = 0; j < n; j++)
		{
			cout << truthTable[i][j]<<'\t';			//输出真值表
			if (truthTable[i][n])
			{
				if (truthTable[i][j] == 0) 
					pdnf += '!';
				pdnf += state[j];
				if (j < n - 1)
					pdnf += '*';
			}
			else
			{
				if(truthTable[i][j] == 1)
					pcnf += '!';
				pcnf += state[j];
				if (j < n - 1)
					pcnf += '+';
			}
		}
		cout << truthTable[i][n] << endl;
		if (truthTable[i][n])
			pdnf += ")+";
		else
			pcnf += ")*";
	}
	pdnf.erase(pdnf.size() - 1);		//删除多余的联结词
	pcnf.erase(pcnf.size() - 1);
	cout << "主析取范式为:" << pdnf << endl;
	cout << "主合取范式为:" << pcnf << endl;
}

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值