实验目的
学习逻辑表达式真值表建立,逻辑等价判断的实现。
实验内容与要求
- 写一段程序,测试p和q两个逻辑表达式是否逻辑相等
- 用真值表判断
- 输入的逻辑表达式为命题逻辑表达式
- 输入的逻辑表达式可以为复合命题,可包含四种联接词:与,或,非,条件
实验原理:
1.输入变量的个数,比如a b c,通过stringstream来读取,存储在哈希表和vector中.
2.输入命题p,命题q.
3.深度优先搜索,枚举变量的真值表.
void dfs(int index) {
if (末尾) {
输出;
}
第index位取反;
dfs(index + 1);
第index位取反;
dfs(index + 1);
}
4.在“输出”部分,处理命题p和q.按顺序读入p和q的字符串,&|!>分别为与、或、非、蕴含
对于如何读取逻辑表达式,可以直接对字符串从左到右解析。
bool process(string p) {
bool res = true;
int flag = 0;
int rev = 0;
for (int i = 0; i < p.length(); ++i) {
switch (p[i]) {
case '&':
flag = 1;
break;
case '|':
flag = 2;
break;
case '!':
{
int index = 0;
for (; index < vars.size(); ++index) {
if (p.substr(i+1).find(vars[index]) == 0)break;
}
string obj = vars[index];
rev = !var[obj];
switch (flag) {
case 0:
res = rev;
break;
case 1:
res = res && rev;
break;
case 2:
res = res || rev;
if (res)return res;
break;
case 4:
if (!res || (res && rev))return true;
return false;
break;
}
++i;
break;
}
case '>':
flag = 4;
break;
default:
{
int index = 0;
for (; index < vars.size(); ++index) {
if (p.substr(i).find(vars[index]) == 0)break;
}
string obj = vars[index];
switch (flag) {
case 0:
res = var[obj];
break;
case 1:
res = res&&var[obj];
break;
case 2:
res = res||var[obj];
if (res)return res;
break;
case 4:
if (!res||( res && var[obj]))return true;
return false;
break;
}
}
}
}
return res;
}
显然,这种方式只能解析较为简单的逻辑表达式,且容易存在优先级处理的问题,因此需要使用更为高级的方法来解析字符串。
可以参见计算器对任意表达式的匹配,通过构建二叉树的方式来处理表达式。
读取表达式的算法(二叉树):
1.按照运算符优先级(括号>取反>或>且),进行构建二叉树
2.通过后序遍历,进行逻辑运算.
struct node
{
bool bval = true;
string val;
node* l, * r;
};
bool singleBracket(string s) {
if (s[0] == '(' && s[s.length() - 1] == ')') {
string ss = s.substr(1, s.length() - 2);
if (ss.find('(') == ss.npos && ss.find(')') == ss.npos)
return 1;
}
return 0;
}
bool belongToBracket(string s, int i) {
int l = 0, r = 0;
for (int j = i; j >= 0; --j) {
if (s[j] == '(')l--;
if (s[j] == ')')l++;
if (l == -1)return 1;
}
for (int j = i; j <s.length(); ++j) {
if (s[j] == ')')r--;
if (s[j] == '(')r++;
if (r == -1)return 1;
}
return 0;
}
node* build(string p) {
if (!p.length())return NULL;
if (singleBracket(p)) {
string s = p.substr(1, p.length() - 2);
if(s.find('(')==s.npos&&s.find(')')==s.npos)
return build(s);
}
int i = 0;
node* obj = new node();
if (p.length() == 1) {
obj->val = p;
return obj;
}
if (p.length()==2&&p[0]=='!'||singleBracket(p.substr(1)) && p[0] == '!') {
obj->val = '!';
obj->l = build(p.substr(1));
return obj;
}
for (; i < p.length(); ++i) {
if (p[i] == '>' && !belongToBracket(p,i)) {
obj->val = p[i];
obj->l = build(p.substr(0, i));
obj->r = build(p.substr(i + 1, p.length() - i - 1));
return obj;
}
}
i = 0;
for (; i < p.length(); ++i) {
if (p[i] == '|' && !belongToBracket(p, i)) {
obj->val = p[i];
obj->l = build(p.substr(0, i));
obj->r = build(p.substr(i + 1, p.length() - i - 1));
return obj;
}
}
i = 0;
for (; i < p.length(); ++i) {
if (p[i] == '&' && !belongToBracket(p, i)) {
obj->val = p[i];
obj->l = build(p.substr(0, i));
obj->r = build(p.substr(i + 1, p.length() - i - 1));
return obj;
}
}
return obj;
}
bool postorder(node* tree) {
if (!tree)return 1;
if (tree->val[0] != '&' && tree->val[0] != '|' && tree->val[0] != '>'&& tree->val[0] != '!')
return var[tree->val];
bool L = 1, R = 1;
if (tree->l)L = postorder(tree->l);
if (tree->r)R = postorder(tree->r);
switch (tree->val[0]) {
case '&':
return L && R;
case '|':
return L || R;
case '>':
return (L ? R : 1);
case '!':
return!(L && R);
}
}
bool process(string p) {
node* tree = build(p);
return postorder(tree);
}
以下是完整的代码。
// Exp4_逻辑等价判断.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//bool process(string p) {
// bool res = true;
// int flag = 0;
// int rev = 0;
// for (int i = 0; i < p.length(); ++i) {
// switch (p[i]) {
// case '&':
// flag = 1;
// break;
// case '|':
// flag = 2;
//
// break;
// case '!':
// {
// int index = 0;
// for (; index < vars.size(); ++index) {
// if (p.substr(i+1).find(vars[index]) == 0)break;
// }
// string obj = vars[index];
// rev = !var[obj];
// switch (flag) {
// case 0:
// res = rev;
// break;
// case 1:
// res = res && rev;
// break;
// case 2:
// res = res || rev;
// if (res)return res;
// break;
// case 4:
//
// if (!res || (res && rev))return true;
// return false;
//
// break;
// }
// ++i;
// break;
// }
// case '>':
// flag = 4;
// break;
// default:
// {
// int index = 0;
// for (; index < vars.size(); ++index) {
// if (p.substr(i).find(vars[index]) == 0)break;
// }
// string obj = vars[index];
// switch (flag) {
// case 0:
// res = var[obj];
// break;
// case 1:
// res = res&&var[obj];
// break;
// case 2:
// res = res||var[obj];
// if (res)return res;
// break;
// case 4:
// if (!res||( res && var[obj]))return true;
// return false;
//
//
// break;
// }
//
// }
//
//
// }
//
// }
//
//
// return res;
//}
#include <iostream>
#include <string>
#include <stack>
#include <sstream>
#include <vector>
#include <unordered_map>
using namespace std;
unordered_map<string, bool>var;
vector<string>vars;
/// <summary>
/// & | ! >
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
struct node
{
bool bval = true;
string val;
node* l, * r;
};
bool singleBracket(string s) {
if (s[0] == '(' && s[s.length() - 1] == ')') {
string ss = s.substr(1, s.length() - 2);
if (ss.find('(') == ss.npos && ss.find(')') == ss.npos)
return 1;
}
return 0;
}
bool belongToBracket(string s, int i) {
int l = 0, r = 0;
for (int j = i; j >= 0; --j) {
if (s[j] == '(')l--;
if (s[j] == ')')l++;
if (l == -1)return 1;
}
for (int j = i; j <s.length(); ++j) {
if (s[j] == ')')r--;
if (s[j] == '(')r++;
if (r == -1)return 1;
}
return 0;
}
node* build(string p) {
if (!p.length())return NULL;
if (singleBracket(p)) {
string s = p.substr(1, p.length() - 2);
if(s.find('(')==s.npos&&s.find(')')==s.npos)
return build(s);
}
int i = 0;
node* obj = new node();
if (p.length() == 1) {
obj->val = p;
return obj;
}
if (p.length()==2&&p[0]=='!'||singleBracket(p.substr(1)) && p[0] == '!') {
obj->val = '!';
obj->l = build(p.substr(1));
return obj;
}
for (; i < p.length(); ++i) {
if (p[i] == '>' && !belongToBracket(p,i)) {
obj->val = p[i];
obj->l = build(p.substr(0, i));
obj->r = build(p.substr(i + 1, p.length() - i - 1));
return obj;
}
}
i = 0;
for (; i < p.length(); ++i) {
if (p[i] == '|' && !belongToBracket(p, i)) {
obj->val = p[i];
obj->l = build(p.substr(0, i));
obj->r = build(p.substr(i + 1, p.length() - i - 1));
return obj;
}
}
i = 0;
for (; i < p.length(); ++i) {
if (p[i] == '&' && !belongToBracket(p, i)) {
obj->val = p[i];
obj->l = build(p.substr(0, i));
obj->r = build(p.substr(i + 1, p.length() - i - 1));
return obj;
}
}
return obj;
}
bool postorder(node* tree) {
if (!tree)return 1;
if (tree->val[0] != '&' && tree->val[0] != '|' && tree->val[0] != '>'&& tree->val[0] != '!')
return var[tree->val];
bool L = 1, R = 1;
if (tree->l)L = postorder(tree->l);
if (tree->r)R = postorder(tree->r);
switch (tree->val[0]) {
case '&':
return L && R;
case '|':
return L || R;
case '>':
return (L ? R : 1);
case '!':
return!(L && R);
}
}
bool process(string p) {
node* tree = build(p);
return postorder(tree);
}
char btos(bool i) {
return (i ? 'T' : 'F');
}
string p, q;
bool same = true;
void dfs(int index) {
if (index == vars.size()) {
if (process(p) != process(q))same = false;
for (auto i : vars)cout << btos(var[i]) << (i != vars.back() ? "\t" : "");
cout << "\t\t" << btos(process(p)) << "\t\t\t" << btos(process(q)) << endl;
return;
}
var[vars[index]] = !var[vars[index]];
dfs(index + 1);
var[vars[index]] = !var[vars[index]];
dfs(index + 1);
}
int main()
{
cout << "请输入变量:" << endl;
string src;
getline(cin, src);
stringstream ss(src);
while (ss >> src) {
if (!var[src])vars.push_back(src);
var[src] = 1;
}
cout << "请输入命题p:" << endl;
getline(cin, p);
cout << "请输入命题q:" << endl;
getline(cin, q);
for (auto i : vars)cout << i << (i != vars.back() ? "\t" : "");
cout << "\t\t" << p << "\t\t" << q << endl;
dfs(0);
if(same)
cout << "两个命题等价!" << endl;
else
cout << "两个命题不等价!" << endl;
return 0;
}