2014-09-23 34 views
1

我尝试使用基于GNU Prolog的Prolog脚本实现C接口。我的问题是获取嵌套Prolog列表的单个元素。在C接口中从Prolog获取列表元素

实际上我的C代码看起来像

... 
int func; 
PlTerm arg[10]; 
PlTerm *sol_gb; 
PlBool res; 
int nmb; 
char *strHead; 
char *strTail; 
PlLong nummero; 
PlTerm pl_nummero; 

Pl_Start_Prolog(argc, argv); 


Pl_Query_Begin(PL_TRUE); 

arg[0] = Pl_Mk_String(strRName); 
arg[1] = Pl_Mk_Variable(); 
arg[2] = Pl_Mk_Variable(); 
arg[3] = Pl_Mk_String("true"); 

res = Pl_Query_Call(func, 4, arg); 

sol_gb = Pl_Rd_List(arg[2]); 
nmb = Pl_List_Length(sol_gb[0]); 

strHead = Pl_Write_To_String(sol_gb[0]);  
printf("strHead = %s\n",strHead); 
strTail = Pl_Write_To_String(sol_gb[1]);  
printf("strTail = %s\n",strTail); 
... 

序言列表arg中返回[2]看起来像

[ [ Spezial Bolognese, 
    [2, ,Zwiebeln,300,gramm,Hackfleisch,10, ,Tomaten, 
    100,ml,Sahne,500,gramm,Spaghetti] 
    ], 
    [ Spaghetti Bolognese, 
    [2, ,Zwiebeln gehackt,300,gramm,Hackfleisch,10, ,Fleischtomaten, 
    100,ml,Sahne,500,gramm,Spaghetti] 
    ] 
] 

转换的输出转换成一个字符串是

strHead = [Spezial Bolognese,[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch, 
      10, ,Fleischtomaten,100,ml,Sahne,500,gramm,Spaghetti]] 

strTail = [[Spaghetti Bolognese,[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch, 
      10, ,Fleischtomaten,100,ml,Sahne,500,gramm,Spaghetti]]] 

所以我认为,我“几乎在那里”,但因为我不得不重新激活我的C知识,我没有得到解决方案如何进入列表的下一个级别最后得到每个元素作为字符串(“Spezial Bolognese”,下一步:“2”,“Zwiebeln”等)。

我该如何逐步浏览C中的Prolog列表?

我会很高兴每一个提示,再次感谢你!

回答

2

要从C代码中获取列表的内容,您可以使用2种功能。

第一可能性(简单,因为该列表被看作是一个扁平的物体,但需要更多的存储器,并且需要适当的列表中,即,不为未通过[]终止列表工作)

int Pl_Rd_Proper_List_Check(PlTerm the_prolog_list, PlTerm *the_array_receiving_arguments); 

此功能接收到一个数组(这取决于你确保它足够大),将列表中的每个元素存储在数组中并返回元素的总数。例如:

PlTerm list = ...some Prolog list... 
int nElem = Pl_List_Length(list); 
PlTerm *elem = (PlTerm *) calloc(nElem, sizeof(PlTerm)); 
Pl_Rd_Proper_List_Check(list, elem); 
int i; 
for(i = 0; i < nElem; i++) { 
    // here there is an argument in elem[i], let's print it 
    Pl_Write(elem[i]); 
} 

第二可能性(更一般的,但看到一个列表作为链表,每个单元包含头部和尾部(列表))

PlTerm *Pl_Rd_List(PlTerm the_prolog_list); 

此函数返回的2数组元素对应于接收列表的头部和尾部。应该在列表的每个元素上调用该函数;要么知道元素的数量,要么测试列表的末尾(例如等待列表atom []的结尾)。这里是一个代码,它可以在上面的循环中进行,因为我们知道列表的第二个参数是嵌套列表。

PlTerm list = ... some Prolog list...; 
while(!Pl_Un_Atom(Pl_Atom_Nil(), list)) { 
    PlTerm *lst_arg = Pl_Rd_List(list); // [0] = head element, [1] = tail list 
    // here there is an argument in lst_arg[0], let's print it 
    Pl_Write(lst_arg[0]); 
    list = lst_arg[1]; 
} 

在你的榜样,第一个列表的样子:

[ 'Spezial Bolognese', 
    [2,' ','Zwiebeln', 
    300,'gramm','Hackfleisch', 
    10,' ','Tomaten', 
    100,'ml','Sahne', 
    500,'gramm','Spaghetti'] 
] 

所以第二个元素是一个嵌套列表。下面的代码使用用于上述列表中的第一种方法(其具有2个元件),对于嵌套列表的第二种方法:

nElem = Pl_List_Length(sol_gb[0]); 
PlTerm *elem = (PlTerm *) calloc(nElem, sizeof(PlTerm)); 
Pl_Rd_Proper_List_Check(sol_gb[0], elem); 
int i; 
for(i = 0; i < nmb; i++) { 
    if (i != 1) { 
     Pl_Write(elem[i]); 
     printf("\n"); 
    } else {    // we know it is a list 
     printf("("); 
     PlTerm list = elem[i]; 
     while(!Pl_Un_Atom(Pl_Atom_Nil(), list)) { 
      PlTerm *lst_arg = Pl_Rd_List(list); // [0] = head element, [1] = tail list 
      printf(" "); 
      Pl_Write(lst_arg[0]); 
      list = lst_arg[1]; 
     } 
     printf(")\n"); 
    } 
} 

这里应该是输出

Spezial Bolognese 
(2 Zwiebeln 300 gramm Hackfleisch 10 Tomaten 100 ml Sahne 500 gramm Spaghetti) 
+0

很多,非常感谢! :)我会测试它,然后给出反馈。 - - 有用!!呃,我真的很感谢你的帮助! – kiw 2014-09-25 07:33:33

0

您给出的列表清单的示例代码听起来像是知识表示的一个非常糟糕的选择的教科书示例。我强烈建议你将它改为更具说明性的表示。喜欢的东西:

% pizza(Name, Steps) 
pizza('Spezial Bolognese', ...). 
... 

其中Steps可能是step(...)项目列表。这可能会使处理信息更容易,更高效。例如,在Prolog方面,您可以使用标准的arg/3谓词来访问某个步骤中的特定元素。使用列表,除了列表头以外,除了遍历它们之外别无选择。

+0

感谢您的意见。但即使对于一个简单的Prolog列表,你是否知道如何从C接口中的列表中获取单个元素? – kiw 2014-09-24 09:08:18