📄 动物识别专家系统.cpp
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//事实链表的结构描述
struct CAUSE_TYPE
{
char *cause;
struct CAUSE_TYPE *next;
};
struct RULE_TYPE
{
char *result;
int lastflag;
struct CAUSE_TYPE *cause_chain;
struct RULE_TYPE *next;
};
struct CAUSE_TYPE *DataBase;//已知事实链表头指针
struct CAUSE_TYPE *Conclusion;//结论链表头指针
struct RULE_TYPE *KnowledgeBase;//知识库规则链表头指针
struct RULE_TYPE *Used;//已使用规则链表头指针
void freeKB(struct RULE_TYPE *);
void freeDB(struct CAUSE_TYPE *);
int FindCause(char *);
void markKB();
void creatKB();
void inputDB();
void think();
void explain();
void copyKB(struct RULE_TYPE *rp,struct RULE_TYPE *KB);
//主函数
void main()
{
printf("请用正确的命令操作:\n");
printf("\t\t创建知识库: create\n");
printf("\t\t输入已知事实: input\n");
printf("\t\t进行推理: think\n");
printf("\t\t解释: explain\n");
printf("\t\t退出: exit\n");
char ch[10];
gets(ch);
while(1)
{
if(strcmp("exit",ch)==0)
{
//if(KnowledgeBase) freeKB(KnowledgeBase);
//if(Used) freeKB(Used);
//if(DataBase) freeDB(DataBase);
//if(Conclusion) freeDB(Conclusion);
printf("已正常退出!!!\n");
return;
}
if(strcmp("create",ch)==0)
{
if(KnowledgeBase)
{printf("知识库已创建!\n");}
else
{
creatKB(); printf("知识库已创建!\n");
RULE_TYPE *rp;
for(rp=KnowledgeBase;rp;rp=rp->next)
{printf("%s\n",rp->result);}
}
RULE_TYPE *rp1=NULL,*rp2=NULL;
copyKB(rp1,KnowledgeBase);
for(rp2=KnowledgeBase;rp2;rp2=rp2->next)
{printf("%s",rp2->result);printf("\n");}
}
else if(strcmp("input",ch)==0)
inputDB();
else if(strcmp("think",ch)==0)
{
think();
RULE_TYPE *rp;
for(rp=KnowledgeBase;rp;rp=rp->next)
{printf("%s\n",rp->result);}
}
else if(strcmp("explain",ch)==0)
explain();
else
{
printf("请选择正确的命令:\n");
printf("\t\t创建知识库: create\n");
printf("\t\t输入已知事实: input\n");
printf("\t\t进行推理: think\n");
printf("\t\t解释: explain\n");
printf("\t\t退出: exit\n");
}
gets(ch);
}
}
//释放事实链表子程序
void freeDB(struct CAUSE_TYPE *cPoint)
{
struct CAUSE_TYPE *cp;
while(cPoint)
{
cp=cPoint->next;
free(cPoint->cause);
cPoint->cause=NULL;
cPoint->next=NULL;
free(cPoint);
cPoint=cp;
}
}
//释放规则链表子程序
void freeKB(struct RULE_TYPE *rPoint)
{
struct RULE_TYPE *rp;
while(rPoint)
{
rp=rPoint->next;
freeDB(rPoint->cause_chain);
rPoint->cause_chain=NULL;
free(rPoint->result);
rPoint->result=NULL;
rPoint->next=NULL;
free(rPoint);
rPoint=rp;
}
}
//标记结论性规则子程序
void markKB()
{
struct RULE_TYPE *rp1,*rp2;
struct CAUSE_TYPE *cp;
rp1=KnowledgeBase;
while(rp1)
{
cp=rp1->cause_chain;
rp1->lastflag=1;
while(cp)
{
rp2=KnowledgeBase;
while(rp2)
{
//若该规则的结论是某规则的条件,则将该规则置为非结论规则
if(strcmp(rp2->result,cp->cause)==0)
rp2->lastflag=0;
rp2=rp2->next;
}
cp=cp->next;
}
rp1=rp1->next;
}
}
//创建知识库
void creatKB()
{
//if(KnowledgeBase)
// {printf("知识库已创建!\n");return;}
FILE *fp;
struct CAUSE_TYPE *cp=NULL;
struct RULE_TYPE *rp=NULL;
int i,j;
char sp[80];
char ch;
freeKB(KnowledgeBase);
freeKB(Used);
KnowledgeBase=Used=NULL;
if((fp=fopen("c:\\rule.dat","r"))==NULL)
{
printf("\n知识库不存在!\n");
printf("请输入新的规则,以创建知识库!\n");
//for输入新知识库规则
for(i=1;;i++)
{
printf("\n*****************第(%d)条规则***********************",i);
printf("\n**结论:(是/会/有)");
//输入规则结论
gets(sp);
if(*sp=='\0') break;
rp=(struct RULE_TYPE *)malloc(sizeof(rp));
rp->result=(char *)malloc(sizeof(sp));
strcpy(rp->result,sp);
rp->cause_chain=NULL;
rp->next=KnowledgeBase;
KnowledgeBase=rp;
//输入规则的条件
for(j=1;;j++)
{
printf("\n**条件(%d):(是/会/有)",j);
gets(sp);
if(*sp=='\0') break;
cp=(struct CAUSE_TYPE *)malloc(sizeof(cp));
cp->cause=(char *)malloc(sizeof(sp));
strcpy(cp->cause,sp);
cp->next=rp->cause_chain;
rp->cause_chain=cp;
}
}
if(!KnowledgeBase)
{
printf("\n警告!知识库中没有任何规则!!\n");
return;
}
printf("\n需要保存已建立的知识库吗?(Y/N)?");
while(!strchr("YyNn",ch=getchar()));//?
if(ch=='Y'||ch=='y')
if((fp=fopen("C:\\rule.dat","w"))==NULL)
{
printf("\n写文件有错误!\n");
exit(1);
}
else
{
//保存已建立的知识库
rp=KnowledgeBase;
while(rp)
{
fputs(rp->result,fp);
fputc('\n',fp);//"\n"为结论或事实的结束符
cp=rp->cause_chain;
while(cp)
{
fputs(cp->cause,fp);
fputc('\n',fp);
cp=cp->next;
}
fputs("\\\n",fp);//"\"是一条规则的结束符
rp=rp->next;
}
fclose(fp);
}
}
else
{
//若知识库文件已存在,则读入所有的规则,建立知识库
while(!feof(fp))
{
fgets(sp,80,fp);
if(*sp=='\\') break;
rp=(struct RULE_TYPE *)malloc(sizeof(rp));
rp->result=(char *)malloc(i=strlen(sp));
sp[i-1]='\0';
strcpy(rp->result,sp);
rp->cause_chain=NULL;
rp->next=KnowledgeBase;
KnowledgeBase=rp;
fgets(sp,80,fp);
while(*sp!='\\')
{
cp=(struct CAUSE_TYPE *)malloc(sizeof(cp));
cp->cause=(char *)malloc(i=strlen(sp));
sp[i-1]='\0';
strcpy(cp->cause,sp);
cp->next=rp->cause_chain;
rp->cause_chain=cp;
fgets(sp,80,fp);
}
}
fclose(fp);
}
//给知识库中的所有结论规则打上标记
markKB();
}
//输入已知条件的子程序
void inputDB()
{
//if(!KnowledgeBase)
// {printf("规则库不存在!!!\n"); return;}
int i;
char sp[80];
struct CAUSE_TYPE *cp;
//释放条件链表和结论链表
freeDB(DataBase);
freeDB(Conclusion);
DataBase=Conclusion=NULL;
printf("\n*****请输入已知事实:\n");
for(i=1;;i++)
{
printf("\n**条件(%d):(是/会/有)",i);
gets(sp);
if(*sp=='\0') break;
cp=(struct CAUSE_TYPE *)malloc(sizeof(cp));
cp->cause=(char *)malloc(sizeof(sp));
strcpy(cp->cause,sp);
cp->next=DataBase;
DataBase=cp;
}
//printf("已知事实为:");
if(DataBase=='\0')
printf("已知事实为空空空空空!");
else
{
printf("已知事实已读入,可以用think命令推理了!");
//for(cp=DataBase;cp!='\0';cp=cp->next)
// printf("%s ",cp->cause);
}
printf("\n");
}
//在条件链表及结论链表中查证字符串sp是否存在,若存在返回1,否则返回0
int FindCause(char *sp)
{
struct CAUSE_TYPE *cp2;
cp2=DataBase;
while(cp2)
if(strcmp(sp,cp2->cause)==0) return(1);
else cp2=cp2->next;
cp2=Conclusion;
while(cp2)
if(strcmp(sp,cp2->cause)==0) return(1);
else cp2=cp2->next;
return(0);
}
//推理机子程序
void think()
{
if(!DataBase)
{printf("没有已知事实!!!\n"); return;}
struct RULE_TYPE *rp1,*rp2;
struct CAUSE_TYPE *cp1;
int RuleCount,i;
char sp[80];
//把规则链表和已使用规则链表连接起来
if(Used)
{
//rp1=Used;
//while(rp1->next) rp1=rp1->next;
//rp1->next=KnowledgeBase;
//KnowledgeBase=Used;
//Used=NULL;
rp1=KnowledgeBase;
while(rp1) rp1=rp1->next;
rp1=Used;
Used=NULL;
}
if(Conclusion)
{
freeDB(Conclusion);
Conclusion=NULL;
}
do
{
RuleCount=0;
rp1=KnowledgeBase;
while(rp1)
{
cp1=rp1->cause_chain;
//取出一条规则的条件部分,检查是不全部为已知
while(cp1)
if(FindCause(cp1->cause)==0)//若有条件未知,则跳出该规则
break;
else cp1=cp1->next;//若该条件已知,则查找下一条件是否已知
if(cp1)//若cp1不为空,则该规则的条件不是全部已知,考查下一条规则
{
rp2=rp1;
rp1=rp1->next;
}
else if(FindCause(rp1->result)==0)//该规则的条件均满足,且得出的是新事实
{
//将新事实保存到conlusion中
cp1=(struct CAUSE_TYPE *)malloc(sizeof(cp1));
cp1->cause=(char *)malloc(sizeof(rp1->result));
strcpy(cp1->cause,rp1->result);
cp1->next=Conclusion;
Conclusion=cp1;
//(得出了新结论)将该规则从知识库中取出,插入已使用规则链表
rp2=rp1->next;
rp1->next=Used;
Used=rp1;
rp1=rp2;
RuleCount++;
if(Used->lastflag==1)
{
RuleCount=0;
break;
}
}
else
{
rp2=rp1;
rp1=rp1->next;
}
}
}while(RuleCount>0); //do while
if(!Conclusion||Used->lastflag==0)
{
printf("\n已知事实不充分!请输入补充事实:\n");
cp1=DataBase;
//显示已输入的事实
for(i=1;cp1;i++)
{
printf("\n**条件(%d):(是/会/有)%s",i,cp1->cause);
cp1=cp1->next;
}
//输入补充事实
for(;;i++)
{
printf("\n**条件(%d):(是/会/有)",i);
gets(sp);
if(*sp=='\0') break;
cp1=(struct CAUSE_TYPE *)malloc(sizeof(cp1));
cp1->cause=(char *)malloc(sizeof(sp));
strcpy(cp1->cause,sp);
cp1->next=DataBase;
DataBase=cp1;
}
}
else printf("\n这个动物:(是/会/有)%s\n",Conclusion->cause);
}
//对推理结果进行解释
void explain()
{
struct RULE_TYPE *rp;
struct CAUSE_TYPE *cp;
int i;
rp=Used;
i=0;
if(rp=='\0') {printf("没有可以解释的!!!\n"); return;}
while(rp)
{
printf("\n*这个动物(是/会/有)%s,因为:\n",rp->result);
cp=rp->cause_chain;
while(cp)
{
printf("**(%d)--它(是/会/有)%s\n",++i,cp->cause);
cp=cp->next;
}
rp=rp->next;
}
}
void copyKB(struct RULE_TYPE *rp,struct RULE_TYPE *KB)
{
struct CAUSE_TYPE *cp,*cp1;
struct RULE_TYPE *rp1,*rp2,*rp3;
rp1=KB;
while(rp1)
{
rp2=(struct RULE_TYPE *)malloc(sizeof(rp2));
rp2->result=(char *)malloc(sizeof(rp1->result));
strcpy(rp2->result,rp1->result);
cp=rp1->cause_chain;
while(cp)
{
cp1=(struct CAUSE_TYPE *)malloc(sizeof(cp1));
cp1->cause=(char *)malloc(sizeof(cp->cause ));
strcpy(cp1->cause,cp->cause );
cp=cp->next;
}
rp2->lastflag=rp1->lastflag ;
if(!rp)
rp=rp2;
else
{
rp3=rp;
while(rp3->next)
rp3=rp3->next;
rp3->next=rp2;
}
rp1=rp1->next ;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -