离散作业真的难顶QAQ,非得整个编程题
输入一个逻辑式,计算变元的所有可能,判断逻辑式是否是可满足的
例如
输入
!((PdQ)cP)#
输出
====================================================================
输入规则为c=Λ,d=V,i=→,e=←→,!=┐
命题变元请用大写字母表示
支持26个字母变元
逻辑式请尽可能用括号表示运算顺序
并以#结尾!
====================================================================
请输入表达式(以#结尾):!((PdQ)cP)#
输入的表达式为:
┐((PVQ)ΛP)
┐((0V0)Λ0) 的计算结果是: 1
┐((1V0)Λ1) 的计算结果是: 0
┐((0V1)Λ0) 的计算结果是: 1
┐((1V1)Λ1) 的计算结果是: 0
此命题是可满足的
请按任意键继续. . .
整体代码是在数值表达式计算器的基础上改进的
也是通过优先级表来实现优先级判断,其中的比较符也可以用数值表示优先级
基本的注释咱应该都写上了,实际也测试过了
运行环境是visual studio 2019
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#define INIT_STACK_SIZE 100 //栈最大长度
#define SET_NUM 8 //运算符数量
//字符优先级表
unsigned char prior[SET_NUM][SET_NUM] =
{
/* 'Λ' 'V' '→''←→''(' ')' '#' '!' */
/*'Λ'*/ '>', '>', '>', '>', '<','>', '>', '<',
/*'V '*/ '>', '>', '>', '>', '<','>', '>', '<',
/*'→'*/ '>', '>', '>', '>', '<','>', '>', '<',
/*'←→'*/'>', '>', '>', '>', '<','>', '>', '<',
/*'('*/ '<', '<', '<', '<', '<','=', ' ', '<',
/*')'*/ '>', '>', '>', '>', ' ','>', '>', '>',
/*'#'*/ '<', '<', '<', '<', '<',' ', '=', '<',
/*'!'*/ '>', '>', '>', '>', '<','>', '>', '>'
};
//表示支持的运算符,定义比较矩阵的行列对应方式
unsigned char priorSet[SET_NUM] = { 'c', 'd', 'i', 'e','(', ')', '#', '!' };
//结构体定义,这是用来存放字符的栈
typedef struct
{
char* base;
char* top;
int stacksize;
} SqStackC;
//结构体定义,这是用来存放数字的栈
typedef struct
{
int* base;
int* top;
int stacksize;
} SqStackN;
//函数定义
void initStackN(SqStackN&);
void initStackC(SqStackC&);
void pushN(SqStackN&, int);
void pushC(SqStackN&, int);
void popN(SqStackN&, int&);
void popC(SqStackN&, int&);
int calculate(int, char, int, SqStackN&);
int findInSet(char);
char compare(char, char);
void getSolution();
//初始化数字栈
void initStackN(SqStackN& S)
{
S.base = (int*)malloc(INIT_STACK_SIZE * sizeof(int));
S.top = S.base;
S.stacksize = INIT_STACK_SIZE;
}
//初始化字符栈
void initStackC(SqStackC& S)
{
S.base = (char*)malloc(INIT_STACK_SIZE * sizeof(char));
S.top = S.base;
S.stacksize = INIT_STACK_SIZE;
}
//向数字栈中存放数字
void pushN(SqStackN& S, int x)
{
if (S.top - S.base >= S.stacksize)
return;
*(S.top++) = x;
}
//向字符栈中存放字符
void pushC(SqStackC& S, char x)
{
if (S.top - S.base >= S.stacksize)
return;
*(S.top++) = x;
}
//从数字栈中取出数字
void popN(SqStackN& S, int& x)
{
if (S.top == S.base)
return;
x = *(--S.top);
}
//从字符栈中取出字符
void popC(SqStackC& S, char& x)
{
if (S.top == S.base)
return;
x = *(--S.top);
}
//这个函数返回aoperation b的值。假如operation为'+',则返回a+b的值
int calculate(int a, char operation, int b, SqStackN& S)
{
int o = 1;
/*判断operation,返回对应的计算结果*/
switch (operation) {
case 'c':
return a & b;
case 'd':
return a | b;
case 'i':
if (a == 1 && b == 0)o = 0;
return o;
case 'e':
return a == b;
default:
return 0;
}
}
//查找字符c在priorSet中的什么位置,priorSet是所支持的所有字符的集合
int findInSet(char c)
{
int i;
for (i = 0; i < SET_NUM; i++) {
if (priorSet[i] == c)
return i;
}
return -1;
}
//比较optrtop和c的优先关系
char compare(char optrtop, char c)
{
int i, j;
//从priorSet中取出optrtop和c的位置
i = findInSet(optrtop);
j = findInSet(c);
//如果返回值中有-1表示这个符号不支持,结束程序
if (i == -1 || j == -1) {
printf("不支持的符号类型\n");
exit(0);
}
//否则返回二者优先级关系
else
return prior[i][j];
}
void getSolution()
{
SqStackC Optr;
SqStackN Num;
//获得表达式
printf("====================================================================");
printf("\n\t输入规则为c=Λ,d=V,i=→,e=←→,!=┐\n\t命题变元请用大写字母表示\n\t支持26个字母变元\n\t逻辑式请尽可能用括号表示运算顺序\n\t并以#结尾!\n");
printf("====================================================================\n");
printf("请输入表达式(以#结尾):");
char input[100] = { 0 };
char in[100] = { 0 };
int a[26] = { 0 };
int b[26] = { 0 };
int numofobject = 0;
int iftrue = 0;
scanf_s("%s", in, 100);
printf("输入的表达式为:\n");
//将表达式转化为正常的表示方式,此段可省略
for (int i = 0; in[i] != '#'; i++) {
if (in[i] == '!')printf("┐");
else if (in[i] == 'c')printf("Λ");
else if (in[i] == 'd')printf("V");
else if (in[i] == 'i')printf("→");
else if (in[i] == 'i')printf("←→");
else printf("%c", in[i]);
}
printf("\n\n");
//处理变元,得到变元的数量和变元的名称,名称以ascii码存在b中,使用a[b[i]]来获取变元的值
for (int i = 0; in[i] != '#'; i++) {
if (in[i] >= 65 && in[i] <= 90) {
if (a[in[i] - 65] == 0) {
a[in[i] - 65] = 1;
b[numofobject] = in[i] - 65;
numofobject++;
}
}
}
//主要处理部分,n个变元有2^n种可能情况
for (int times = 0; times < pow(2, numofobject); times++) {
//通过位运算对每个变元进行取值,比如三个变元取101时,此时times=5,每次位运算得到一位,则a[b[0]]=1,a[b[1]]=0,a[b[2]]=1
//变元变化顺序取决于在字母表中的位置,靠前的为低位
for (int f = 0; f < numofobject; f++) {
a[b[f]] = ((times >> f) & 1)+48;
}
//将这种情况生成为代入了数值的表达式,并在最后添上#
int end = 0;
for (int i = 0; in[i] != '#'; i++) {
if (in[i] >= 65 && in[i] <= 90) {
input[i] = a[in[i] - 65];
}
else {
input[i] = in[i];
}
end = i;
}
input[end + 1] = '#';
//表达式输出部分,显示代入后的表达式,可省略
for (int i = 0; input[i] != '#'; i++) {
if (input[i] == '!')printf("┐");
else if (input[i] == 'c')printf("Λ");
else if (input[i] == 'd')printf("V");
else if (input[i] == 'i')printf("→");
else if (input[i] == 'i')printf("←→");
else printf("%c", input[i]);
}
//初始化栈,并在运算符栈放入终止符以便比较
initStackC(Optr);
initStackN(Num);
pushC(Optr, '#');
//计算模块
for (int i = 0; input[i] != '#'; i++) {
//遇到数字则入栈
if ('0' == input[i] || input[i] == '1') {
int x = input[i]-48;
pushN(Num, x);
}
//处理操作符
if (input[i] == 'c' || input[i] == 'd' || input[i] == 'i' || input[i] == 'e' || input[i] == '(' || input[i] == ')' || input[i] == '!') {
a:
char topstack; //获取栈顶元素
popC(Optr, topstack);
pushC(Optr, topstack);
char cmp = compare(topstack, input[i]);
if (cmp == '>') {
//单目操作符单独运算
if (topstack == '!') {
int op;
popN(Num, op);
op = !op;
popC(Optr, topstack);
pushN(Num, op);
}
else {
int op2, op1;
popN(Num, op2); popN(Num, op1);
int out = calculate(op1, topstack, op2, Num);
popC(Optr, topstack);
pushN(Num, out);
}
goto a;
}
if (cmp == '=') { //匹配括号
popC(Optr, topstack);
}
if (cmp == '<') {
pushC(Optr, input[i]);
}
}
}
//计算剩余操作符
while (Optr.top != Optr.base + 1) {
int op2, op1;
char topstack;
int out;
popC(Optr, topstack);
if (topstack == '!') {
int op;
popN(Num, op);
out = !op;
}
else {
popN(Num, op2); popN(Num, op1);
out = calculate(op1, topstack, op2, Num);
}
pushN(Num, out);
}
//数字栈的最后一项就是运算结果
int output;
popN(Num, output);
if (output == 1) {
iftrue = 1;
}
printf("\t的计算结果是:\t%d\n", output);
}
//判断命题是否可能满足
if (iftrue == 1) {
printf("\n此命题是可满足的\n\n");
}
else {
printf("\n此命题是不可满足的\n\n");
}
}
//主函数部分
int main()
{
getSolution();
system("pause");
return 0;
}
Comments | NOTHING