1.实验目的
掌握命题公式真值表的求解,并实现自动求解程序。
2.实验内容
输入:任意命题公式
输出:该命题公式的真值表
要求:
- 输入任意命题公式,要求用数据存储命题公式的所有赋值及对应真值,并输出该公式真值表
- 此题,难度稍大,对命题公式的表示的方式不一样,实现过程略有不同,可查找相关资料。
3.实验过程(主要思想、核心算法、核心代码)
代码比较长,还需要细心观看,有什么意见还请大佬提出,谢谢!
主函数
#include <stdio.h>
#include <string.h>
int main()
{
void quFan(char a[]);
void kuohao(char a[]);
void heQu(char a[]);
void stJian(char a[]);
void xiQu(char a[]);
int allData(char a[],char b[]);
void fillIn(char a[],char varchar[],int nvar,char values[],char resultchar[]);
char pstate[120],pstate0[120],charList[120],charVal[120];
int i=0,nold=0,nnew=0,nvar=1,nRow=1,j=0,flagsum=1;
printf("请输入公式(析|,合&,条-,双=,否!,01):\n");
gets(pstate0);
nold=strlen(pstate0)+1;
nnew=strlen(pstate0);
for(i=0;i<nnew;i++)
{
pstate[i]=pstate0[i];
}
pstate[i]='\0';
nvar=allData(pstate,charList);//取变元个数
nRow=1;//有2^n个情况
for(i=0;i<nvar;i++){
charVal[i]='0';nRow=nRow*2;
}
charVal[i]='\0';
for(i=0;i<nRow;i++){//输出每种情况的结果
for(j=0;j<nvar;j++)
{
printf("%4c",charVal[j]);//每种赋值情况输出
}
/**
将值填入公式
pstate原始数组
返回pstate填充后数组
*/
fillIn(pstate0,charList,nvar,charVal,pstate);
//计算公式的值
nold=strlen(pstate0)+1;
nnew=strlen(pstate);
while(nnew<nold)
{
nold=strlen(pstate);
quFan(pstate);
kuohao(pstate);
stJian(pstate);
heQu(pstate);
xiQu(pstate);
nnew=strlen(pstate);
}
printf("%15c%s",' ',pstate);
printf("\n");
//值加1
flagsum=1;
for(j=nvar-1;j>=0;j--)
{
if(charVal[j]=='1'){
if(flagsum==1){//1+1=10//进位
charVal[j]='0';flagsum=1;
}else{break;}//1+0=1 不变
}else if(charVal[j]=='0'){
if(flagsum==1){ //0+1=1 //没有进位
charVal[j]='1'; flagsum=0;
}else{break;}// 0+0
}
}
}
return 0;
}
取反,也就是非!
void quFan(char a[]){
int _result=0,i=0,j=0;
while(i<strlen(a)){
j=i;_result=0;
//非的真值情况
if((j+1<strlen(a))&&(a[j]=='!')&&(a[j+1]=='1')){
a[j]='0';_result=1;
}else if((j+1<strlen(a))&&(a[j]=='!')&&(a[j+1]=='0')){
a[j]='1';_result=1;
}
if(_result==1){//修改成功后则后面的往前覆盖
j++;
while(a[j+1]!='\0'){
a[j]=a[j+1]; j++;
}
a[j]='\0';
}else{i++;}
}
}
括号解析
void kuohao(char a[])
{
int _result=0,i=0,j=0;
while(i<strlen(a)){
j=i; _result=0;
//括号的处理
if((j+2<strlen(a))&&(a[j]=='(')&&(a[j+1]=='1')&&(a[j+2]==')')){
a[j]='1'; _result=1;
}else if((j+2<strlen(a))&&(a[j]=='(')&&(a[j+1]=='0')&&(a[j+2]==')')){
a[j]='0'; _result=1;
}
if(_result==1){//修改成功后则后面的往前覆盖
j++;
while(a[j+2]!='\0'){
a[j]=a[j+2]; j++;
}
a[j]='\0';
}else {i++;}
}
}
合取
void heQu(char a[]){
int _result=0,i=0,j=0;
while(i<strlen(a)){
j=i;_result=0;
//合取的真值情况
if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='&')&&(a[j+2]=='0'))
{a[j]='0';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='&')&&(a[j+2]=='1'))
{a[j]='0';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='&')&&(a[j+2]=='0'))
{a[j]='0';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='&')&&(a[j+2]=='1'))
{a[j]='1';_result=1;}
if(_result==1){//修改成功后则后面的往前覆盖
j++;
while(a[j+2]!='\0'){
a[j]=a[j+2];j++;
}
a[j]='\0';
}else {i++;}
}
}
析取
void xiQu(char a[]){
int _result=0,i=0,j=0;
while(i<strlen(a)){
j=i;_result=0;
//析取的真值情况
if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='|')&&(a[j+2]=='0'))
{a[j]='0';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='|')&&(a[j+2]=='1'))
{a[j]='1';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='|')&&(a[j+2]=='0'))
{a[j]='1';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='|')&&(a[j+2]=='1'))
{a[j]='1';_result=1;}
if(_result==1){//修改成功后则后面的往前覆盖
j++;
while(a[j+2]!='\0'){
a[j]=a[j+2];j++;
}
a[j]='\0';//结尾添加字符串结束符
}else {i++;}
}
}
双条件
void stJian(char a[])
{
int _result=0,i=0,j=0;
while(i<strlen(a)){
j=i;_result=0;
//双条件的真值情况
if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='=')&&(a[j+2]=='0'))
{a[j]='0';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='=')&&(a[j+2]=='1'))
{a[j]='0';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='=')&&(a[j+2]=='0'))
{a[j]='0';_result=1;}
else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='=')&&(a[j+2]=='1'))
{a[j]='1';_result=1;}
if(_result==1){//修改成功后则后面的往前覆盖
j++;
while(a[j+2]!='\0'){
a[j]=a[j+2];j++;
}
a[j]='\0';
}else {i++;}
}
}
获取命题公式所有不同的元素
int allData(char a[],char b[]){
char tmpc=' ';
int n=strlen(a),i=0,j=0,k=0;
for(i=0;i<n;i++){//获取所有变元,以便于输出和赋值
if(((a[i]>='a')&&(a[i]<='z'))||((a[i]>='A')&&(a[i]<='Z'))){
for(k=0;k<j;k++){
if(b[k]==a[i]){
break;
}
}
if(k>=j){
b[j]=a[i];
j++;
}
}
}
b[j]='\0';//加上结束标志
//printf("====%s",b);
//从高到低排序
for(i=0;i<j-1;i++){
for(k=0;k<j-i-1;k++){
if(b[k]>b[k+1]){
tmpc=b[k];
b[k]=b[k+1];
b[k+1]=tmpc;
}
}
}
return j;//不同的变元个数
}
将赋值情况代入命题公式中
void fillIn(char a[],char varchar[],int nvar,char values[],char resultchar[])
{
/**
a是原始公式
varchar是变元列表如abc
values 是变元的某次取值
二进制的思维把相应位置的变元替换成'0'或'1'
*/
int nLen=strlen(a),i=0,j=0,k=0;
for(i=0;i<nLen;i++){//不改变原数组
resultchar[i]=a[i];
}
resultchar[i]='\0';
for(i=0;i<nLen;i++){
for(j=0;j<nvar;j++){
if(resultchar[i]==varchar[j]){
resultchar[i]=values[j];
break;
}
}
}
}
温馨提示:以上是完整代码,小代码块可能多出一个花括号,不碍事那是main的或括号。大佬有意见或者建议还请提出,学习进步。