离散数学实验:真值表c++实现
为实现算符优先算法,我们采用两个工作栈。一个称作 OPTR,用以寄
存运算符;另一个称作 OPND,用以寄存操作数或运算结果。算法的基本思
想是:
(
1)首先设置操作数栈为空栈,符号“@”为运算符的栈底元素;
(
2)调用函数 Divi(exp,myopnd)得到命题公式包含的命题变元序
列 myopnd(按字典序排列,同一个命题变元只出现一次);
(
3)依次读入命题公式中的每个字符,若是命题变元则其对应的赋值
进 OPND 栈,若是运算符,则和 OPTR 栈的栈顶运算符比较后作相应操作,
直至整个命题公式求值完毕。
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
#include<unordered_map>
#include<cmath>
using namespace std;
double sum = 0;
char value[50] = " ";
string s;//命题公式
stack<char> OPND;
stack<char> OPTR;
queue<char>transfer;//储存s转换的逆波兰表达式
queue<char>new_tf;//复制transfer
//否定、合取、析取、条件 双条件
// !、 & 、 | 、 -、 +
int Divi(const string exp, char myopnd[50])
{
int num = exp.size();
int key = 0;
for (int i = 0; i < num; i++)
{
if (exp[i] >= 'a' && exp[i] <= 'z' || exp[i] >= 'A' && exp[i] <= 'Z')
{
int l = 0;
for (int k = 0; k < key; k++)
{
if (exp[i] == myopnd[k])
l++;
}
if (l == 0)
{
myopnd[key] = exp[i];
key++;
}
}
}
sum = key;
return key; //得到的个数是key个
}
void change()//将命题公式转换成逆波兰表达式
{
int i;
for (i = 0; i < s.length(); i++)
{//banyuyou防盗注释
if (s[i] >= 'A' && s[i] <= 'Z' || s[i] >= 'a' && s[i] <= 'z')//变元直接压入栈
{
transfer.push(s[i]);
}
else if (s[i] == '!')//检查栈顶优先级看是否压入
{//banyuyou防盗注释
if (OPND.top() == '+' || OPND.top() == '-' || OPND.top() == '|' || OPND.top() == '&' || OPND.top() == '!' || OPND.top() == '@' || OPND.top() == '(')
{
OPND.push(s[i]);
}
}
else if (s[i] == '&')
{
while (OPND.top() == '!')
{
char temp = OPND.top();
transfer.push(temp);
OPND.pop();
}
if (OPND.top() == '+' || OPND.top() == '-' || OPND.top() == '|' || OPND.top() == '&' || OPND.top() == '@' || OPND.top() == '(')
{
OPND.push(s[i]);
}
}
else if (s[i] == '|')
{
while (OPND.top() == '&' || OPND.top() == '!')
{
char temp = OPND.top();
transfer.push(temp);
OPND.pop();
}
if (OPND.top() == '-' || OPND.top() == '|' || OPND.top() == '+' || OPND.top() == '@' || OPND.top() == '(')
{
OPND.push(s[i]);
}
}
else if (s[i] == '-')
{
while (OPND.top() == '&' || OPND.top() == '|' || OPND.top() == '!')
{
char temp = OPND.top();
transfer.push(temp);
OPND.pop();
}
if (OPND.top() == '-' || OPND.top() == '+' || OPND.top() == '@' || OPND.top() == '(')
{
OPND.push(s[i]);
}
}
else if (s[i] == '+')
{
while (OPND.top() == '&' || OPND.top() == '|' || OPND.top() == '-' || OPND.top() == '!')
{
char temp = OPND.top();
transfer.push(temp);
OPND.pop();
}
if (OPND.top() == '+' || OPND.top() == '@' || OPND.top() == '(')
{
OPND.push(s[i]);
}
}
else if (s[i] == '(')
{
OPND.push(s[i]);
}
else if (s[i] == ')')
{
while (OPND.top() != '(')
{
char temp = OPND.top();
transfer.push(temp);
OPND.pop();
}
if (OPND.top() == '(')
{
OPND.pop();
continue;
}
}
}
while (!OPND.empty())
{
if (OPND.top() != '@')
{
char temp = OPND.top();
transfer.push(temp);
OPND.pop();
}
else if (OPND.top() == '@')
{
OPND.pop();
}
}
}
void fei()//非
{
if (!OPTR.empty())
{
int temp = !OPTR.top();
OPTR.pop();//弹出一个真值,并出栈
OPTR.push(temp);//操作结果压栈
}//banyuyou防盗注释
}
void yu() //与
{
if (!OPTR.empty()) {
int temp1 = OPTR.top();
OPTR.pop();//弹出两个真值,并出栈
int temp2 = OPTR.top();
OPTR.pop();
int temp = temp1 & temp2;
OPTR.push(temp);//操作结果压栈
}//banyuyou防盗注释
}
void huo() //或
{
if (!OPTR.empty()) {
int temp1 = OPTR.top();
OPTR.pop();
int temp2 = OPTR.top();
OPTR.pop();
int temp = temp1 | temp2;
OPTR.push(temp);
}//banyuyou防盗注释
}
void tiaojian() //条件
{
if (!OPTR.empty()) {
int temp1 = OPTR.top(); OPTR.pop();
int temp2 = OPTR.top(); OPTR.pop();
int temp;
if (temp1 == 0 && temp2 == 1) temp = 0;
else temp = 1;
OPTR.push(temp);
}//banyuyou防盗注释
}
void Shuangtiaojian() //双条件
{
if (!OPTR.empty())
{
int temp1 = OPTR.top(); OPTR.pop();
int temp2 = OPTR.top(); OPTR.pop();
int temp;
if (temp1 == temp2) temp = 1;
else temp = 0;
OPTR.push(temp);
}//banyuyou防盗注释
}
//banyuyou防盗注释
int main()
{
cout << "---------- - 真值表生成系统----------" << endl;
cout << "请输入命题公式" << endl;
OPND.push('@');//防止空栈调用pop()或top()报错
cin >> s;//输入变元
sum = Divi(s, value);//获取变元数量
vector<vector<int>>zhi(pow(2, sum), vector<int>(sum, 0));
vector<vector<int>>result(pow(2, sum), vector<int>(1, 0));
for (int i = 1; i < pow(2, sum); i++)
{
zhi[i][sum - 1] = zhi[i - 1][sum - 1] + 1;
}
for (int i = pow(2, sum) - 1; i >= 0; i--)
{
for (int j = sum - 1; j > 0; j--)
{
if (zhi[i][j] >= 2)
{
int num = zhi[i][j] / 2;
zhi[i][j - 1] = zhi[i][j - 1] + num;
zhi[i][j] = zhi[i][j] - 2 * num;
}
}
}
change();
for (int an = 0; an < pow(2, sum); an++)//循环,获取不同变元值时命题公式的值
{
int len = transfer.size();
for (int i = 0; i < len; i++)
{
int temp = transfer.front();
transfer.push(temp);
new_tf.push(temp);
transfer.pop();
}
while (!transfer.empty())
{
if (transfer.front() >= 'a' && transfer.front() <= 'z' || transfer.front() >= 'A' && transfer.front() <= 'Z')
{
for (int i = 0; i < sum; i++)
{
if (transfer.front() == value[i])
{
OPTR.push(zhi[an][i]);
transfer.pop();
}
}
}
else if (transfer.front() == '!')
{
fei();
transfer.pop();
}
else if (transfer.front() == '&')
{
yu();
transfer.pop();
}
else if (transfer.front() == '|')
{
huo();
transfer.pop();
}
else if (transfer.front() == '-')
{
tiaojian();
transfer.pop();
}
else if (transfer.front() == '+')
{
Shuangtiaojian();
transfer.pop();
}
}
if (transfer.empty())
{
result[an][0] = OPTR.top();
OPTR.pop();
}
int ntflen = new_tf.size();
for (int i = 0; i < ntflen; i++)//将new_tf值重新填入transfer(因为现在transfer是空的,将公式填入才能进行下一个循环)
{
int temp = new_tf.front();
new_tf.push(temp);
transfer.push(temp);
new_tf.pop();
}
}
for (int i = 0; i < sum; i++)//表头
{
cout << value[i] << " ";//变元
}
cout << s << endl;
for (int i = 0; i < pow(2, sum); i++)//表身
{
for (int j = 0; j < sum; j++)
{
cout << zhi[i][j] << " ";//真值表值
cout << result[i][0] << "\n";
}
return 0;
}