#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <math.h>
#define N 50
void panduan(int b[N], int f);//赋值函数
int tkh(char sz[N], char ccu[N], int icu[N], int h0);//分级运算函数
int fkh(char sz[N], char ccu[N], int icu[N], int h0);//主运算函数
int main()
{
int i1, i2, d = 1, icu[N], kh = 0, jg, j = 0, h0;//icu[N]用于存放变量值,kh括号计数,jg存放结果
int bj = 0, hq[N], h = 0, x = 0, xq[N];//hq[N]存放合取结果xq[N]存放析取结果
char sz[N], ccu[N], sz0[N], s;//sz[N]存放式子,ccu[N]存放变量,sz0[N]也是用于存放式子
hq[0] = -1;
xq[0] = -1;
printf("*****************************************\n");
printf("\n");
printf(" 用!表示否定\n");
printf(" 用&表示且\n");
printf(" 用|表示或\n");
printf(" 用^表示条件\n");
printf(" 用~表示双条件\n");
printf("\n");
printf("*****************************************\n\n");
printf(" 请输入一个合法的命题公式:\n");
gets_s(sz);//读取式子
strcpy(sz0, sz);
for (i1 = 0; i1 < strlen(sz); i1++)
{
if (sz[i1] == ')' || sz[i1] == '(')//存储括号数量
kh++;
if (sz[i1] >= 'a' && sz[i1] <= 'z' || sz[i1] >= 'A' && sz[i1] <= 'Z')
{
for (i2 = 0; i2 < j; i2++) //判断并储存变量。
{
if (ccu[i2] == sz[i1]) //去除重复变量
d = 0;
}
if (d == 1)
{
ccu[j] = sz[i1];
j++;
}
d = 1;
}
}
printf("\n该式子中的变量个数为:%d\n", j);//输出变量个数
h0 = j;
printf("\n输出真值表如下:\n \n"); //输出真值表表头
for (i1 = 0; i1 < h0; i1++)
printf(" %c ", ccu[i1]);
printf(" ");
puts(sz);
printf("\n");
for (i1 = 0; i1 < j; i1++) //先将所有的变量赋值为1。
icu[i1] = 1;
for (i2 = 0; i2 < j; i2++) //输出真值表前项
printf(" %d ", icu[i2]);
jg = tkh(sz, ccu, icu, h0); //用函数求结果
if (jg == 0) //结果为0,合取加1
hq[h++] = bj;
else //否则,析取加1
xq[x++] = bj;
printf(" %d\n", jg); //输出运算结果
strcpy(sz, sz0);
for (i1 = 0; i1 < pow(2, j) - 1; i1++)
{
++bj;
panduan(icu, j - 1); //赋值变量
jg = tkh(sz, ccu, icu, h0);
if (jg == 0) //结果为0,合取加1
hq[h++] = bj;
else //否则,析取加1
xq[x++] = bj;
strcpy(sz, sz0); //恢复被修改的数组。
for (i2 = 0; i2 < j; i2++)
printf(" %d ", icu[i2]);//输出真值表前项
printf(" %d\n", jg);//输出运算结果
}
if (hq[0] == -1) //不存在合取范式时
printf("\n该命题公式不存在主合取范式。\n");
else
{
printf("\n该命题公式的主合取范式:\n\t");
for (i1 = 0; i1 < h; i1++)
{
if (i1 > 0)
printf("/\\");
printf("M(%d)", hq[i1]); //输出主合取范式
}
}
if (xq[0] == -1)
printf("\n该命题公式不存在主析取范式。\n");
else
{
printf("\n\n该命题公式的主析取范式:\n\t");
for (i1 = 0; i1 < x; i1++)
{
if (i1 > 0)
printf("\\/");
printf("m(%d)", xq[i1]);//输出主析取范式
}
} //结束
getch();
}
void panduan(int b[N], int f) // 二进制赋值。
{
int i;
i = f;
if (b[f] == 1) //减1
b[f] = 0;
else //进位
{
b[f] = 1;
panduan(b, --i);
}
}
int tkh(char sz[N], char ccu[N], int icu[N], int h0)//分级运算函数
{
int i, j, h, s, kh = 0, wz[N], a;
char xs1[N], ckh[N]; //xs1用来保存括号内的字符 ckh用来保存括号。
s = strlen(sz);
for (i = 0; i < s; i++)
if (sz[i] == '(' || sz[i] == ')') //判断括号
{
wz[kh] = i; //存储括号位置
ckh[kh] = sz[i]; //存储括号类型
kh++;
}
if (kh == 0)
return fkh(sz, ccu, icu, h0);//如果无括号,直接运行
else
{
for (i = 0; i < kh; i++)
if (ckh[i] == ')') //找到第一个
break;
for (j = wz[i - 1] + 1, h = 0; j < wz[i]; j++, h++) //存储最内级括号中的内容
xs1[h] = sz[j];
xs1[h] = '\0';
a = fkh(xs1, ccu, icu, h0); //运行最内层括号的式子,得到结果
if (a == 1) //判断并存储结果
sz[wz[i - 1]] = 1;
else
sz[wz[i - 1]] = -2;
for (j = wz[i - 1] + 1; j < s + wz[i - 1] - wz[i]; j++)//将括号后内容前移
sz[j] = sz[j + wz[i] - wz[i - 1]];
sz[j] = '\0';
return tkh(sz, ccu, icu, h0);//循环执行
}
}
int fkh(char sz[N], char ccu[N], int icu[N], int h0)//主运算函数
{
int i, h = 0, j = 0, j1 = 0, j2 = 0, j3 = 0, j4 = 0, j5 = 0, i1, i2, p1 = -1, p2 = -1, s;
char dt[N];
s = strlen(sz);
if (s == 1)
{
for (i1 = 0; i1 < h0; i1++)
if (sz[0] == ccu[i1])
p1 = icu[i1];
if (sz[0] == -2 || p1 == 0) //判断是否是最后一项
return 0;
else
return 1;
} //1 就是sz[0]的值
else
{
for (i = 0; i < s - j; i++) //先处理非
if (sz[i] == '!')
{
for (i1 = 0; i1 < h0; i1++)
if (sz[i + 1] == ccu[i1])
{ //将变量赋值并给P1
p1 = icu[i1];
}
if (sz[i + 1] == -2) //如果是前运算结果的0,则P1等于0
p1 = 0;
if (p1 == -1) //如果是数字,直接给P1
p1 = sz[i + 1];
sz[i] = !p1;
j++;
p1 = -1;
for (i1 = i + 1; i1 < s - j; i1++)
sz[i1] = sz[i1 + 1]; //将后续式子前移一项
}
p1 = -1;
j1 = j;
for (i = 0; i < s - j1 - 2 * j2; i++) // 处理与
if (sz[i] == '&')
{
for (i1 = 0; i1 < h0; i1++)
{
if (sz[i - 1] == ccu[i1]) //将变量赋值并给P1
p1 = icu[i1];
if (sz[i + 1] == ccu[i1]) //将变量赋值并给P2
p2 = icu[i1];
}
if (sz[i - 1] == -2) //如果是前运算结果的0,则P1等于0
p1 = 0;
if (sz[i + 1] == -2)
p2 = 0;
if (p1 == -1) //如果是数字,直接给P1
p1 = sz[i - 1];
if (p2 == -1)
p2 = sz[i + 1];
sz[i - 1] = p1 && p2;
j2++;
p1 = -1;
p2 = -1;
for (i1 = i; i1 < s - j1 - 2 * j2; i1++)//将后续式子前移两项
sz[i1] = sz[i1 + 2];
i = i - 1;
}
for (i = 0; i < s - j1 - 2 * j2 - 2 * j3; i++) // 处理或。
if (sz[i] == '|')
{
for (i1 = 0; i1 < h0; i1++)
{
if (sz[i - 1] == ccu[i1]) //将变量赋值并给P1
p1 = icu[i1];
if (sz[i + 1] == ccu[i1])
p2 = icu[i1];
}
if (sz[i - 1] == -2) //如果是前运算结果的0,则P1等于0
p1 = 0;
if (sz[i + 1] == -2)
p2 = 0;
if (p1 == -1) //如果是数字,直接给P1
p1 = sz[i - 1];
if (p2 == -1)
p2 = sz[i + 1];
sz[i - 1] = p1 || p2;
j3++;
p1 = -1;
p2 = -1;
for (i1 = i; i1 < s - j1 - 2 * j2 - 2 * j3; i1++)//将后续式子前移两项
sz[i1] = sz[i1 + 2];
i--;
}
for (i = 0; i < s - j1 - 2 * j2 - 2 * j3 - 2 * j4; i++) // 处理条件
if (sz[i] == '^')
{
for (i1 = 0; i1 < h0; i1++)
{
if (sz[i - 1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if (sz[i + 1] == ccu[i1])
p2 = icu[i1];
}
if (sz[i - 1] == -2) //如果是前运算结果的0,则P1等于0
p1 = 0;
if (sz[i + 1] == -2)
p2 = 0;
if (p1 == -1) //如果是数字,直接给P1
p1 = sz[i - 1];
if (p2 == -1)
p2 = sz[i + 1];
sz[i - 1] = !p1 || p2;
j4++;
p1 = -1;
p2 = -1;
for (i1 = i; i1 < s - j1 - 2 * j2 - 2 * j3 - 2 * j4; i1++)//将后续式子前移两项
sz[i1] = sz[i1 + 2];
i--;
}
for (i = 0; i < s - j1 - 2 * j2 - 2 * j3 - 2 * j4 - 2 * j5; i++) // 处理双条件
if (sz[i] == '~')
{
for (i1 = 0; i1 < h0; i1++)
{
if (sz[i - 1] == ccu[i1])//将变量赋值并给P1
p1 = icu[i1];
if (sz[i + 1] == ccu[i1])
p2 = icu[i1];
}
if (sz[i - 1] == -2) //如果是前运算结果的0,则P1等于0
p1 = 0;
if (sz[i + 1] == -2)
p2 = 0;
if (p1 == -1) //如果是数字,直接给P1
p1 = sz[i - 1];
if (p2 == -1)
p2 = sz[i + 1];
sz[i - 1] = (!p1 || p2) && (!p2 || p1);
j5++;
p1 = -1;
p2 = -1;
for (i1 = i; i1 < s - j1 - 2 * j2 - 2 * j3 - 2 * j4 - 2 * j5; i1++)//将后续式子前移两项
sz[i1] = sz[i1 + 2];
i--;
}
return sz[0];
}
}
大二(上)离散数学 主析取范式与主合取范式
最新推荐文章于 2024-04-18 23:21:30 发布