大一菜鸡肝了近两个小时的成果,用于计算真值表;
拿来水一篇博客(并不);
代码中比较重要的两部分是原式向后缀式的转换,遍历所有原子命题的可能取值;
具体的细节看代码吧,尽量添加了注释;
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int maxstr = 1e5 + 10;
char s[maxstr],str[maxstr],Vstr[maxn];//依次为原式,后缀式,存放原子命题的符号
bool var[maxn];//不同原子命题的真值
map<char,int>v;//储存原子命题对应的编号
void Print_true(bool b){//打印bool对应的真值符号
if(b) printf("T ");
else printf("F ");
}
int Priority(char c){//返回运算符的优先级
int p;
switch (c) {
case '!': p = 5; break;
case '&': p = 4; break;
case '|': p = 3; break;
case '-': p = 2; break;
case '=': p = 1; break;
default : p = 0; break;
}
return p;
}
bool ToPostfix(){//原式转化为后缀表达式
int cnt = 0;
int len = strlen(s);
stack<char>ope;
for(int i=0; i<len; i++){
if(s[i] == '('){
ope.push(s[i]);
}
else if(s[i] == ')'){
if(ope.empty()) return false;
while(ope.top() != '('){
str[cnt++] = ope.top();
ope.pop();
if(ope.empty()) return false;
}
ope.pop();
}
else if(Priority(s[i]) == 0){
str[cnt++] = s[i];
}
else {
if(ope.empty()){
ope.push(s[i]);
}
else {
if(Priority(s[i]) > Priority(ope.top())){
ope.push(s[i]);
}
else{
while(!ope.empty() && ope.top() != '(' && Priority(s[i]) <= Priority(ope.top())) {
str[cnt++] = ope.top();
ope.pop();
}
ope.push(s[i]);
}
}
}
}
while(!ope.empty()){
str[cnt++] = ope.top();
ope.pop();
}
str[cnt] = 0;
return true;
}
bool Calculate(bool a, bool b, char ope){//进行真值的运算
bool ans;
if(ope == '&'){
if(a == true && b == true) ans = true;
else ans = false;
}
else if(ope == '|'){
if(a == true || b == true) ans = true;
else ans = false;
}
else if(ope == '-'){
if(a == true && b == false) ans = false;
else ans = true;
}
else if(ope == '='){
if(a == b) ans = true;
else ans = false;
}
return ans;
}
void init_var(int n, int sum){//对var数组初始化
while(sum>0){
bool x = sum%2;
var[n--] = x;
sum /= 2;
}
do{
var[n--] = false;
}while(n > 0);
}
bool Result(){//对后缀式进行计算
stack<bool>res;
int len = strlen(str);
for(int i=0; i<len; i++){
if(str[i] == '!'){
if(res.empty()){
printf("计算出现异常!
");
}
else {
bool f = res.top();
// printf("text = %d
",f);
res.pop();
res.push(!f);
}
}
else if(Priority(str[i])){
bool a,b;
if(res.empty()) printf("计算出现异常!
");
else {
b = res.top();
res.pop();
}
if(res.empty()) printf("计算出现异常!
");
else {
a = res.top();
res.pop();
}
bool ans = Calculate(a, b, str[i]);
res.push(ans);
}
else {
res.push(var[v[str[i]]]);
}
}
return res.top();
}
void Print_Out(){//打印提示语
printf("您好,欢迎使用离散数学真值表计算V1.2版本。
");
printf("使用说明:数据为多组输入,每组一行,直接输入命题公式即可。
");
printf("注:命题变元必须使用小写或大写字母表示。
");
printf("联结词说明(英文符号): 非:! 合取:& 析取:|(逻辑或) 条件:-(负号) 双条件:=
");
}
void NumOfVar(int &n){//提取命题公式中的变元
int len = strlen(s);
bool asi[200];
memset(asi, false, sizeof(asi));
for(int i=0; i<len; i++){
asi[s[i]] = true;
}
n = 0;
for(int i='A'; i<='Z'; i++){
if(asi[i]){
Vstr[++n] = i;
v[i] = n;
}
}
for(int i='a'; i<='z'; i++){
if(asi[i]){
Vstr[++n] = i;
v[i] = n;
}
}
}
int main(){
int n,cnt=0;
Print_Out();
printf("
请输入第%d组:
",++cnt);
while(~scanf("%s",s)){
v.clear();
NumOfVar(n);
if(ToPostfix()==false){
printf("您输入的原式错误
");
}
else {
//标题栏的输出
for(int i=1; i<=n; i++){
printf("%c ",Vstr[i]);
}
printf("%s
",s);
//打印各部分真值
int m = pow(2,n);
for(int i=0; i<m; i++){
init_var(n, i);
for(int j=1; j<=n; j++){
Print_true(var[j]);
}
bool ans = Result();
Print_true(ans);
printf("
");
}
printf("
");
printf("请输入第%d组:
",++cnt);
}
}
return 0;
}