双指针:指向作为指针的struct成员的指针

时间:2012-12-06 12:06:57

标签: c pointers struct double-pointer

我正在尝试编写一个程序来播放“Pangolin”(如this guy - 它询问是/否问题,沿着二叉树向下走,直到它到达叶节点。然后“猜测”,如果用户说答案是错误的,则询问用户他们在想什么,以及一个区别于错误提示的问题。然后将新数据添加到树中。

这是我的树节点结构。对于包含问题的节点,NodeType为QUESTION_NODE,对于包含“对象”的节点,NodeType为OBJECT_NODE - 这是程序推断用户要考虑的事情。问题节点具有指向子节点的指针 - 一个用于是,一个用于否。

typedef struct _TreeNode {
  NodeType type;
  union {
    char* question;
    char* objectName;
  } nodeString; 
  //children for yes and no answers: will be invalid when type is OBJECT_NODE
  struct _TreeNode* yes;
  struct _TreeNode* no;
} TreeNode;

由于这是一个学习练习,我试图用双指针来做。这是应该向树添加问题节点的函数:

void addData(TreeNode** replace, char* wrongGuess) {
  //create a new object node for what the user was thinking of
  // ... (code to get user input and build the new object node struct) ... //

  //create a new question node so we don't suck at pangolin so much
  // ... (code to get a question from the user and put it in a question node struct) ... //

  //link the question node up to its yes and no
  printf("What is the answer for %s?\n", newObjectName);
  if (userSaysYes()) {
    newQuestionNodePtr->yes = newObjectNodePtr;
    newQuestionNodePtr->no = *replace;
  }
  else {
    newQuestionNodePtr->no = newObjectNodePtr;
    newQuestionNodePtr->yes = *replace;
  }

  //redirect the arc that brought us to lose to the new question
  *replace = newQuestionNodePtr;
}

然后将addData函数称为,因此

void ask(node) {
  //(... ask the question contained by "node" ...)//

  //get a pointer to the pointer that points to the yes/no member pointer
  TreeNode** answerP2p;
  answerP2p = userSaysYes() ? &(node.yes) : &(node.no);

     //(... the user reports that the answer we guessed was wrong ...)//

      puts("I am defeated!");
      //if wrong, pass the pointer to pointer
      addData(answerP2p, answerNode.nodeString.objectName);

我的(大概是错误的)理解是这样的:

在“ask()”中,我向addData传递一个指向“node”的成员“yes”(或者没有)的指针。该成员又是一个指针。当在addData中,我分配给“* replace”时,这应该修改结构,重定向其“是”(或否)成员指针指向我创建的新问题节点。

我已调试并发现newQuestionNode和newObjectNode已成功创建。 newQuestionNode的子项被正确分配。但是,新问题节点未插入树中。 “* replace = newQuestionNodePtr”行没有我期望的效果,“ask”范围中“node”引用的节点没有重定向其子指针。

任何人都能看出我的理解中有什么问题吗?或者也许是我在代码中没有表达出来的方式?对不起,这个问题太长了。

2 个答案:

答案 0 :(得分:1)

您不应将传递给函数的指针声明为双指针。而是将单个指针的地址传递给函数:

TreeNode* answerP2p;
answerP2p = userSaysYes() ? node.yes : node.no;

addData(&answerP2p, answerNode.nodeString.objectName);

答案 1 :(得分:0)

不幸的是,我并没有完全理解Joachim Pileborg上面的回答,但我最终解决了我的问题,我猜这对于新的C-farers来说是一个相当常见的错误[1],所以我会在这里发布它术语

在我从Java到C的仓促过渡中,我告诉自己“好的,结构只是对象没有方法”。评估这种简化的有效性是留给读者的练习。我还将此假设扩展为“当一个参数是一个结构类型时,它会自动通过引用传递”。这显然是假的,但我甚至都没想过。笨。

所以这里真正的问题是我正在为ask()参数传递TreeNode类型为node的变量。整个结构都是通过价值传递的(当然)。当我将answerP2p传递给addData()时,它实际上正常工作,但它正在修改ask() TreeNode的本地副本。我更改了ask()以取TreeNode*而且,有一棵树。

  1. C 我在那里做了什么[1]?