实验原理
使用的数据结构和存储结构:
- 栈(中缀转后缀并计算)
- 数组(存放真值表)
- 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;
}