题目要求
给定任意一个命题公式的真值表,并根据真值表求主范式。
算法思想
- 将逻辑表达式转换为后缀表达式,然后套用逆波兰表达式的求值方法
- 利用位运算,找出一个十进制整数对应二进制的每一位,给命题变项赋值
- 记录下成真赋值以及成假赋值,最后输出
代码
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <cmath>
#include <iomanip>
using namespace std;
/**
* 用new_value替换src字符串中的old_value
* @param src
* @param old_value
* @param new_value
*/
void replace(string &src, const string &old_value, const string &new_value);
/**
* 获取一个整数二进制的某一位
* @param num
* @param bit 位数
* @return
*/
int valueAtBit(int num, int bit);
/**
* 计算给定真值及联结词的真值
* @param p 命题变项p的赋值
* @param q 命题变项q的赋值
* @param model 联结词
* @return 运算的真值
*/
int value(char p, char q, char op);
/**
* 根据给定的表达式求取命题变项的个数
* @param p_var 用于存放命题变项
* @param ex 表达式
*/
void get_p_var(vector<char> &p_var, const string &ex);
/**
* Infix expression is regarded as suffix expression
* @param midExpression the mid expression
* @return the suffix expression
*/
string midToSuf(const string &midExpression);
/**
* Calculate the suffix expression with stack and record the value
* @param suf suf expression
* @param p_var
* @param result real value set
* @param assigment
*/
void calculate(const string &suf, vector<char> &p_var, vector<char> &result, vector<char> &t_assigment, vector<char> &f_assigment);
/**
* 由后缀表达式计算
* @param str
* @return value
*/
int getValue(const string &str);
void setOut(vector<char> var, vector<char> result, vector<char> t_assigment, vector<char> f_assignment);
/**
* 整数转二进制串
* @param i
* @param size
* @return
*/
string intToStr(int i, int size);
int main() {
// 读入需要求的表达式
string ex;
string suf_ex; // Suffix expression corresponding to infix expression
// 记录命题变项
vector<char> p_var;
vector<char> result; // alphaStack propositional variables stack
vector<char> t_assignment; // True assignment
vector<char> f_assignment;
string t_str, f_str;
cout << "please input expression:(!:否定(括号外的否定需化入括号内) &:合取 |:析取 >:蕴涵 =:等价)";
cin >> ex;
// Analytic expression, determine the number of propositional variables
get_p_var(p_var, ex);
// Infix expression is regarded as suffix expression
suf_ex = midToSuf(ex);
// Calculate the suffix expression and record the value
calculate(suf_ex, p_var, result, t_assignment, f_assignment);
setOut(p_var, result, t_assignment, f_assignment);
return 0;
}
void setOut(vector<char> var, vector<char> result, vector<char> t_assigment, vector<char> f_assignment) {
cout << "真值表如下:" << endl;
int size = var.size();
int k = pow(2, size);
for (int i = 0; i < size; ++i) {
cout << setiosflags(ios::left) << setfill(' ') << setw(2) << var[i];
}
cout << endl;
string value;
string t;
for (int j = 0; j < k; ++j) {
value = intToStr(j, size);
for (int i = 0; i < size; ++i) {
cout << setiosflags(ios::left) << setfill(' ') << setw(2) << value[i];
}
t = to_string(result[j]);
cout << " " << t << endl;
}
cout << "主析取范式:" << endl;
int length = t_assigment.size();
for (int l = 0; l < length; ++l) {
t = to_string(t_assigment[l]);
t.insert(0, 1, 'm');
if (l + 1 != length) {
t.append(1, '|');
}
cout << t;
}
cout << endl;
cout << "主合取范式:" << endl;
t.clear();
length = f_assignment.size();
for (int l = 0; l < length; ++l) {
t = to_string(f_assignment[l]);
t.insert(0, 1, 'M');
if (l + 1 != length) {
t.append(1, '&');
}
cout << t;
}
}
int value(char p, char q, char op) {
int val = 0;
if (!isdigit(p) || !isdigit(q)) {
throw "输入不合法";
}
bool p_v = p != '0';
bool q_v = q != '0';
switch (op) {
case '=':
val = p_v == q_v;
break;
case '>':
val = p_v ? q_v ? 1 : 0 : 1;
break;
case '|':
val = q_v || p_v;
break;
case '&':
val = p_v && q_v;
break;
default:
break;
}
return val;
}
void get_p_var(vector<char> &p_var, const string &ex) {
bool exists = false;
int length = ex.length();
for (int i = 0; i < length; ++i) {
exists = false;
// if ex[i] is not a alpha, then continue.
if (!isalpha(ex[i])) {
continue;
}
for (char j : p_var) {
// 如果当前命题变项已经存放,则直接跳过当前字符
if (ex[i] == j) {
exists = true;
break;
}
}
if (!exists) {
p_var.push_back(ex[i]);
}
}
}
bool isOperator(char ch) {
return ch == '|' || ch == '&' || ch == '>' || ch == '=' || ch == '(' || ch == ')';
// 否则返回false
}
int getPriority(char ch) {
int level = 0; // 优先级
switch (ch) {
case '(':
level = 1;
break;
case '=':
level = 2;
break;
case '>':
level = 3;
break;
case '|':
level = 4;
break;
case '&':
level = 5;
break;
case ')':
level = 6;
break;
default:
break;
}
return level;
}
string midToSuf(const string &midExpression) {
string str;
int length = midExpression.length();
stack<char> op;
char top = ' ';
for (int i = 0; i < length; ++i) {
char ca = midExpression[i];
if (isalpha(ca) || isdigit(ca) || ca == '!') { // 如果是数字
if (ca == '!') {
str.append(1, ca);
str.append(1, midExpression[++i]);
continue;
} else {
str.append(1, ca);
}
} else if (isOperator(ca)) {// 操作符
if (!op.empty()) {
top = op.top();
}
if (op.empty() || ca == '(' || getPriority(top) < getPriority(ca)) {
op.push(ca);
if (ca == ')') {
while (true) {
top = op.top();
op.pop();
if (top == '(') {
break;
} else {
if (top == ')') {
continue;
}
str.append(1, top);
}
}
}
} else {
top = op.top();
op.pop();
op.push(ca);
str.append(1, top);
}
} else {
throw "expression is error";
}
}
// 第二个while结束
while (!op.empty()) {
top = op.top();
op.pop();
str.append(1, top);
}
return str;
}
void calculate(const string &suf, vector<char> &p_var, vector<char> &result, vector<char> &t_assigment, vector<char> &f_assigment) {
int size = p_var.size();
int k = pow(2, size);
string oldStr;
string newStr;
string temp;
string t_value;
for (int i = 0; i < k; ++i) {
temp = suf;
// 赋值
t_value = intToStr(i, size);
for (int j = 0; j < size; ++j) {
newStr.append(1, t_value[size - 1 - j]);
oldStr.append(1, p_var[size - 1 - j]);
replace(temp, oldStr, newStr);
newStr.clear();
oldStr.clear();
}
int length = temp.length();
for (int l = 0; l < length; ++l) {
if (temp[l] == '!') {
char t = temp[++l];
int v = t - '0';
v = !v;
temp.replace( l , 1, to_string(v));
}
}
replace(temp,"!","");
int v = getValue(temp);
if (v != 0) {
t_assigment.push_back(i);
} else {
f_assigment.push_back(i);
}
result.push_back(v);
}
}
string intToStr(int i, int size) {
string str;
for (int j = 0; j < size; ++j) {
int r = valueAtBit(i, j + 1);
str.append(1, r + '0');
}
reverse(str.begin(), str.end());
return str;
}
int getValue(const string &str) {
stack<char> num;
int size = str.size();
for (int i = 0; i < size; ++i) {
char t = str[i];
if (isdigit(t)) {
num.push(t);
} else {
char c1 = num.top();
num.pop();
char c2 = num.top();
num.pop();
int v = value(c2, c1, t);
num.push(v + '0');
}
}
return num.top() - '0';
}
int valueAtBit(int num, int bit) {
return (num >> (bit - 1)) & 1;
}
void replace(string &src, const string &old_value, const string &new_value) {
// 每次重新定位起始位置,防止上轮替换后的字符串形成新的old_value
for (string::size_type pos(0); pos != string::npos; pos += new_value.length()) {
if ((pos = src.find(old_value, pos)) != string::npos) {
src.replace(pos, old_value.length(), new_value);
} else break;
}
}
总结
我这代码写的太low了
有时间再对这个代码进行优化