📄 expertsys.c
字号:
/* An improved expert system that finds multiple goals and displays reasoning*/
#include "stdio.h"
#include "alloc.h"
#define MAX 100
struct attribute {
char attrib[80];
struct attribute *next;/*use linked list */
} at;
struct object {
char name[80];
struct attribute *alist;/*pointer to list of attributes */
} ob;
struct rejected_object{
char name[80];
char attrib[80];/*attribute that caused rejection*/
char condition;/*should it or shouldn't it have been found */
} rj;
struct rejected_object r_base[MAX];
struct object k_base[MAX];/*holds the knowledge base */
int l_pos=-1;/* location of top of k base */
int r_pos=-1;/*location of top of reject base */
struct attribute *yes,*no;/* used for yes and no lists */
struct attribute *yesnext,*nonext;
main()
{
char ch;
no=yes='\0';
do{
free_trails();
ch=menu();
switch(ch){
case 'e':enter();
break;
case 'q':query();
break;
case 's':save();
break;
case 'l':load();
}
}while(ch!='x');
}
free_trails()
{
struct attribute *p;
while(yes){
p=yes->next;
free(yes);
yes=p;
}
while(no){
p=no->next;
free(no);
no=p;
}
r_pos=-1;
}
/* input an object and its list of attributes */
enter()
{
int t,i;
struct attribute *p,*oldp;
for (;;){
t=get_next();/*get the index of the next */
/*available object in k_base */
if(t==-1){
printf("Out of list space.\n");
return;
}
printf("Object name: ");
gets(k_base[t].name);
if(!*k_base[t].name){
l_pos--;
break;
}
p=(struct attribute *) malloc(sizeof(at));
if(p=='\0'){
printf("Out of memory.\n");
return;
}
k_base[t].alist=p;
for(i=0;i<sizeof(p->attrib);i++)p->attrib[i]=' ';
printf("Enter attributes (RETURN to quit)\n");
for(;;){
printf(": ");
gets(p->attrib);
if(!p->attrib[0])break;
oldp=p;
p->next=(struct attribute *)malloc(sizeof(at));
if(p->next=='\0'){
printf("Out of memory.\n");
return;
}
p=p->next;
p->next='\0';
for(i=0;i<sizeof(p->attrib);i++)p->attrib[i]=' ';
}
oldp->next='\0';
}
}
/* inquire information from the expert */
query()
{
int t;
char ch;
struct attribute *p;
for(t=0;t<=l_pos;t++){
p=k_base[t].alist;
if(try(p,k_base[t].name)){
printf("%s fits current description\n",k_base[t].name);
printf("continue? (Y/N):");
ch=tolower(getche());
printf("\n");
if(ch=='n') return;
}
}
printf("No (more) object(s) found\n");
}
/* try an object */
try(p,ob)
struct attribute *p;
char *ob;
{
char answer;
struct attribute *a,*t;
if(!trailno(p,ob)) return 0;
if(!trailyes(p,ob)) return 0;
while(p){
/*if already been asked then move on to next attribute */
if(ask(p->attrib)){
printf("is/does/has it %s? ",p->attrib);
answer=tolower(getche());
printf("\n");
a=(struct attribute *)malloc(sizeof(at));
if(!a){
printf("out of memory\n");
return;
}
a->next='\0';
switch(answer){
case 'n':
strcpy(a->attrib,p->attrib);
if(!no){
no=a;
nonext=no;
}
else{
nonext->next=a;
nonext=a;
}
reject(ob,p->attrib,'n');
return ;
case 'y':
strcpy(a->attrib,p->attrib);
if(!yes){
yes=a;
yesnext=yes;
}
else{
yesnext->next=a;
yesnext=a;
}
p=p->next;
break;
case 'w':/* why? */
reasoning(ob);
break;
}
}
else p=p->next;
}
return 1;
}
/* see if it has any attributes known not to be part of the
object by checking the no list */
trailno(p,ob)
struct attribute *p;
char *ob;
{
struct attribute *a,*t;
a=no;
while(a){
t=p;
while(t){
if(!strcmp(t->attrib,a->attrib)){
reject(ob,t->attrib,'n');
return 0;/*does hve a negative attribute */
}
t=t->next;
}
a=a->next;
}
return 1;
}
/* see if it has all attributes known
to be part of the object by checking the yes list */
trailyes(p,ob)
char *ob;
{
struct attribute *a,*t;
char ok;
a=yes;
while(a){
ok=0;
t=p;
while(t){
if(!strcmp(t->attrib,a->attrib)){
ok=1;/*does have a needed attribute */
}
t=t->next;
}
if(!ok){
reject(ob,a->attrib,'y');
return 0;
}
a=a->next;
}
return 1;
}
/* see if attribute already asked */
ask(attrib)
char *attrib;
{
struct attribute *p;
p=yes;
while(p && strcmp(attrib,p->attrib))
p=p->next;
if(!p)return 1;/* false if end of list */
else return 0;
}
/* show why a line of reasoning is being followed */
reasoning(ob)
char *ob;
{
struct attribute *t;
int i;
printf("Trying %s\n",ob);
if(yes)
printf("it is/has/does:\n");
t=yes;
while(t){
printf("%s\n",t->attrib);
t=t->next;
}
if(no)printf("it is/has/does not:\n");
t=no;
while(t){
printf("%s\n",t->attrib);
t=t->next;
}
for(i=0;i<=r_pos;i++){
printf("%s is rejected because ",r_base[i].name);
if(r_base[i].condition=='n')
printf("%s is not an attribute.\n",r_base[i].name);
else
printf("%s is a required attribute.\n",r_base[i].attrib);
}
}
/* place rejected object into database */
reject (ob,at,cond)
char *ob,*at,cond;
{
r_pos++;
strcpy(r_base[r_pos].name,ob);
strcpy(r_base[r_pos].attrib,at);
r_base[r_pos].condition=cond;
}
/* get next free index in k_base array */
get_next()
{
l_pos++;
if(l_pos<MAX)return l_pos;
else return -1;
}
menu()
{
char ch;
printf("(E)nter,(Q)uery,(S)ave,(L)oad,e(X)it\n");
do{
printf("choose one: ");
ch=tolower(getche());
}while(!is_in(ch,"eqslx"));
printf("\n");
return ch;
}
save()
{
int t,x;
struct attribute *p;
FILE *fp;
if((fp=fopen("expert.dat","w"))==0){
printf("cannot open file\n");
return;
}
printf("saving knowledge base\n");
for(t=0;t<=l_pos;++t){
for(x=0;x<sizeof(k_base[t].name);x++)
putc(k_base[t].name[x],fp);
p=k_base[t].alist;/*原来是k_base[c].alist;下标是c,可以根本没定义变量c. */
while(p){
for(x=0;x<sizeof(p->attrib);x++)
putc(p->attrib[x],fp);
p=p->next;
}
/* end of list marker */
for(x=0;x<sizeof(p->attrib);x++)putc('\o',fp);
}
putc(0,fp);
fclose(fp);
}
load()
{
int t,x;
struct attribute *p,*oldp;
FILE *fp;
if((fp=fopen("expert.dat","r"))==0){
printf("cannot open file\n");
return;
}
printf("loading knowledge base\n");
/*free any old lists */
clear_kbase();
for(t=0;t<MAX;++t){
if((k_base[t].name[0]=getc(fp))==0)break;
for(x=1;x<sizeof(k_base[t].name);x++)
k_base[t].name[x]=getc(fp);
k_base[t].alist=(struct attribute *)malloc(sizeof(at));
p=k_base[t].alist;
if(!p){
printf("Out of memory\n");
return;
}
for(;;){
for(x=0;x<sizeof(p->attrib);x++)
p->attrib[x]=getc(fp);
oldp=p;/*加上此行*/
if(!p->attrib[0]){
oldp->next='\0';
break;/* end of list */
}
p->next=(struct attribute *)malloc(sizeof(at));
if(!p->next){
printf("out of memory\n");
break;
}
oldp=p;
p=p->next;
}
}
fclose(fp);
l_pos=t-1;
}
clear_kbase()
{
int t;
struct attribute *p,*p2;
for(t=0;t<=l_pos;t++){
p=k_base[t].alist;
while(p){
p2=p->next;
free(p);
p=p2;
}
}
}
is_in(ch,s)
char ch,*s;
{
while(*s)
if(ch==*s++)return 1;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -