1

GNU Prolog に基づく 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] に返される Prolog リストは次のようになります。

[ [ 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 リストをステップ実行するにはどうすればよいですか?

私はすべてのヒントをとても嬉しく思います。ありがとうございました!

4

2 に答える 2

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

2 番目の可能性 (より一般的ですが、リストを連鎖リストと見なします。各セルには先頭と末尾 (リスト) が含まれます)

PlTerm *Pl_Rd_List(PlTerm the_prolog_list);

この関数は、受け取ったリストの先頭と末尾に対応する 2 つの要素の配列を返します。この関数は、リストの各要素に対して呼び出す必要があります。要素の数を知っているか、リストの終わりをテストします (たとえば、リスト atom [] の終わりを待っています)。これを行うコードを次に示します (リストの 2 番目の引数がネストされたリストであることがわかっているため、上記のループ内にあることが予想されます。

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 番目の要素はネストされたリストです。次のコードは、上記のリスト (2 つの要素を持つ) に対して最初のメソッドを使用し、ネストされたリストに対して 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 )
于 2014-09-24T15:53:59.573 に答える