离散数学真值表的计算

大一菜鸡肝了近两个小时的成果,用于计算真值表;
拿来水一篇博客(并不);
代码中比较重要的两部分是原式向后缀式的转换,遍历所有原子命题的可能取值;
具体的细节看代码吧,尽量添加了注释;

#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;
}
原文地址:https://www.cnblogs.com/sdutzxr/p/12457310.html