CLIPS - 从事实列表中获取特定模板的事实
CLIPS - Getting facts of a specific template from fact-list
我有 (Student (Name x) (Age y))
这样的模板。我可以通过使用以下命令检查名为 Name
的插槽的所有事实来获取 Name
的值:
EnvGetFactList(theEnv, &factlist, NULL);
if (GetType(factlist) == MULTIFIELD)
{
end = GetDOEnd(factlist);
multifieldPtr = GetValue(factlist);
for (i = GetDOBegin(factlist); i <= end; i++)
{
EnvGetFactSlot(theEnv,GetMFValue(multifieldPtr, i),"Name",&theValue);
buf = DOToString(theValue);
printf("%s\n", buf);
}
}
我想检查这个事实是否属于 Student
类型。如果是,则获取 Name
插槽的值。
我想我应该使用 EnvFactDeftemplate
但我无法让它工作。这是我的代码
templatePtr = EnvFindDeftemplate(theEnv, "Student");
templatePtr = EnvFactDeftemplate(theEnv,templatePtr);
EnvGetFactSlot(theEnv,&templatePtr,"Name",&theValue);
但我得到以下 运行 时间错误:Segmentation fault (core dumped)
。问题出在哪里?
EnvGetFactSlot 需要指向事实的指针,而不是指向 deftemplate 的指针。使用 EnvGetNextFact 函数之一而不是 EnvGetFactList 来迭代事实也更容易。这是一个工作示例:
int main()
{
void *theEnv;
void *theFact;
void *templatePtr;
DATA_OBJECT theValue;
theEnv = CreateEnvironment();
EnvBuild(theEnv,"(deftemplate Student (slot Name))");
EnvBuild(theEnv,"(deftemplate Teacher (slot Name))");
EnvAssertString(theEnv,"(Student (Name \"John Brown\"))");
EnvAssertString(theEnv,"(Teacher (Name \"Susan Smith\"))");
EnvAssertString(theEnv,"(Student (Name \"Sally Green\"))");
EnvAssertString(theEnv,"(Teacher (Name \"Jack Jones\"))");
templatePtr = EnvFindDeftemplate(theEnv,"Student");
for (theFact = EnvGetNextFact(theEnv,NULL);
theFact != NULL;
theFact = EnvGetNextFact(theEnv,theFact))
{
if (EnvFactDeftemplate(theEnv,theFact) != templatePtr) continue;
EnvGetFactSlot(theEnv,theFact,"Name",&theValue);
EnvPrintRouter(theEnv,STDOUT,DOToString(theValue));
EnvPrintRouter(theEnv,STDOUT,"\n");
}
EnvPrintRouter(theEnv,STDOUT,"-------------\n");
for (theFact = EnvGetNextFactInTemplate(theEnv,templatePtr,NULL);
theFact != NULL;
theFact = EnvGetNextFactInTemplate(theEnv,templatePtr,theFact))
{
EnvGetFactSlot(theEnv,theFact,"Name",&theValue);
EnvPrintRouter(theEnv,STDOUT,DOToString(theValue));
EnvPrintRouter(theEnv,STDOUT,"\n");
}
}
我有 (Student (Name x) (Age y))
这样的模板。我可以通过使用以下命令检查名为 Name
的插槽的所有事实来获取 Name
的值:
EnvGetFactList(theEnv, &factlist, NULL);
if (GetType(factlist) == MULTIFIELD)
{
end = GetDOEnd(factlist);
multifieldPtr = GetValue(factlist);
for (i = GetDOBegin(factlist); i <= end; i++)
{
EnvGetFactSlot(theEnv,GetMFValue(multifieldPtr, i),"Name",&theValue);
buf = DOToString(theValue);
printf("%s\n", buf);
}
}
我想检查这个事实是否属于 Student
类型。如果是,则获取 Name
插槽的值。
我想我应该使用 EnvFactDeftemplate
但我无法让它工作。这是我的代码
templatePtr = EnvFindDeftemplate(theEnv, "Student");
templatePtr = EnvFactDeftemplate(theEnv,templatePtr);
EnvGetFactSlot(theEnv,&templatePtr,"Name",&theValue);
但我得到以下 运行 时间错误:Segmentation fault (core dumped)
。问题出在哪里?
EnvGetFactSlot 需要指向事实的指针,而不是指向 deftemplate 的指针。使用 EnvGetNextFact 函数之一而不是 EnvGetFactList 来迭代事实也更容易。这是一个工作示例:
int main()
{
void *theEnv;
void *theFact;
void *templatePtr;
DATA_OBJECT theValue;
theEnv = CreateEnvironment();
EnvBuild(theEnv,"(deftemplate Student (slot Name))");
EnvBuild(theEnv,"(deftemplate Teacher (slot Name))");
EnvAssertString(theEnv,"(Student (Name \"John Brown\"))");
EnvAssertString(theEnv,"(Teacher (Name \"Susan Smith\"))");
EnvAssertString(theEnv,"(Student (Name \"Sally Green\"))");
EnvAssertString(theEnv,"(Teacher (Name \"Jack Jones\"))");
templatePtr = EnvFindDeftemplate(theEnv,"Student");
for (theFact = EnvGetNextFact(theEnv,NULL);
theFact != NULL;
theFact = EnvGetNextFact(theEnv,theFact))
{
if (EnvFactDeftemplate(theEnv,theFact) != templatePtr) continue;
EnvGetFactSlot(theEnv,theFact,"Name",&theValue);
EnvPrintRouter(theEnv,STDOUT,DOToString(theValue));
EnvPrintRouter(theEnv,STDOUT,"\n");
}
EnvPrintRouter(theEnv,STDOUT,"-------------\n");
for (theFact = EnvGetNextFactInTemplate(theEnv,templatePtr,NULL);
theFact != NULL;
theFact = EnvGetNextFactInTemplate(theEnv,templatePtr,theFact))
{
EnvGetFactSlot(theEnv,theFact,"Name",&theValue);
EnvPrintRouter(theEnv,STDOUT,DOToString(theValue));
EnvPrintRouter(theEnv,STDOUT,"\n");
}
}