C++实现求主析取范式、主合取范式


离散数学第一次上机实验,突击学完什么是主析取范式和主合取范式之后粗略地想了下实现的思路。

第一步自然是把输入的式子转换成后缀表达式。结合数据结构书上对基本四则运算的代码和前人的思路勉强写出来一个,但还是有很多地方可能一转头就会忘了怎么实现。

转换成后缀表达式之后的事情就显得轻松多了。

下面贴代码。

#include<iostream>
#include<string>

using namespace std;

class SeqStack {
public:
	SeqStack(int mSize);
	~SeqStack();
	bool Push(char x);
	bool Pop();
	char Top();
	bool Empty();
private:
	int top;
	char *stack;
	int maxtop;
};
SeqStack::SeqStack(int mSize) {
	maxtop = mSize - 1;
	stack = new char[mSize];
	top = -1;
}
SeqStack::~SeqStack() {
	delete[]stack;
}
bool SeqStack::Push(char x) {
	if (top == maxtop)
		return false;
	stack[++top] = x;
	return true;
}
bool SeqStack::Pop() {
	if (-1==top )return false;
	top--;
	return true;
}
bool SeqStack::Empty() {
	if (-1==top)return true;
	return false;
}
char SeqStack::Top() {
	return stack[top];
}
bool IsLegal(const string orgin) {
	for (unsigned int i = 0; i < orgin.length(); i++) {
		if (orgin[i] != 'P' && orgin[i] != 'Q' && orgin[i] != 'R' && orgin[i] != '&' && orgin[i] != '|' && orgin[i] != '=' && orgin[i] != '>'&&orgin[i]!='!')return false;
	}
	return true;
}
int And(int a,int b, SeqStack &stack) { 
	int res = a * b;
	stack.Push(res);
	return res;
}

int Or (int a, int b, SeqStack &stack) {
	int res = a + b;
	res = res > 1 ? 1 : res;
	stack.Push(res);
	return res;
}
int Not(int a, SeqStack &stack) {  
	a = stack.Top();
	stack.Pop();
	int res = a == 1 ? 0 : 1;
	stack.Push(res);
	return res;
}

int If(int a, int b, SeqStack &stack) { //条件
	int res = (b == 1 && a == 0) ? 0 : 1;
	stack.Push(res);
	return res;
}

int Iif(int a, int b, SeqStack &stack) {//双条件
	int res = (b == a) ? 1 : 0;
	stack.Push(res);
	return res;
}

bool CanIn(char out,SeqStack &stack) {        //先计算优先级,然后判断能否进栈
	char in = stack.Top();
	int i=0, o=0;  //分别表示栈内外运算符的优先级
	switch (in) {
	case '#':i = 0; break;
	case '(':i = 1; break;
	case '=':i = 3; break;
	case '>':i = 5; break;
	case '|':i = 7; break;
	case '&':i = 9; break;
	case '!':i = 11; break;
	case ')':i = 12; break;
	}

	switch (out) {
	case '#':o = 0; break;
	case '(':o = 12; break;
	case '=':o = 2; break;
	case '>':o = 4; break;
	case '|':o = 6; break;
	case '&':o = 8; break;
	case '!':o = 10; break;
	case ')':o = 1; break;
	}
	if (i < o)      //栈外优先级比栈内高就进栈
		return true;
	else
		return false;
}

void InfixToPostfix(string &orgin ,SeqStack &stack) {  //转换为后缀表达式
	string tmp;                //保存后缀表达式
	stack.Push('#');                
	for (int i = 0; (unsigned)i <orgin.length(); i++) {
		if (orgin[i] == 'P' || orgin[i] == 'Q' || orgin[i] == 'R' ) {
			tmp = tmp + orgin[i];
			continue;
		}
		if (CanIn(orgin[i],stack))
			stack.Push(orgin[i]);
		else if (orgin[i] == ')'){
			while (stack.Top() != '('){
				tmp = tmp + stack.Top();
				stack.Pop();
			}
			stack.Pop();
		}
		else{
			do{
				tmp = tmp + stack.Top();
				stack.Pop();
			} while (!CanIn(orgin[i],stack));
			stack.Push(orgin[i]);
		}
	}
	while (stack.Top() != '#'){
		tmp = tmp + stack.Top();
		stack.Pop();
	}
	stack.Pop();                // '#' 出栈
	orgin = tmp;
}


int Calculate(int number,string &org,SeqStack &stack, int p, int q, int r){
	int value=0,a=0,b=0,res=0;
	if (number == 3){
		for (int i = 0; (unsigned)i <org.length(); i++){
			if (org[i] == 'P' || org[i] == 'Q' || org[i] == 'R'){
				value = org[i] == 'P' ? p : org[i] == 'Q' ? q : r;
				stack.Push(value);
				continue;
			}
			if (org[i] != '!'){
				a = stack.Top();
				stack.Pop();
				b = stack.Top();
				stack.Pop();
			}
			switch (org[i]){
			case '=':res=Iif(a,b,stack); break;
			case '>':res=If(a, b, stack); break;
			case '|':res=Or(a, b, stack); break;
			case '&':res=And(a, b, stack); break;
			case '!':res=Not(a, stack); break;
			}
		}
	}
	if (number == 2){
		for (int i = 0;(unsigned)i <org.length(); i++){
			if (org[i] == 'P' || org[i] == 'Q'){
				value = org[i] == 'P' ? p : q;
				stack.Push(value);
				continue;
			}
			if (org[i] != '!'){
				a = stack.Top();
				stack.Pop();
				b = stack.Top();
				stack.Pop();
			}
			switch (org[i]) {
			case '=':res = Iif(a, b, stack); break;
			case '>':res = If(a, b, stack); break;
			case '|':res = Or(a, b, stack); break;
			case '&':res = And(a, b, stack); break;
			case '!':res = Not(a, stack); break;
			}
		}
	}
	return res;
}
char num2bool(int t) {
	if (0 == t)return 'T';
	else return 'F';
}


void Print(int number, string &orgin, SeqStack &stack) {
	int p, q, r, res;
	string pcnf;    //主合取范式
	string  pdnf;    //主析取范式
	if (number == 3) {
		cout << "P\t" << "Q\t" << "R\t" << "Z" << endl;
		for (p = 1; p >= 0; p--) {
			for (q = 1; q >= 0; q--) {
				for (r = 1; r >= 0; r--) {
					res = Calculate(3, orgin, stack, p, q, r);
					if (res == 1)
						pdnf = pdnf + "(" + (p == 1 ? "P" : "!P") + "&" + (q == 1 ? "Q" : "!Q") + "&"
						+ (r == 1 ? "R" : "!R") + ")" + " | ";
					else
						pcnf = pcnf + "(" + (p == 0 ? "P" : "!P") + "|" + (q == 0 ? "Q" : "!Q") + "|"
						+ (r == 0 ? "R" : "!R") + ")" + " & ";
					char cp, cq, cr, cres;
					cp = num2bool(p);
					cq = num2bool(q);
					cr = num2bool(r);
					cres = num2bool(res);
					cout << cp << "\t" << cq << "\t" << cr << "\t" << cres << endl;
				}
			}
		}
	}
	if (number == 2) {
		cout << "P\t" << "Q\t" << "Z" << endl;
		for (p = 1; p >= 0; p--) {
			for (q = 1; q >= 0; q--) {
				res=Calculate(2, orgin, stack, p, q, 0);
				if (res == 1)
					pdnf = pdnf + "(" + (p == 1 ? "P" : "!P") + "&" + (q == 1 ? "Q" : "!Q") + ")" + " | ";
				else
					pcnf = pcnf + "(" + (p == 0 ? "P" : "!P") + "|" + (q == 0 ? "Q" : "!Q") + ")" + " & ";
				char cp, cq, cres;
				cp = num2bool(p);
				cq = num2bool(q);
				cres = num2bool(res);
				cout << cp << "\t" << cq << "\t" << cres << endl;
			}
		}
	}
	//永真和永假的情况下长度为0
	if (pdnf.length() != 0)
		pdnf.erase(pdnf.length() - 2);
	if (pcnf.length() != 0)
		pcnf.erase(pcnf.length() - 2);
	cout << "主析取范式:" << pdnf << endl << endl;
	cout << "主合取范式:" << pcnf << endl << endl;

}
/****************************主函数******************************/
int main() {
	SeqStack stack(200);
	int cnt = 0;
	string orgin;
	int number;


	cout << "/**************输入提示*****************/" << endl;
	cout << "/*              ! 否定                 */" << endl;
	cout << "/*              | 析取                 */" << endl;
	cout << "/*              & 合取                 */" << endl;
	cout << "/*              > 条件                 */" << endl;
	cout << "/*              = 双条件               */" << endl;
	cout << "/**************输入提示*****************/" << endl;
	cout << "请输入变元数量 (2 或 3)" << endl;

	loop:cin >> number;
	if(2==number) 
		cout << endl << "变元请用P、Q表示" << endl ;
	else if (3==number)
		cout << endl << "变元请用P、Q、R表示" << endl;
	else {
		cout << "请输入2或3:  " << endl;
		goto loop;
	}
	cout << "输入命题:";
	int flag = 0;
	
	do {
		if (flag != 0) {
			cout << "输入包含不合法字符,请仔细阅读输入提示并重新输入\n(符号请使用半角英文符号)" << endl;
			cout << "输入命题:";
		}
		cin >> orgin;
		flag = 1;
	} while (!IsLegal(orgin));
	InfixToPostfix(orgin,stack);
	Print(number,orgin,stack);
	while (1);
	return 0;

}



  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是用C++编程实现用真值表法取任意含三个以内变量的主析取范式合取范式的代码: ```cpp #include <iostream> #include <string> #include <vector> #include <cmath> using namespace std; // 计算真值表 vector<vector<bool>> truthTable(int n) { int rows = pow(2, n); vector<vector<bool>> table(rows, vector<bool>(n)); for (int i = 0; i < rows; i++) { for (int j = 0; j < n; j++) { table[i][j] = (i / static_cast<int>(pow(2, j))) % 2; } } return table; } // 计算主析取范式 string mDNF(vector<vector<bool>> table) { string res; int n = table[0].size(); for (int i = 0; i < table.size(); i++) { if (table[i][n - 1]) { string term; for (int j = 0; j < n - 1; j++) { if (table[i][j]) { term += ('A' + j); } else { term += ('!' + to_string(j)); } term += "&"; } term.pop_back(); // 去除最后一个"&" res += ("(" + term + ")|"); } } res.pop_back(); // 去除最后一个"|" return res; } // 计算合取范式 string mCNF(vector<vector<bool>> table) { string res; int n = table[0].size(); for (int i = 0; i < table.size(); i++) { if (!table[i][n - 1]) { string term; for (int j = 0; j < n - 1; j++) { if (!table[i][j]) { term += ('A' + j); } else { term += ('!' + to_string(j)); } term += "|"; } term.pop_back(); // 去除最后一个"|" res += ("(" + term + ")&"); } } res.pop_back(); // 去除最后一个"&" return res; } int main() { int n; cout << "请输入变量数(不超过3):"; cin >> n; vector<vector<bool>> table = truthTable(n); cout << "真值表:" << endl; for (int i = 0; i < table.size(); i++) { for (int j = 0; j < n; j++) { cout << table[i][j] << " "; } cout << endl; } cout << "主析取范式:" << mDNF(table) << endl; cout << "合取范式:" << mCNF(table) << endl; return 0; } ``` 运行程序,输入变量数(不超过3),程序将输出真值表、主析取范式合取范式。例如,当输入2时,输出结果为: ``` 请输入变量数(不超过3):2 真值表: 0 0 0 1 1 0 1 1 主析取范式:(!0&!1)|(0&!1) 合取范式:(0|1)&(!0|1)&(0|!1) ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值