简体   繁体   English

双指针:指向作为成员的结构成员的指针

[英]Double pointer: pointer to struct member that is a pointer

I'm trying to write a program to play "Pangolin" (like this guy - it asks yes/no questions, walking down a binary tree until it gets to a leaf node. It then "guesses", and if the user says the answer was wrong, asks the user what they were thinking of and for a question that distinguishes that from the incorrect gues. It then adds the new data to the tree). 我正在尝试编写一个程序来播放“ Pangolin”(像这个家伙一样 -它询问是/否问题,沿着二叉树走直到到达叶节点。然后“猜测”,如果用户说答案是错误的,向用户询问他们在想什么,并提出将其与错误猜测区分开来的问题,然后将新数据添加到树中。

This is the my struct for a tree node. 这是我的树节点结构。 NodeType is QUESTION_NODE for nodes containing a question or OBJECT_NODE for nodes containing an "object" - that is the thing the program deduces the user to be thinking of. 对于包含问题的节点,NodeType为QUESTION_NODE;对于包含“对象”的节点,NodeType为OBJECT_NODE;这是程序推论用户所考虑的事物。 Question nodes have pointers to child nodes - one for yes and one for no. 问题节点具有指向子节点的指针-一个表示是,一个表示否。

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;

As this is a learning exercise, I'm trying to do it with double pointers. 由于这是一项学习练习,因此我正在尝试使用双指针。 Here is the function that is supposed to add a question node to the tree: 这是应该向树中添加问题节点的函数:

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

The addData function is then called thus : 然后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);

My (presumably wrong) understanding is this: 我的(大概是错误的)理解是:

In "ask()", I am passing addData a pointer which points to "node"'s member "yes" (or no). 在“ ask()”中,我向addData传递了一个指向“节点”成员“是”(或否)的指针。 That member is in turn a pointer. 该成员又是一个指针。 When, in addData, I assign to "*replace", this should modify the struct, redirecting its "yes" (or no) member pointer to point to the new question node I have created. 在addData中,当我分配给“ * replace”时,这应该修改结构,将其“是”(或否)成员指针重定向到指向我创建的新问题节点。

I have debugged and found that the newQuestionNode and newObjectNode are created successfully. 我已经调试,发现newQuestionNode和newObjectNode创建成功。 newQuestionNode's children are correctly assigned. 已正确分配newQuestionNode的子级。 However the new question node is not inserted into the tree. 但是,新问题节点未插入树中。 The "*replace = newQuestionNodePtr" line does not have the effect I would expect, and the node referred to by "node" in the "ask" scope does not have its child pointer redirected. “ * replace = newQuestionNodePtr”行没有我期望的效果,并且“ ask”范围中“ node”所引用的节点没有重定向其子指针。

Can anyone see what is wrong in my understanding? 有人能理解我的理解是什么问题吗? Or perhaps a way in which I haven't expressed it right in my code? 还是我未在代码中正确表达的方式? Sorry this question is so long. 抱歉,这个问题太长了。

You should not declare the pointer you pass to the function as a double pointer. 您不应将传递给函数的指针声明为双指针。 Instead pass the address of a single pointer to the function: 而是将单个指针的地址传递给该函数:

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

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

Unfortunately I don't quite understan'd Joachim Pileborg's answer above, but I eventually sussed my problem and I guess it's a fairly common mistake for new C-farers[1], so I'll post it here in my own terms. 不幸的是,我对Joachim Pileborg的回答并不太了解,但是我最终还是怀疑我的问题,我猜这对于新的C员工来说是一个相当普遍的错误,因此我将以我自己的方式发表在这里。

In my hasty transition from Java to CI had told myself "OK, structs are just objects without methods". 在我从Java到CI的匆忙过渡中,我告诉自己:“好, 结构只是没有方法的对象 ”。 Assessing the validity of this simplification is left as an exercise to the reader. 评估这种简化方法的有效性留给读者练习。 I also extended this assumption to "when an argument is of a struct type, it is automatically passed by reference". 我还将这一假设扩展为“当参数为结构类型时,它会自动通过引用传递”。 That's obviously false, but I hadn't even thought about it. 这显然是错误的,但我什至都没有想到。 Stupid. 笨。

So the real problem here is that I was passing ask() a variable of type TreeNode for its node argument. 因此,这里的真正问题是,我在传递ask()一个TreeNode类型的变量作为其node参数。 This entire struct was being passed by value (of course). 整个结构都通过值传递(当然)。 When I passed answerP2p to addData() , it was actually working correctly, but it was modifying ask() 's local copy of the TreeNode . 当我将answerP2p传递answerP2p addData() ,它实际上可以正常工作,但它正在修改ask()TreeNode本地副本。 I changed ask() to take a TreeNode* and lo, there was a tree. 我更改了ask()以使用TreeNode* ,然后发现有一棵树。

  1. C what I did there[1]? C我在那里做了什么[1]?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM