0

我有以下规则Yacc,我想从中创建一个链表,但是当我尝试打印它时,我一直在获取列表中的最后一个节点:

node_list
:                                                   {$$=NULL;}
| node_list node                                    {if ($1 != NULL) $1->next=$2; $$=$2;    }
;

我的理解是,例如,如果这是列表

node1
node2
node3

Yacc将其扩展为

node_list node3
node_list node2 node3
ndoe_list node1 node2 node3
NULL node1 node2 node3

但由于我得到了上面代码的最后一个节点,所以我的猜测是列表以崇高的顺序展开

node_list node1
node_list node2 node1
ndoe_list node3 node2 node1
NULL node3 node2 node1

那么我尝试使用以下代码:

node_list
:                                                   {$$=NULL;}
| node_list node                                    {$2->next=$1; $$=$2 ;   }
;

我知道在每种情况下我都会返回列表中的最后一个节点,这就是为什么我只得到一个节点。所以我尝试了这段代码:

node_list
:                                                   {$$=NULL;}
| node_list node                                    {$$=linkXmlNode($1,$2);}
;

linkXmlNode在哪里

XmlNode * linkXmlNode(XmlNode * first, XmlNode * second)
{
XmlNode * temp = second;
while (second->next != NULL) 
    second=second->next;

second->next=first; 
return temp;
}

现在我让最后一个节点每次重复 3 次。我也尝试了另一个方向,但现在我得到了第一个节点:

XmlNode * linkXmlNode(XmlNode * first, XmlNode * second)
{
if (first == NULL) return second;
XmlNode * temp = first;
while (first->next != NULL)
    first= first->next;
first->next = second;
return temp
}

如果有人知道如何Yacc扩展列表,那就太好了。


编辑:回答 我的打印功能有误,上述功能有效。错误是我没有打印迭代器,而是打印参数,因此多次获得同一个节点。

4

2 回答 2

1
if ($1 != NULL) $1->next=$2; $$=$2;

返回$2,但$2不指向$1; 你指$1的是$2相反,但你没有回来$1,所以什么都不会知道。(什么东西,只给定$2,应该知道如何得到,$1因为它只$1知道这种关系?)

$2->next=$1; $$=$2

应该给你你的清单,但顺序相反。要以其他顺序获取它,您需要同时传递一个头指针和尾指针,或者在列表上插入一个附加规则以在传递它之前反转列表。

您的第三次尝试在链接方面最接近正确;如果您获得相同的数据,它留下了如何复制列表元素的问题。请注意,yacc它本身对您的列表一无所知;根本不会“扩展”列表,这就是您的代码应该做的。

(我不清楚你的最新评论是否表明你已经解决了你的问题。)

于 2012-05-11T20:15:38.057 回答
0

你得到以下产品:

 => nodeList
nodeList node1 => nodeList
nodeList node2 => nodeList
nodeList node3 => nodeList

因此,在您的第一种情况下,您的列表从 null 开始,然后将 node1 附加到它,然后将 node2 附加到它,然后将 node3 附加到它。我要说的是,您将节点链接到列表末尾的代码应该会导致最终列表按升序排列,但我刚刚看到您的编辑表明它一直都是正确的。

于 2012-05-11T20:18:20.633 回答