这是一款针对 p、q、r 三个变元的二元真值(0 假、1 真)命题逻辑工具,核心实现中缀公式转后缀、真值计算、真值表生成及主析取 / 合取式输出,下面从功能和应用两方面精简解析。


核心功能:中缀命题公式转后缀、生成真值表、输出主析取 / 合取式;
实现核心:栈结构处理表达式与真值计算,三层循环遍历变元真值组合;
核心应用:逻辑学习、离散数学实验、简单数字电路设计辅助。


一、核心功能实现


整体流程:输入中缀命题公式→转后缀表达式→真值计算与真值表生成→输出两种范式,各模块分工明确。


1. 前期准备


全局变量:Array_one/Array_two存储主析取 / 合取式对应的变元真值组合,Counter_one/Counter_two记录组合数量;Stack(操作符栈)、Num(真值栈)支撑表达式转换与计算;save存储后缀表达式,s存储输入的中缀公式。
函数分工:涵盖优先级比较、表达式转换、5 种逻辑运算、真值计算、范式输出,支撑全流程执行。


2. 中缀转后缀表达式(Transform函数)


将人类易输入的中缀公式(如p&!q>r)转为计算机易计算的后缀表达式(逆波兰式,如pq!&r>):
字母(p/q/r)直接存入save;
操作符 / 括号:栈空直接入栈,非右括号操作符直接入栈,右括号则弹出栈顶操作符至save,直到遇到左括号(最后弹出左括号不存入);
遍历结束后,将栈内剩余操作符全部弹出存入save,完成转换。


3. 操作符优先级比较(Amp函数)


为表达式转换提供优先级依据,从高到低:((5) > !(非,4) > &(与,3) > |(或,2) > >(条件,1) > $(双条件,0) > )(-1),符合命题逻辑运算规则。


4. 真值计算与真值表生成(Truenum函数)


三层循环遍历 p、q、r 的 8 种真值组合(2³=8);
遍历后缀表达式:字母对应变元真值压入Num栈,操作符调用对应运算函数;
输出当前变元真值与公式结果,生成真值表;
分类存储:公式结果为 1 存入Array_one(主析取式备用),为 0 存入Array_two(主合取式备用),最后清空真值栈。


5. 五种逻辑运算实现


非运算(fei):弹出栈顶真值取反,结果压栈;
与运算(yu):弹出两个真值执行逻辑与,结果压栈;
或运算(huo):弹出两个真值执行逻辑或,结果压栈;
条件运算(tiaojian):蕴含关系,仅前件 1、后件 0 时结果为 0,其余为 1;
双条件运算(Shuangtiaojian):等价关系,两真值相等时结果为 1,否则为 0。


6. 主析取 / 合取式输出


主析取式(Output_xiqu):所有使公式为真的极小项析取(|)组合,真值 1 保留原变元、0 取非,变元间用 & 连接,极小项间用 | 连接;
主合取式(Output_hequ):所有使公式为假的极大项合取(&)组合,真值 0 保留原变元、1 取非,变元间用 | 连接,极大项间用 & 连接。


7. 主函数调度


程序入口,依次完成:输出系统提示→接收用户输入→中缀转后缀→生成真值表→输出主合取式与主析取式→程序退出。


二、应用场景


逻辑学学习辅助:帮助初学者理解命题公式真值规律、表达式转换及范式含义,验证手动计算结果的正确性。
命题逻辑问题求解:验证命题公式等价性,判定公式类型(重言式、矛盾式、可满足式)。
数字电路设计辅助:对应门电路逻辑,生成真值表并简化逻辑表达式,辅助组合逻辑电路设计。
离散数学实验参考:直接完成真值表、范式转换类实验,也可作为栈、逻辑运算编程实现的参考案例。


三、注意事项


仅支持 p、q、r 三个变元,仅支持二元真值(0/1),非真正 “三元逻辑”;
中缀转后缀函数存在瑕疵,复杂表达式可能转换错误;
输入公式需符合语法规范,括号需成对,无非法字符。

#include<iostream>
#include<cctype>
#include<set>
#include<string>
#include<stack>
using namespace std;

#define Max 1000
int Array_one[Max][3] = { 0 }, Array_two[Max][3] = { 0 }, Counter_one = 0, Counter_two = 0; // 储存各个变元的真值,计数器
string s; // 储存命题公式
stack<char> Stack; // 操作符栈
stack<int> Num; // 真值栈
char save[Max], c; // 后缀表达式及临时字符
int follow = 0; // 计数器
int p, q, r; // 储存真值

int Amp(char a); // 操作符优先级比较函数
void Transform(); // 中缀表达式转后缀表达式
void fei(); // 非运算
void yu(); // 与运算
void huo(); // 或运算
void tiaojian(); // 条件运算
void Shuangtiaojian(); // 双条件运算
void Truenum(); // 真值运算
void Output_xiqu(); // 输出主析取式
void Output_hequ(); // 输出主合取式

int main() {
    cout << "------------------------------------------------欢迎您进入三元逻辑运算系统---------------------------------------------" << endl;
    cout << "变元为p,q,r" << endl;
    cout << "! 非运算,& 与运算,| 或运算,> 条件运算,$ 双条件运算,( 左括号,) 右括号" << endl;
    cout << "请输入命题公式!" << endl;
    cin >> s;

    Transform();
    cout << "\t\t\t**真值表**" << endl;
    cout << "p\t\t" << "q\t\t" << "r\t\t" << s << endl;
    Truenum();
    Output_hequ();  // 输出主合取式
    Output_xiqu();  // 输出主析取式
    cout << endl;

    return 0;
}

int Amp(char a) {
    switch (a) {
        case '(': return 5; break;
        case '!': return 4; break;
        case '&': return 3; break;
        case '|': return 2; break;
        case '>': return 1; break;
        case '$': return 0; break;
        case ')': return -1; break;
    }
}

void Transform() {
    for (int i = 0; i < s.length(); i++) {  // 遍历命题公式
        c = s[i];  // 临时储存字符
        if (isalpha(c))  // 如果为字母, 后缀表达式直接储存
            save[follow++] = c;
        if (c == '!' || c == '&' || c == '|' || c == '>' || c == '$' || c == '(' || c == ')') { // 操作符处理
            if (Stack.empty()) Stack.push(c);  // 栈为空,直接压入
            else if (c != ')') Stack.push(c);  // 遇到操作符直接入栈
            else if (c == ')') {  // 右括号处理
                while (!Stack.empty() && Amp(Stack.top()) > Amp(c)) {  // 优先级大于当前的操作符
                    if (Stack.top() == '(') break;  // 如果是左括号,则退出
                    save[follow++] = Stack.top();  // 存储栈顶操作符
                    Stack.pop();  // 弹出栈顶操作符
                }
                if (Stack.top() == '(') Stack.pop();  // 弹出左括号
            }
        }
    }
    while (!Stack.empty()) {  // 将剩余操作符处理完
        save[follow++] = Stack.top();
        Stack.pop();
    }
}

void Truenum() {
    for (p = 0; p <= 1; p++) {
        for (q = 0; q <= 1; q++) {
            for (r = 0; r <= 1; r++) {
                cout << p << "\t\t" << q << "\t\t" << r << "\t\t";
                for (int i = 0; i < follow; i++) {
                    c = save[i];  // 临时存储字符
                    if (isalpha(c)) {  // 变元时处理真值
                        switch (c) {
                            case 'p': Num.push(p); break;
                            case 'q': Num.push(q); break;
                            case 'r': Num.push(r); break;
                        }
                    }
                    else if (c == '!') fei();  // 非运算
                    else if (c == '&') yu();  // 与运算
                    else if (c == '|') huo();  // 或运算
                    else if (c == '>') tiaojian();  // 条件运算
                    else if (c == '$') Shuangtiaojian();  // 双条件运算
                }
                cout << Num.top() << endl;
                if (Num.top() == 1) {  // 判断主析取式
                    Array_one[Counter_one][0] = p;
                    Array_one[Counter_one][1] = q;
                    Array_one[Counter_one++][2] = r;
                }
                else {  // 判断主合取式
                    Array_two[Counter_two][0] = p;
                    Array_two[Counter_two][1] = q;
                    Array_two[Counter_two++][2] = r;
                }
                Num.pop();
            }
        }
    }
}

void Output_xiqu() {
    cout << "主析取式" << endl;
    for (int i = 0; i < Counter_one; i++) {
        cout << "(";
        if (Array_one[i][0] == 0) cout << "(!p)";
        else cout << "p";
        if (Array_one[i][1] == 0) cout << "&(!q)";
        else cout << "&q";
        if (Array_one[i][2] == 0) cout << "&(!r)";
        else cout << "&r";
        if (i == Counter_one - 1) cout << ")";
        else cout << ")|";
    }
    cout << endl;
}

void Output_hequ() {
    cout << "主合取式" << endl;
    for (int i = 0; i < Counter_two; i++) {
        cout << "(";
        if (Array_two[i][0] == 0) cout << "p";
        else cout << "(!p)";
        if (Array_two[i][1] == 0) cout << "|q";
        else cout << "|(!q)";
        if (Array_two[i][2] == 0) cout << "|r";
        else cout << "|(!r)";
        if (i == Counter_two - 1) cout << ")";
        else cout << ")&";
    }
    cout << endl;
}

void fei() {
    int True = !Num.top(); Num.pop();  // 弹出一个真值, 进行非运算
    Num.push(True);  // 操作结果压栈
}

void yu() {
    int True_one = Num.top(); Num.pop();
    int True_two = Num.top(); Num.pop();
    int True = True_one && True_two;
    Num.push(True);  // 操作结果压栈
}

void huo() {
    int True_one = Num.top(); Num.pop();
    int True_two = Num.top(); Num.pop();
    int True = True_one || True_two;
    Num.push(True);  // 操作结果压栈
}

void tiaojian() {
    int True_one = Num.top(); Num.pop();
    int True_two = Num.top(); Num.pop();
    int True;
    if (True_one == 0 && True_two == 1) True = 0;
    else True = 1;
    Num.push(True);  // 操作结果压栈
}

void Shuangtiaojian() {
    int True_one = Num.top(); Num.pop();
    int True_two = Num.top(); Num.pop();
    int True;
    if (True_one == True_two) True = 1;
    else True = 0;
   Num.push(True);
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐