離散數學真值表的計算


大一菜雞肝了近兩個小時的成果,用於計算真值表;
拿來水一篇博客(並不);
代碼中比較重要的兩部分是原式向后綴式的轉換,遍歷所有原子命題的可能取值;
具體的細節看代碼吧,盡量添加了注釋;

#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\t");
    else printf("F\t");
}

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("計算出現異常!\n");
            }
            else {
                bool f = res.top();
                // printf("text = %d\n",f);
                res.pop();
                res.push(!f);
            }
        }
        else if(Priority(str[i])){
            bool a,b;
            if(res.empty()) printf("計算出現異常!\n");
            else {
                b = res.top();
                res.pop();
            }
            if(res.empty()) printf("計算出現異常!\n");
            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版本。\n");
    printf("使用說明:數據為多組輸入,每組一行,直接輸入命題公式即可。\n");
    printf("注:命題變元必須使用小寫或大寫字母表示。\n");
    printf("聯結詞說明(英文符號): 非:! 合取:& 析取:|(邏輯或) 條件:-(負號) 雙條件:=\n");
}

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("\n請輸入第%d組:\n",++cnt);
    while(~scanf("%s",s)){
        v.clear();
        NumOfVar(n);
        if(ToPostfix()==false){
            printf("您輸入的原式錯誤\n");
        }
        else {
            //標題欄的輸出
            for(int i=1; i<=n; i++){
                printf("%c\t",Vstr[i]);
            }
            printf("%s\n",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("\n");
            }
            printf("\n");
            printf("請輸入第%d組:\n",++cnt);
        }
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM