Search code examples
c++clipsexpert-system

CLIPS - Getting facts of a specific template from fact-list


I have templates like (Student (Name x) (Age y)). I can get values of Name by checking all facts for a slot named Name using the following:

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

I'd like to check if this fact is of type Student or not. If yes, get value of Name slot. I think I should use EnvFactDeftemplate but I can't get it to work. Here is my code

templatePtr = EnvFindDeftemplate(theEnv, "Student");
templatePtr = EnvFactDeftemplate(theEnv,templatePtr);
EnvGetFactSlot(theEnv,&templatePtr,"Name",&theValue);

But I get the following run-time errror: Segmentation fault (core dumped). Where is the problem?


Solution

  • EnvGetFactSlot is expecting a pointer to a fact, not a pointer to a deftemplate. It's also easier to use one of the EnvGetNextFact functions rather than EnvGetFactList to iterate over the facts. Here's a working example:

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