问题 G: 真值表(Ⅱ)

问题 G: 真值表(Ⅱ)

题目描述
第二阶段的任务是给定一个逻辑表达式,生成真值表。

输入
同子任务一。

输出
对于每一个逻辑表达式,输出其对应的真值表即可。相对于任务一,输出的最右边增加了一列,包含了表达式和它的各个值。具体见样例。

样例输入
p
p->q
p||q

样例输出
p p
1 1
0 0
p q p->q
1 1 1
1 0 0
0 1 1
0 0 1
p q p||q
1 1 1
1 0 1
0 1 1
0 0 0

计算过程

真值表是使用于逻辑中(特别是在连结逻辑代数、布尔函数和命题逻辑上)的一类数学用表,用来计算逻辑表示式在每种论证(即每种逻辑变数取值的组合)上的值。尤其是,真值表可以用来判断一个命题表示式是否对所有允许的输入值皆为真,亦即是否为逻辑有效的。

真值表被用来计算以“决策程序”建构的命题表示式的值。命题表示式可以是一个原子公式(命题常数、命题变数或命题函数,如Px或P(x)),或以逻辑算子(如逻辑与( ∧ {\displaystyle \land }
)、逻辑或( ∨ {\displaystyle \lor })、逻辑非( ¬ {\displaystyle \lnot }))由原子公式建构出来的公式。举例来说, F x ∧ G x {\displaystyle Fx\land Gx}即是个命题表示式。

真值表中的列标题展示了 (i)命题函数与/或变量,和 (ii)建造自这些命题函数或变量和运算符的真值泛函表达式。行展示对 (i)和 (ii)的T或F指派的每个可能的求值。换句话说,每行都是对 (i)和 (ii)的不同解释。

经典(就是说二值)逻辑的真值表限定于只有两个真值是可能的布尔逻辑系统,它们是“真”或“假”,通常在表中简单的表示为T和F。

因题干表述中要求比上一题的输出多出一列表达式及其值的体现,所以使用汇编语言实现该题目时,需分为两个部分:
1.将输入内容存储为字符串类型并遍历三次,第一次遍历字符串,去除空格并计算字母个数,确认符号位;第二次遍历字符串,去除重复字母并按字母顺序排序;第三次遍历字符串,输出每个字母的二进制编码。
2.判断符号位以及p&q表达式计算结果并输出

下面是对代码的详细解析:

  1. 头文件和命名空间

    • 包含 <bits/stdc++.h> 头文件,这个头文件是GCC编译器的一个特性,它包含了几乎所有标准库的头文件。
    • 使用 using namespace std; 来避免在标准库类型和函数前加 std::
  2. 宏定义

    • MAXSIZE 定义了一个常量,用于确定字符数组的最大大小。
  3. 辅助函数 judge

    • 这个函数用于根据两个整数 pq 以及一个逻辑运算符 ch 来计算结果。
    • 支持的逻辑运算符有 |(或)、^(异或)、-(非)、<(小于)。
  4. 核心函数 cal

    • 这个函数用于计算给定的逻辑表达式 b,并存储结果在字符数组 ans 中。
    • 使用一个栈 op1 来存储整数操作数,以及一个栈 op2 来存储逻辑运算符。
    • 通过遍历表达式 b,结合运算符的优先级和结合性,逐步计算出表达式的结果。
  5. 主函数 main

    • 从标准输入读取字符串 str,直到输入结束。
    • 使用字符数组 b 来存储去除空格后的 str
    • 使用数组 a 来标记 str 中出现的每个字母(假设为变量),并使用数组 ans 存储这些唯一变量的排序结果。
  6. 处理输入字符串

    • 遍历 str,将非空格字符复制到 b,同时记录 str 中每个不同字母的出现次数,并存储到 a 中。
    • a 中标记为出现过的字母按顺序存储到 ans 中。
  7. 计算所有可能的真值组合

    • 使用 pow(2, j) - 1 计算出所有可能的变量组合(j 是变量的数量)。
    • 对于每一种可能的组合,使用 cal 函数计算表达式 b 的结果。
  8. 输出结果

    • 对于每一种变量组合,输出对应的计算结果。
  9. 程序结束

    • 返回 0,表示程序正常结束。

代码逻辑分析

  • 这段代码实现了一个逻辑表达式的求值器,它能够处理包含变量和逻辑运算符的表达式。
  • 它首先处理输入字符串,去除空格并记录变量。
  • 然后,对于所有可能的变量真值组合,使用 cal 函数计算表达式的值。

潜在问题

  • 使用 gets 函数是不安全的,因为它可能导致缓冲区溢出。应该使用 fgets 函数代替。

改进建议

  • 替换 gets 函数为 fgets
  • 清理未使用的变量和潜在的错误。
  • 增加对输入字符串有效性的检查。

部分实现

代码如下(判断符号位以及p&q表达式计算结果并输出):

int judge(int p,int q,char ch)
{
    if(ch=='|'){if(p==0&&q==0)return 0;else return 1;}
    else if(ch=='^'){if(p==1&&q==1)return 1;else return 0;}
    else if(ch=='-'){if(p==1&&q==1)return 1; else if(p==1&&q==0)return 0; else return 1;}
    else if(ch=='<'){if(p==1&&q==1)return 1; else if(p==0&&q==0)return 1;  else return 0;}
    return 0;
}

代码如下(进行多次遍历,第一次遍历字符串,去除空格并计算字母个数,确认符号位;第二次遍历字符串,去除重复字母并按字母顺序排序;第三次遍历字符串,输出每个字母的二进制编码。):

void cal(int sum,int j,char b[],char ans[])
{
    int i;
    int a[11]= {0};
    int flag=0;
    while(sum/2)
    {
        a[flag]=sum%2;
        flag++;
        sum/=2;
    }
    a[flag]=sum;
    flag++;
    for(i=j-1; i>=0; i--){printf("%d ",a[i]);}
    stack<int> op1;
    stack<char> op2;
    sort(ans,ans+j);
    for(i=0; i<strlen(b);)
    {
        if(b[i]>='a'&&b[i]<='z')
        {
            for(int jj=0; jj<j; jj++)
            {
                if(b[i]==ans[jj]){op1.push(a[j-jj-1]);}
            }
            i++;
            continue;
        }
        if((op2.empty()==true)&&(!(b[i]>='a'&&b[i]<='z')))
        {
            op2.push(b[i]);
            if(b[i]=='|'||b[i]=='-'){i+=2;}
            else if(b[i]=='^'||b[i]=='!'||b[i]=='('||b[i]==')'){i++;}
            else if(b[i]=='<')i+=3;
            continue;
        }
        if(op1.empty()==true&&b[i]=='!')
        {
            op2.push(b[i]);i++;
            continue;
        }
        int num,x,y;
        if((op2.top()=='(')&&(b[i]==')')){num=0;}
        else if(b[i]==')')num=1;
        else if(op2.top()=='(')num=-1;
        else if(b[i]=='(')num=-1;
        else
        {
            if(b[i]=='!')x=5;
            else if(b[i]=='^')x=4;
            else if(b[i]=='|')x=3;
            else if(b[i]=='-')x=2;
            else x=1;
            if(op2.top()=='!')y=5;
            else if(op2.top()=='^')y=4;
            else if(op2.top()=='|')y=3;
            else if(op2.top()=='-')y=2;
            else y=1;
            if(x-y>0)num=-1;
            else num=1;
        }
        switch(num)
        {
        case -1:{op2.push(b[i]);break;}
        case 0:{op2.pop();break;}
        case 1:
        {
            char ch;
            ch=op2.top();
            op2.pop();
             if(ch=='!')
            {
            int con;
            con=op1.top();
            con=!con;
            op1.top()=con;
                break;
            }
            else
            {
            int con1,con2;
            con2=op1.top();
            op1.pop();
            con1=op1.top();
            op1.pop();
            op1.push(judge(con1,con2,ch));
                break;
            }
        }
        }
        if(num==1)continue;
        if((b[i]=='|')||(b[i]=='-')){i+=2;}
        else if((b[i]=='^')||(b[i]=='!')||(b[i]=='(')||(b[i]==')')){i++;}
        else{i+=3;}
    }
    while(op2.empty()!=true)
    {
        char ch;
        ch=op2.top();
        op2.pop();
        if(ch=='!')
        {
            int con;
            con=op1.top();
            con=!con;
            op1.top()=con;
        }
        else
        {
            int con1,con2;
            con2=op1.top();
            op1.pop();
            con1=op1.top();
            op1.pop();
            op1.push(judge(con1,con2,ch));
        }
    }
    printf("%d",op1.top());
    printf("\n");
}

总结

#include <bits/stdc++.h>
#define MAXSIZE 201
using namespace std;
  
int judge(int p,int q,char ch)//判断符号位以及pq计算结果
{
    if(ch=='|'){if(p==0&&q==0)return 0;else return 1;}
    else if(ch=='^'){if(p==1&&q==1)return 1;else return 0;}
    else if(ch=='-'){if(p==1&&q==1)return 1; else if(p==1&&q==0)return 0; else return 1;}
    else if(ch=='<'){if(p==1&&q==1)return 1; else if(p==0&&q==0)return 1;  else return 0;}
    return 0;
}
  
void cal(int sum,int j,char b[],char ans[])
{
    int i;
    int a[11]= {0};
    int flag=0;
    while(sum/2)
    {
        a[flag]=sum%2;
        flag++;
        sum/=2;
    }
    a[flag]=sum;
    flag++;
    for(i=j-1; i>=0; i--){printf("%d ",a[i]);}
    stack<int> op1;
    stack<char> op2;
    sort(ans,ans+j);
    for(i=0; i<strlen(b);)
    {
        if(b[i]>='a'&&b[i]<='z')
        {
            for(int jj=0; jj<j; jj++)
            {
                if(b[i]==ans[jj]){op1.push(a[j-jj-1]);}
            }
            i++;
            continue;
        }
        if((op2.empty()==true)&&(!(b[i]>='a'&&b[i]<='z')))
        {
            op2.push(b[i]);
            if(b[i]=='|'||b[i]=='-'){i+=2;}
            else if(b[i]=='^'||b[i]=='!'||b[i]=='('||b[i]==')'){i++;}
            else if(b[i]=='<')i+=3;
            continue;
        }
        if(op1.empty()==true&&b[i]=='!')
        {
            op2.push(b[i]);i++;
            continue;
        }
        int num,x,y;
        if((op2.top()=='(')&&(b[i]==')')){num=0;}
        else if(b[i]==')')num=1;
        else if(op2.top()=='(')num=-1;
        else if(b[i]=='(')num=-1;
        else
        {
            if(b[i]=='!')x=5;
            else if(b[i]=='^')x=4;
            else if(b[i]=='|')x=3;
            else if(b[i]=='-')x=2;
            else x=1;
            if(op2.top()=='!')y=5;
            else if(op2.top()=='^')y=4;
            else if(op2.top()=='|')y=3;
            else if(op2.top()=='-')y=2;
            else y=1;
            if(x-y>0)num=-1;
            else num=1;
        }
        switch(num)
        {
        case -1:{op2.push(b[i]);break;}
        case 0:{op2.pop();break;}
        case 1:
        {
            char ch;
            ch=op2.top();
            op2.pop();
             if(ch=='!')
            {
            int con;
            con=op1.top();
            con=!con;
            op1.top()=con;
                break;
            }
            else
            {
            int con1,con2;
            con2=op1.top();
            op1.pop();
            con1=op1.top();
            op1.pop();
            op1.push(judge(con1,con2,ch));
                break;
            }
        }
        }
        if(num==1)continue;
        if((b[i]=='|')||(b[i]=='-')){i+=2;}
        else if((b[i]=='^')||(b[i]=='!')||(b[i]=='(')||(b[i]==')')){i++;}
        else{i+=3;}
    }
    while(op2.empty()!=true)
    {
        char ch;
        ch=op2.top();
        op2.pop();
        if(ch=='!')
        {
            int con;
            con=op1.top();
            con=!con;
            op1.top()=con;
        }
        else
        {
            int con1,con2;
            con2=op1.top();
            op1.pop();
            con1=op1.top();
            op1.pop();
            op1.push(judge(con1,con2,ch));
        }
    }
    printf("%d",op1.top());
    printf("\n");
}
  
int main()
{
    char str[MAXSIZE];
    int i,j,k;
    while(gets(str))
    {
        int a[260]= {0};
        char ans[260];
        char b[200];
        j=k=0;
        for(i=0; str[i]!='\0'; i++)
        {
            if(str[i]!=' '){ b[k]=str[i]; k++;}
            if(str[i]>='a'&&str[i]<='z')
            {
                int b=str[i];
                if(a[b-97]==0){a[b-97]=1;ans[j]=str[i];j++;}
            }
        }
        b[k]='\0';
        for(i=0; i<=25; i++){if(a[i]==1){printf("%c ",i+97);}}
        cout<<str<<endl;
        int sum=pow(2,j)-1;
        while(sum>=0){cal(sum,j,b,ans);sum--; }
    }
    return 0;
}
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值