高分求:设计一个程序,验证一个表达式是不是命题公式。

cbc 2009-09-27 09:24:58
离散数学中的一个编程题:

设计一个程序,验证一个表达式是不是命题公式。
...全文
924 51 打赏 收藏 转发到动态 举报
写回复
用AI写文章
51 条回复
切换为时间正序
请发表友善的回复…
发表回复
Paradin 2009-09-29
  • 打赏
  • 举报
回复
上面忘记释放了。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXL 255
#define MAX_PRI 255

#define NOT '~' //非
#define AND '&' //与
#define OR '|' //或
#define IMP - //蕴含
#define EQ = //等值
#define LB '('
#define RB ')'
#define NUL 0

typedef struct tagFormNode
{
int type;
struct tagFormNode *left;
struct tagFormNode *right;
} FormNode;

int priority(int ch)
{
switch (ch)
{
case '~': return 5;
case '&': return 4;
case '|': return 3;
case '-': return 2;
case '=': return 1;
default: return 0;
}
}

FormNode *new_node()
{
FormNode *p;
if ((p = (FormNode*)malloc(sizeof(FormNode))) == NULL)
{
printf("malloc heap memory failed.");
exit(-1);
}
p->left = p->right = 0;
return p;
}

int check_paren(const char *formular, int start, int end, int *wrapped)
{
int np = 0, i, flag = 0;
for (i = start; i <= end; ++i)
{
if (formular[i] == '(')
++np;
else if (formular[i] == ')')
--np;
if (np < 0)
return 0;
if (np == 0 && i < end)
flag = 1;
}
if (np != 0) return 0;
*wrapped = 0;
if (formular[start] == '(' && formular[end] == ')' && !flag)
*wrapped = 1;
return 1;
}

int findOp(const char *formular, int start, int end, int *op)
{
int i, ch, pri, tmp, pos, np = 0;
*op = NUL;
pri = MAX_PRI;
for (i = start; i <= end; ++i)
{
ch = formular[i];
if (ch == '(')
++np;
else if (ch == ')')
--np;
if (np == 0)
if ((tmp = priority(ch)) > 0 && tmp < pri)
{
pri = tmp;
*op = ch;
pos = i;
}
}
if (*op == NUL) return -1;
if (*op == NOT)
if (formular[start] == NOT)
pos = start;
else
{
*op = NUL;
return -1;
}
return pos;
}

int setup(const char *formular, int start, int end, FormNode *pNode)
{
int i, wrapped, op, pos;
if (start > end) return 0;
if (start == end)
{
if (isalpha(formular[start]))
{
pNode->type = formular[start];
return 1;
} else
return 0;
}
if (!check_paren(formular, start, end, &wrapped))
{
printf("check_paren failed\n");
return 0;
}
if (wrapped)
{
//printf("wrapped\n");
return setup(formular, start+1, end-1, pNode);
}

if ((pos = findOp(formular, start, end, &op)) >= 0)
{
pNode->type = op;
pNode->left = new_node();
if (op == NOT)
return setup(formular, start+1, end, pNode->left);
else
{
if (!setup(formular, start, pos-1, pNode->left))
return 0;
pNode->right = new_node();
return setup(formular, pos+1, end, pNode->right);
}
}
return 0;
}

void deWhite(char *str)
{
int i, j;
for (i = j = 0; str[j] != '\0'; ++j)
{
if (!isspace(str[j]))
str[i++] = str[j];
}
str[i] = '\0';
}

void destroy(FormNode *pNode)
{
if (pNode == NULL)
return;
destroy(pNode->left);
destroy(pNode->right);
free(pNode);
}

int main(int argc, char *argv[])
{
char formular[MAXL];
FormNode *root = new_node();
fgets(formular, MAXL, stdin);
deWhite(formular);
printf("%s\n", formular);

if (setup(formular, 0, strlen(formular)-1, root))
printf("是公式\n");
else
printf("不是公式\n");
destroy(root);
system("PAUSE");
return 0;
}
//(C)
//A&B
//~~~~(~~~A)
//(A| ( ~(B|(~(C|(D&E))))) )
//((~P)=((P|((~Q)&R))-(~R)))
//~((~(~P))=((P|((~Q) &R))-(~ (~ (~R)))) )

Paradin 2009-09-29
  • 打赏
  • 举报
回复
这个程序判断一个表达式是否是公式并建立了公式树 公式树可进一步用于公式运算
效率不高但是可以工作。
平均复杂度nlog(n)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXL 255
#define MAX_PRI 255

#define NOT '~' //非
#define AND '&' //与
#define OR '|' //或
#define IMP - //蕴含
#define EQ = //等值
#define LB '('
#define RB ')'
#define NUL 0

typedef struct tagFormNode
{
int type;
struct tagFormNode *left;
struct tagFormNode *right;
} FormNode;

int priority(int ch)
{
switch (ch)
{
case '~': return 5;
case '&': return 4;
case '|': return 3;
case '-': return 2;
case '=': return 1;
default: return 0;
}
}

FormNode *new_node()
{
FormNode *p;
if ((p = (FormNode*)malloc(sizeof(FormNode))) == NULL)
{
printf("malloc heap memory failed.");
exit(-1);
}
return p;
}

int check_paren(const char *formular, int start, int end, int *wrapped)
{
int np = 0, i, flag = 0;
for (i = start; i <= end; ++i)
{
if (formular[i] == '(')
++np;
else if (formular[i] == ')')
--np;
if (np < 0)
return 0;
if (np == 0 && i < end)
flag = 1;
}
if (np != 0) return 0;
*wrapped = 0;
if (formular[start] == '(' && formular[end] == ')' && !flag)
*wrapped = 1;
return 1;
}

int findOp(const char *formular, int start, int end, int *op)
{
int i, ch, pri, tmp, pos, np = 0;
*op = NUL;
pri = MAX_PRI;
for (i = start; i <= end; ++i)
{
ch = formular[i];
if (ch == '(')
++np;
else if (ch == ')')
--np;
if (np == 0)
if ((tmp = priority(ch)) > 0 && tmp < pri)
{
pri = tmp;
*op = ch;
pos = i;
}
}
if (*op == NUL) return -1;
if (*op == NOT)
if (formular[start] == NOT)
pos = start;
else
{
*op = NUL;
return -1;
}
return pos;
}

int setup(const char *formular, int start, int end, FormNode *pNode)
{
int i, wrapped, op, pos;
if (start > end) return 0;
if (start == end)
{
if (isalpha(formular[start]))
{
pNode->type = formular[start];
return 1;
} else
return 0;
}
if (!check_paren(formular, start, end, &wrapped))
{
printf("check_paren failed\n");
return 0;
}
if (wrapped)
{
//printf("wrapped\n");
return setup(formular, start+1, end-1, pNode);
}

if ((pos = findOp(formular, start, end, &op)) >= 0)
{
pNode->type = op;
pNode->left = new_node();
if (op == NOT)
return setup(formular, start+1, end, pNode->left);
else
{
if (!setup(formular, start, pos-1, pNode->left))
return 0;
pNode->right = new_node();
return setup(formular, pos+1, end, pNode->right);
}
}
return 0;
}

void deWhite(char *str)
{
int i, j;
for (i = j = 0; str[j] != '\0'; ++j)
{
if (!isspace(str[j]))
str[i++] = str[j];
}
str[i] = '\0';
}

int main(int argc, char *argv[])
{
char formular[MAXL];
FormNode *root = new_node();
fgets(formular, MAXL, stdin);
deWhite(formular);
printf("%s\n", formular);

if (setup(formular, 0, strlen(formular)-1, root))
printf("是公式\n");
else
printf("不是公式\n");
system("PAUSE");
return 0;
}
//(C)
//A&B
//~~~~(~~~A)
//(A| ( ~(B|(~(C|(D&E))))) )
//((~P)=((P|((~Q)&R))-(~R)))
//~((~(~P))=((P|((~Q) &R))-(~ (~ (~R)))) )

Paradin 2009-09-29
  • 打赏
  • 举报
回复
如果仅判断是否是公式 上面所有关于公式树等无关内容都可以去掉。
我也是最近在做个作业 恰好看到lz的帖子
cbc 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 49 楼 paradin 的回复:]
上面忘记释放了。

C/C++ code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>#define MAXL 255#define MAX_PRI 255#define NOT '~'//非#define AND '&'//与#define OR '|'//或#define IMP -//蕴含#define EQ =//等值#define LB '('#define RB ')'#define NUL 0
............

很好,完全实现了所要求功能。有以下不足:
1) 注释偏少,建议增加些注释
2)宏没用上,这个我改了

int priority(int ch)
{
switch (ch)
{
case NOT: return 5;
case AND: return 4;
case OR: return 3;
case IMP: return 2;
case EQ: return 1;
default: return 0;
}
}

wangjieeee 2009-09-28
  • 打赏
  • 举报
回复
up
1212212211 2009-09-28
  • 打赏
  • 举报
回复
UP
liguiman 2009-09-28
  • 打赏
  • 举报
回复
maomaozgc 2009-09-28
  • 打赏
  • 举报
回复
thankyou
Paradin 2009-09-28
  • 打赏
  • 举报
回复
合式的公式
(1)单个命题变元是合式的公式。
(2)如果A是合式的公式,那么(¬ A)是合式的公式。
(3)如果A和B均是合式的公式,那么(A∧B) ,(A∨B) ,   
        (A→B),(A«B)  都是合式的公式。
(4)当且仅当有限次的应用(1)、(2)、(3)条规则由逻辑联结词、圆括号所组成的有意义的符号串是合式的公式。

我的只适合这样的定义。
如果不加括号的话,公式的生成过程就不唯一了,该形式语言是有歧义的,否则要引入优先级。我正在做好了就发上来。

比如

a∧b∨c

可以是(a∧b)∨c 也可以是a∧(b∨c)


cbc 2009-09-28
  • 打赏
  • 举报
回复
[Quote=引用 35 楼 paradin 的回复:]
这个没写完而且还有内存泄漏

C/C++ code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>#define MAXL 255#define NOT '~'#define AND '&'#define OR '|'#define IMP '-'#define EQ '='#define LP '('#define RP ')'//公式树节点typedefstruct tagFormNode
{int type;struct tagFormNode*left;struct tagFormNode*right;
} FormNode;char form[MAXL];int idx=-1;
FormNode*formTree;
。。。。。。


这个程序还有些问题,比如“p&q"是命题公式,但在你的程序里面结论是”不是公式“
cbc 2009-09-28
  • 打赏
  • 举报
回复
合式的公式
(1)单个命题变元是合式的公式。
(2)如果A是合式的公式,那么¬ A是合式的公式。
(3)如果A和B均是合式的公式,那么A∧B ,A∨B ,
A→B,A«B 都是合式的公式。
(4)当且仅当有限次的应用(1)、(2)、(3)条规则由逻辑联结词、圆括号所组成的有意义的符号串是合式的公式。
zhuyunhui 2009-09-28
  • 打赏
  • 举报
回复
UPUP
观弈道童 2009-09-28
  • 打赏
  • 举报
回复

每天回帖即可获得10分可用分!
周成风 2009-09-28
  • 打赏
  • 举报
回复
纯友情帮顶。。
frankge 2009-09-28
  • 打赏
  • 举报
回复
up
bobdog19861111 2009-09-28
  • 打赏
  • 举报
回复
学习,高手show下
Paradin 2009-09-28
  • 打赏
  • 举报
回复
这个没写完而且还有内存泄漏


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXL 255

#define NOT '~'
#define AND '&'
#define OR '|'
#define IMP '-'
#define EQ '='
#define LP '('
#define RP ')'

//公式树节点
typedef struct tagFormNode
{
int type;
struct tagFormNode *left;
struct tagFormNode *right;
} FormNode;

char form[MAXL];
int idx = -1;
FormNode *formTree;

FormNode *new_node()
{
FormNode *p = (FormNode*)malloc(sizeof(FormNode));
if (p == NULL)
{
printf("malloc failed.\n");
exit(-1);
}
p->left = p->right = NULL;
return p;
}

//打印树对应的公式
void printForm(FormNode *pNode)
{
if (pNode == NULL)
return;

if (isalpha(pNode->type))
printf("%c", pNode->type);
else
{
printf("%c", LP);
if (pNode->type == NOT)
{
printf("%c", NOT);
printForm(pNode->left);
}
else
{
printForm(pNode->left);
printf("%c", pNode->type);
printForm(pNode->right);
}
printf("%c", RP);
}

}

//打印所有子公式
void printChild(FormNode *pNode)
{
if (pNode == NULL)
return;
printChild(pNode->left);
printChild(pNode->right);
printForm(pNode);
printf("\n");
}

//去除蕴含
void deImply(FormNode *pNode)
{
if (pNode == NULL)
return;

deImply(pNode->left);
deImply(pNode->right);
if (pNode->type == IMP)
{
FormNode *pNot = new_node();
pNot->type = NOT;
pNot->left = pNode->left;
pNode->left = pNot;
pNode->type = OR;
}
}

//释放
void destroy(FormNode *pNode)
{
if (pNode == NULL)
return;
free(pNode->left);
free(pNode->right);
free(pNode);

}

//去除多重否定
void deMultiNot(FormNode *pNode)
{
FormNode *p, *q, *s;
int i, n;
if (pNode->left != NULL)
{
p = pNode->left;
n = 0;
while (p->type == NOT)
{
++n;
q = p;
p = p->left;
}
if (n > 0)
{
if (n % 2 == 0)
pNode->left = p;
else
pNode->left = q;
}
deMultiNot(pNode->left);
}

if (pNode->right != NULL)
{
p = pNode->right;
n = 0;
while (p->type == NOT)
{
++n;
q = p;
p = p->left;
}
if (n > 0)
{
if (n % 2 == 0)
pNode->right = p;
else
pNode->right = q;
}
deMultiNot(pNode->right);
}
}

//去除多重否定
FormNode *deNot(FormNode *pTree)
{
if (pTree->type == NOT)
{
FormNode *pRoot = new_node();
pRoot->left = pTree;
deMultiNot(pRoot);
pTree = pRoot->left;
free(pRoot);
}
else
deMultiNot(pTree);
return pTree;
}


int nextch()
{
int ch;
while ((ch = form[++idx]) == ' ' || ch == '\t');
return ch;
}

int prenext()
{
int ch, k = idx;
while ((ch = form[++k]) == ' ' || ch == '\t');
return ch;
}

//判断是否是公式并建立公式树
int Formular(FormNode *pNode)
{
int ch = nextch();
if (ch == '\0')
return 0;
if (isalpha(ch))
{
pNode->type = ch;
return 1;
}
if (ch == LP)
{
pNode->left = new_node();
if (prenext() == NOT)
{
pNode->type = NOT;
nextch();
if (!Formular(pNode->left))
return 0;
}
else
{
if (!Formular(pNode->left))
return 0;
ch = nextch();
if (!(ch == OR || ch == AND || ch == IMP || ch == EQ))
return 0;
else
{
pNode->type = ch;
pNode->right = new_node();
}
if (!Formular(pNode->right))
return 0;
}
return (nextch() == RP);
}
else
return 0;
}

//初始化
void init()
{
fgets(form, MAXL, stdin);
form[strlen(form)-1] = '\0';
formTree = new_node();
}


int main(int argc, char *argv[])
{
init();
int isform;
isform = Formular(formTree);
if (nextch() != '\0')
isform = 0;
if (isform)
{
printf("是公式, 所有子公式:\n");
printChild(formTree);
printf("\n\n");

printf("去除双重否定:");
formTree = deNot(formTree);
printForm(formTree);
printf("\n\n");

printf("去除蕴含:");
deImply(formTree);
printForm(formTree);

printf("\n\n");
}
else
{
printf("不是公式\n\n");
}
destroy(formTree);
system("PAUSE");
return 0;
}

//(A| ( ~(B|(~(C|(D&E))))) )
//((~P)=((P|((~Q)&R))-(~R)))
//(~((~(~P))=((P|((~Q) &R))-(~ (~ (~R)))) ))

frank5578 2009-09-28
  • 打赏
  • 举报
回复
我也想知道是怎么做的,
悲剧的人参 2009-09-28
  • 打赏
  • 举报
回复
完全不懂 持观望态度
chentx_123 2009-09-28
  • 打赏
  • 举报
回复
路过,等待牛人
加载更多回复(27)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧