0

「センザンコウ」を再生するプログラムを作成しようとしています (この人のように、はい/いいえの質問をし、リーフ ノードに到達するまでバイナリ ツリーをたどります。次に「推測」し、ユーザーが答えが間違っていた場合、ユーザーが何を考えていたのか、それを間違った推測と区別する質問をユーザーに尋ね、新しいデータをツリーに追加します)。

これは、ツリー ノードの my 構造体です。NodeType は、質問を含むノードの場合は QUESTION_NODE、「オブジェクト」を含むノードの場合は OBJECT_NODE です。これは、ユーザーが考えているとプログラムが推測するものです。質問ノードには、子ノードへのポインターがあります。1 つははい、もう 1 つはいいえです。

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()」では、「node」のメンバー「yes」(または「no」) を指すポインターを addData に渡しています。そのメンバーは、ポインターです。addData で "*replace" に割り当てると、構造体が変更され、"yes" (または no) メンバー ポインターが、作成した新しい質問ノードを指すようにリダイレクトされます。

デバッグしたところ、newQuestionNode と newObjectNode が正常に作成されていることがわかりました。newQuestionNode の子は正しく割り当てられています。ただし、新しい質問ノードはツリーに挿入されません。「*replace = newQuestionNodePtr」行には期待した効果がなく、「ask」スコープの「node」によって参照されるノードの子ポインターはリダイレクトされません。

私の理解で何が間違っているのか誰にもわかりますか?それとも、私のコードでそれを正しく表現していない方法でしょうか? 申し訳ありませんが、この質問はとても長いです。

4

2 に答える 2

1

関数に渡すポインターを double ポインターとして宣言しないでください。代わりに、単一のポインターのアドレスを関数に渡します。

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

addData(&answerP2p, answerNode.nodeString.objectName);
于 2012-12-06T12:12:35.643 に答える
0

残念ながら、上記のJoachim Pileborgの回答を完全には理解していませんが、最終的に問題を検討しました。これは、新しいC-farer [1]にとってはかなり一般的な間違いだと思うので、ここに私自身の言葉で投稿します。

JavaからCIへの急いでの移行で、「OK、構造体はメソッドのない単なるオブジェクトです」と自分に言い聞かせまし。この単純化の妥当性を評価することは、読者の練習問題として残されています。また、この仮定を「引数が構造体タイプの場合、参照によって自動的に渡される」に拡張しました。それは明らかに間違っていますが、私はそれについて考えさえしていませんでした。愚か。

したがって、ここでの本当の問題は、引数ask()に型の変数を渡していたことです。この構造体全体が値によって渡されていました(もちろん)。に渡したとき、実際には正しく機能していましたが、のローカルコピーを変更していました。私はaとloを取るように変更しました、木がありました。TreeNodenodeanswerP2paddData()ask()TreeNodeask()TreeNode*

  1. C私はそこで何をしましたか[1]?
于 2012-12-11T16:56:12.430 に答える