• 【命题逻辑实验题】求给定命题公式的真值表[C语言程序实现](支持蕴含式的运算)


    实验一 命题逻辑:求给定命题公式的真值表

    实验原理:[可忽略]

    将命题公式A在所有赋值下取值情况列成表,称作A的真值表。
    构造真值表的具体步骤如下:
    (1) 找出公式中所含的全体命题变项p1,p2,…,pn (若无下角标就按字典顺序排列),列出2n个赋值。本课程规定,赋值从00…0开始,然后按二进制加法依次写出各赋值,直到11…1为止。
    (2) 按从低到高的顺序写出公式的各个层次。
    (3) 对应各个赋值计算出各层次的真值,直到最后计算出公式的真值。  实验要求和说明: 本实验要求大家利用编程语言,编写程序,输出给定命题公式(p→q)∧r的真值表。一般我们将公式中的命题变元放在真值表的左边,将公式的结果放在真值表的右边。
    .

    (p→q)∧r的真值表如下:程序预期输出:
    在这里插入图片描述在这里插入图片描述

    预期实现

    • 输入任意表达式能出对应的结果
    • 能对(与 或 非 蕴含 等价 括号)进行运算
    • 能进行优先级处理
    • 能识别多个命题不会重复

    代码实现效果

    将与 或 非 蕴含 等价 括号符号化

    中文逻辑表达代码表达
    析取式|
    合取式&
    非/取反
    蕴含式->
    等值式<->

    输入如上例题的表达式:(p→q)∧r

    则输入(p->q)&r 即可在这里插入图片描述
    复杂输入优先级以及等值式展开测试(完美通过)在这里插入图片描述

    代码分享

    /*-------------------------------------。
    程序名字:离散结构逻辑表达式计算机[增强版] 
    程序作者:CTGU_LLZ
    完成时间:2020/12/4-2020/12/4
    
    函数说明:
    	1.binaryAdder 模拟n位数的0-1循环
    	2.getAns0 格式化好的情况下进行求值[全是基础模拟]
    	3.getAns 去除括号[少量注释讲解] 
    	4.format 讲等价式或者蕴含式展开[注释讲解] 
    	5.printTable 打印表格
    	调用逻辑: 展开 -> 去括号 -> 求值 -> 打印 
    变量说明: 略,英文字面意思 
    代码补充:本代码可以用很多方式优化,例如查找变量可以直接用map去找,存新的变量可以用set直接插入等等 
    --------------------------------------*/
    #include <math.h>
    #include <stdio.h> /*	标准输入输出头文件 */
    #include <string.h>/*	字符串数组的函数定义的头文件	*/
    #define N 500
    void binaryAdder(int b[N], int f) /*二进制赋值加一器*/
    {
        //原理就是二进制相当于写几层for循环
        if (b[f] == 0) //如果本位是0则加一
            b[f] = 1;
        else //否则相当于1+1进位递归判断后面是否进位
        {
            b[f] = 0;
            binaryAdder(b, f + 1);
        }
    }
    //原理类似表达式计算机 参考了模板代码
    int getAns0(char expression[N], char variable[N], int loop[N], int h0) //不带括号版本计算值
    {
        int i, h = 0, j = 0, j1 = 0, j2 = 0, j3 = 0, i1, i2, p1 = -1, p2 = -1, s;
        char dt[N];
        s = strlen(expression);
        if (s == 1)
            if (expression[0] == -2)
                return 0;
            else
                return 1; /*1	就是 expression[0] 的值*/
        else
        {
            for (i = 0; i < s - j; i++) /*	先处理非 */
            {
                if (expression[i] == '!')
                {
                    for (i1 = 0; i1 < h0; i1++)
                        if (expression[i + 1] == variable[i1])
                            p1 = loop[i1];
                    if (expression[i + 1] == -2)
                        p1 = 0;
                    if (p1 == -1)
                        p1 = expression[i + 1];
                    dt[j + 2] = !p1;
                    expression[i] = j + 2;
                    j++;
                    p1 = 0;
                    for (i1 = i + 1; i1 < s - j; i1++)
                        expression[i1] = expression[i1 + 1];
                }
            }
            p1 = -1;
            j1 = j;
            for (i = 0; i < s - j1 - 2 * j2; i++) /*	处理与 */
                if (expression[i] == '&')
                {
                    for (i1 = 0; i1 < h0; i1++)
                    {
                        if (expression[i - 1] == variable[i1])
                            p1 = loop[i1];
                        if (expression[i + 1] == variable[i1])
                            p2 = loop[i1];
                    }
                    for (i2 = 2; i2 < j + 2; i2++)
                    {
                        if (expression[i - 1] == i2)
                            p1 = dt[i2];
                        if (expression[i + 1] == i2)
                            p2 = dt[i2];
                    }
                    if (expression[i - 1] == -2)
                        p1 = 0;
                    if (expression[i + 1] == -2)
                        p2 = 0;
                    if (p1 == -1)
                        p1 = (int)(expression[i - 1]);
                    if (p2 == -1)
                        p2 = (int)(expression[i + 1]);
                    dt[j + 2] = p1 && p2;
                    expression[i - 1] = j + 2;
                    j++;
                    j2++;
                    p1 = -1;
                    p2 = -1;
                    for (i1 = i; i1 < s - j1 - 2 * j2; i1++)
                        expression[i1] = expression[i1 + 2];
                    i = i - 1;
                }
            for (i = 0; i < s - j1 - 2 * j2 - 2 * j3; i++) /*	处理或 */
                if (expression[i] == '|')
                {
                    for (i1 = 0; i1 < h0; i1++)
                    {
                        if (expression[i - 1] == variable[i1])
                            p1 = loop[i1];
                        if (expression[i + 1] == variable[i1])
                            p2 = loop[i1];
                    }
                    for (i2 = 2; i2 < j + 2; i2++)
                    {
                        if (expression[i - 1] == i2)
                            p1 = dt[i2];
                        if (expression[i + 1] == i2)
                            p2 = dt[i2];
                    }
                    if (expression[i - 1] == -2)
                        p1 = 0;
                    if (expression[i + 1] == -2)
                        p2 = 0;
                    if (p1 == -1)
                        p1 = expression[i - 1];
                    if (p2 == -1)
                        p2 = expression[i + 1];
                    dt[j + 2] = p1 || p2;
                    expression[i - 1] = j + 2;
                    j++;
                    j3++;
                    p1 = -1;
                    p2 = -1;
                    for (i1 = i; i1 < s - j1 - 2 * j2 - 2 * j3; i1++)
                        expression[i1] = expression[i1 + 2];
                    i--;
                }
            return dt[j + 1];
        }
    }
    int getAns(char expression[N], char variable[N], int loop[N], int h0) //去括号
    {
        int i, j, k, slen, bracketsNum = 0, bracketsIndex[N], flag; /*bracketsIdex 用来保存括号位置 */
        char charStore[N], brackets[N];                             /*charStore	用来保存括号内的字符	brackets 用来保存括号 */
        slen = strlen(expression);
        for (i = 0; i < slen; i++)
        {
            if (expression[i] == '(' || expression[i] == ')')
            {
                bracketsIndex[bracketsNum] = i;
                brackets[bracketsNum] = expression[i];
                bracketsNum++;
            }
        }
        if (bracketsNum == 0)
            return getAns0(expression, variable, loop, h0);
        else
        {
            for (i = 0; i < bracketsNum; i++) //找到第一个右括号
                if (brackets[i] == ')')
                    break;
            for (j = bracketsIndex[i - 1] + 1, k = 0; j < bracketsIndex[i]; j++, k++) //储存这层括号内表达式
                charStore[k] = expression[j];
            charStore[k] = '';
    
            flag = getAns0(charStore, variable, loop, h0);
            if (flag == 1)
                expression[bracketsIndex[i - 1]] = 1;
            else
                expression[bracketsIndex[i - 1]] = -2;
            for (j = bracketsIndex[i - 1] + 1; j < slen + bracketsIndex[i - 1] - bracketsIndex[i]; j++) //去括号
                expression[j] = expression[j + bracketsIndex[i] - bracketsIndex[i - 1]];
            expression[j] = '';
            return getAns(expression, variable, loop, h0);
        }
    }
    
    void format(char expression[N]) //格式化蕴含式和等价式展开,方便求值 
    {             
        while (1) //从左往右的优先级
        {
            int flag = 1;                                    //有没有 -> 或者 <->
            char left[N], midLeft[N], midRight[N], right[N]; //左边部分右边部分和 -> 符号分开的两个部分
            int slen = strlen(expression);
            for (int i = 0; i < slen; i++)
            {
                if (expression[i] == '-' && expression[i + 1] == '>')
                { //处理蕴含式 q&(p->r)|y 后面用这个举例
                    //蕴含式优先级最低,要考虑有无括号情况
                    flag = 0;
                    int li = i - 1, bracketsNum = 0;
                    //往左边扫
                    //匹配到左括号+1,右括号-1
                    while (li >= 0) //有单独的左括号表示q|(q->r)蕴含式优先级杯括号提高了单独处理
                    {
                        if (expression[li] == ')')
                            bracketsNum--;
                        else if (expression[li] == '(')
                            bracketsNum++;
                        if (bracketsNum > 0)
                            break;
                        li--;
                    }
                    if (bracketsNum > 0) //有多余左括号
                    {
                        int j = 0, tempi = li + 1;
                        for (tempi; tempi < i; tempi++)
                        { //把p存起来
                            midLeft[j++] = expression[tempi];
                        }
                        midLeft[j] = '';
                        for (tempi = 0; tempi <= li; tempi++)
                        { //把q存起来
                            left[tempi] = expression[tempi];
                        }
                        left[tempi] = '';
                    }
                    else
                    {
                        int tempi;
                        left[0] = '';
                        for (tempi = 0; tempi < i; tempi++)
                        { //把q存起来
                            midLeft[tempi] = expression[tempi];
                        }
                        midLeft[tempi] = '';
                    }
                    li = i + 2, bracketsNum = 0;
                    //往右边扫
                    //匹配到左括号+1,右括号-1
                    while (li < slen && expression[li] != '-' && expression[li] != '<') //和上面原理相反
                    {
                        if (expression[li] == ')')
                            bracketsNum--;
                        else if (expression[li] == '(')
                            bracketsNum++;
                        if (bracketsNum < 0)
                            break;
                        li++;
                    }
                    if (bracketsNum < 0 || expression[li] == '-' || expression[li] == '<') //有多余又括号
                    {
                        int j = 0, tempi;
                        for (tempi = i + 2; tempi < li; tempi++)
                        { //把p存起来
                            midRight[j++] = expression[tempi];
                        }
                        midRight[j] = '';
                        j = 0;
                        for (tempi = li; tempi < slen; tempi++)
                        { //把q存起来
                            right[j++] = expression[tempi];
                        }
                        right[j] = '';
                    }
                    else
                    {
                        int tempi;
                        right[0] = '';
                        int j = 0;
                        for (tempi = i + 2; tempi < slen; tempi++)
                        { //把q存起来
                            midRight[j++] = expression[tempi];
                        }
                        midRight[j] = '';
                    }
                    //开始拼接新的expression
                    //r&q->p|a  --> (!(r&q)v())
                    expression[0] = '';
                    strcat(expression, left);
                    strcat(expression, "(!");
                    if (strlen(midLeft) > 1)
                        strcat(expression, "(");
                    strcat(expression, midLeft);
                    if (strlen(midLeft) > 1)
                        strcat(expression, ")");
                    strcat(expression, "|");
                    if (strlen(midRight) > 1)
                        strcat(expression, "(");
                    strcat(expression, midRight);
                    if (strlen(midRight) > 1)
                        strcat(expression, ")");
                    strcat(expression, ")");
                    strcat(expression, right);
                    break;
                }
                else if (i + 2 < slen && expression[i] == '<' && expression[i + 1] == '-' && expression[i + 2] == '>')
                { //处理等价式
                    flag = 0;
                    int li = i - 1, bracketsNum = 0;
                    //和上面同理,只是长度变成了3个 <->
                    while (li >= 0)
                    {
                        if (expression[li] == ')')
                            bracketsNum--;
                        else if (expression[li] == '(')
                            bracketsNum++;
                        if (bracketsNum > 0)
                            break;
                        li--;
                    }
                    if (bracketsNum > 0) //有多余左括号
                    {
                        int j = 0, tempi = li + 1;
                        for (tempi; tempi < i; tempi++)
                        { //把p存起来
                            midLeft[j++] = expression[tempi];
                        }
                        midLeft[j] = '';
                        for (tempi = 0; tempi <= li; tempi++)
                        { //把q存起来
                            left[tempi] = expression[tempi];
                        }
                        left[tempi] = '';
                    }
                    else
                    {
                        int tempi;
                        left[0] = '';
                        for (tempi = 0; tempi < i; tempi++)
                        { //把q存起来
                            midLeft[tempi] = expression[tempi];
                        }
                        midLeft[tempi] = '';
                    }
                    li = i + 2, bracketsNum = 0;
                    //往右边扫
                    //匹配到左括号+1,右括号-1
                    while (li < slen && expression[li] != '-' && expression[li] != '<') //和上面原理相反
                    {
                        if (expression[li] == ')')
                            bracketsNum--;
                        else if (expression[li] == '(')
                            bracketsNum++;
                        if (bracketsNum < 0)
                            break;
                        li++;
                    }
                    if (bracketsNum < 0 || expression[li] == '-' || expression[li] == '<') //有多余又括号
                    {
                        int j = 0, tempi;
                        for (tempi = i + 3; tempi < li; tempi++)
                        { //把p存起来
                            midRight[j++] = expression[tempi];
                        }
                        midRight[j] = '';
                        j = 0;
                        for (tempi = li; tempi < slen; tempi++)
                        { //把q存起来
                            right[j++] = expression[tempi];
                        }
                        right[j] = '';
                    }
                    else
                    {
                        int tempi;
                        right[0] = '';
                        int j = 0;
                        for (tempi = i + 3; tempi < slen; tempi++)
                        { //把q存起来
                            midRight[j++] = expression[tempi];
                        }
                        midRight[j] = '';
                    }
                    expression[0] = '';
                    strcat(expression, left);
                    strcat(expression, "((!");
                    if (strlen(midLeft) > 1)
                        strcat(expression, "(");
                    strcat(expression, midLeft);
                    if (strlen(midLeft) > 1)
                        strcat(expression, ")");
                    strcat(expression, "|");
                    if (strlen(midRight) > 1)
                        strcat(expression, "(");
                    strcat(expression, midRight);
                    if (strlen(midRight) > 1)
                        strcat(expression, ")");
                    strcat(expression, ")&");
                    strcat(expression, "(!");
                    if (strlen(midRight) > 1)
                        strcat(expression, "(");
                    strcat(expression, midRight);
                    if (strlen(midRight) > 1)
                        strcat(expression, ")");
                    strcat(expression, "|");
                    if (strlen(midLeft) > 1)
                        strcat(expression, "(");
                    strcat(expression, midLeft);
                    if (strlen(midLeft) > 1)
                        strcat(expression, ")");
                    strcat(expression, "))");
                    strcat(expression, right);
                    break;
                }
            }
            //printf("%s
    ", expression);
            if (flag)
                break; //没有蕴含式或者等价式退出
        }
    }
    
    void printTable() /*	功能 BC*/
    {
        int i1, i2, loop[N], bracketsNum = 0, ans, variableNum = 0;
        char expression[N], oldexpression[N], variable[N], expressionTemp[N];
        printf("【请输入一个合法的命题公式】
    ");
        printf("|基本析取:q|p            |
    ");
        printf("|基本合取: q&p            |
    ");
        printf("|可包含蕴含式 : q->r      |
    ");
        printf("|可包含等价式 : q<->r     |
    ");
        printf("|可包含否和括号: p|(!q|r) |
    ");
        printf("|
    |
    |:");
        scanf("%s", expression);
        strcpy(oldexpression, expression);
        format(expression); //将主析取范式转换为标准式
        strcpy(expressionTemp, expression);
        for (i1 = 0; i1 < strlen(expression); i1++)
        {
            if (expression[i1] == ')' || expression[i1] == '(')
                bracketsNum++;
            if (expression[i1] >= 'a' && expression[i1] <= 'z' || expression[i1] >= 'A' && expression[i1] <= 'Z')
            {
                for (i2 = 0; i2 < variableNum; i2++) /*	判断并储存变量 */
                    if (variable[i2] == expression[i1])
                        break;
                if (i2 == variableNum) //自然退出循环说明变量之前还没有过就存下
                {
                    variable[variableNum] = expression[i1];
                    variableNum++;
                }
            }
        }
        printf("总变量个数为:	%d
    ", variableNum);
        variableNum;
        printf("输出真值表如下: 
    ");
        //打印表头的信息
        for (i1 = 0; i1 < variableNum; i1++)
            printf(" %c ", variable[i1]);
        printf("[%s] ==> ", oldexpression);
        printf("[%s] ", expression);
        printf("
    ");
        for (i1 = 0; i1 < variableNum; i1++) /*	先将所有的变量赋值为零	*/
            loop[i1] = 0;
        //打印表格主体的信息
        for (i1 = 0; i1 < (int)pow(2, variableNum); i1++) //打印2^n次方行情况
        {
            if (i1 != 0)              //0的时候不需要加一
                binaryAdder(loop, 0); //n位二进制递归加法器:000 -> 100 -> 010 -> 110类似
            ans = getAns(expression, variable, loop, variableNum);
            strcpy(expression, expressionTemp);  //恢复被修改的数组
            for (i2 = 0; i2 < variableNum; i2++) //将每行的变量真值打印出来
                printf(" %d ", loop[i2]);
            for (int formati = 0; formati < strlen(oldexpression) + 5; formati++)
                printf("-");
            printf("> ");
            for (int formati = 0; formati < strlen(oldexpression); formati++)
                printf(" ");
            printf("%d
    ", ans);
        }
        getchar(); 
        getchar();
    }
    
    int main()
    {
        do
        {
            printTable();
        } while (1);
    }
    
    

    最后就完成了,代码如上,欢迎学习与参考

  • 相关阅读:
    linux uniq 命令实用手册
    linux sort 命令实用手册
    linux awk 命令实用手册
    如何高效使用vim
    15个有趣好玩的linux shell 命令
    一篇文章带你编写10种语言HelloWorld
    如何用hugo 搭建博客
    c++中的exit()
    枚举数据类型C++
    常见的字符测试函数
  • 原文地址:https://www.cnblogs.com/404name/p/14634081.html
Copyright © 2020-2023  润新知