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");
     }
  }