2014-09-23 35 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