问题 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表达式计算结果并输出
下面是对代码的详细解析:
-
头文件和命名空间:
- 包含
<bits/stdc++.h>
头文件,这个头文件是GCC编译器的一个特性,它包含了几乎所有标准库的头文件。 - 使用
using namespace std;
来避免在标准库类型和函数前加std::
。
- 包含
-
宏定义:
MAXSIZE
定义了一个常量,用于确定字符数组的最大大小。
-
辅助函数
judge
:- 这个函数用于根据两个整数
p
和q
以及一个逻辑运算符ch
来计算结果。 - 支持的逻辑运算符有
|
(或)、^
(异或)、-
(非)、<
(小于)。
- 这个函数用于根据两个整数
-
核心函数
cal
:- 这个函数用于计算给定的逻辑表达式
b
,并存储结果在字符数组ans
中。 - 使用一个栈
op1
来存储整数操作数,以及一个栈op2
来存储逻辑运算符。 - 通过遍历表达式
b
,结合运算符的优先级和结合性,逐步计算出表达式的结果。
- 这个函数用于计算给定的逻辑表达式
-
主函数
main
:- 从标准输入读取字符串
str
,直到输入结束。 - 使用字符数组
b
来存储去除空格后的str
。 - 使用数组
a
来标记str
中出现的每个字母(假设为变量),并使用数组ans
存储这些唯一变量的排序结果。
- 从标准输入读取字符串
-
处理输入字符串:
- 遍历
str
,将非空格字符复制到b
,同时记录str
中每个不同字母的出现次数,并存储到a
中。 - 将
a
中标记为出现过的字母按顺序存储到ans
中。
- 遍历
-
计算所有可能的真值组合:
- 使用
pow(2, j) - 1
计算出所有可能的变量组合(j
是变量的数量)。 - 对于每一种可能的组合,使用
cal
函数计算表达式b
的结果。
- 使用
-
输出结果:
- 对于每一种变量组合,输出对应的计算结果。
-
程序结束:
- 返回 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;
}