3

2 年生のプログラミング クラスで、病院と病院の医師と患者を表す二重リンク リストのセットを作成するという問題があります。病院には医師のリストがあり、各医師には患者のリストがあります。私の問題は、「hireDoctor」関数を呼び出して医師を病院のリストに追加すると、どういうわけかヘッドポインターが変更されることです。ここに私のコードがあります:

    /* adds a Doctor to the Hospital's list of Doctors */
    void Hospital::hireDoctor(Doctor *doc)
    {
        DoctorNode node;
        node.value = *doc;
        DoctorNode* curr;

        if (drListHead == NULL) {    //if doctor list is empty,
            drListHead = &node;    //insert the node at the beginning
            node.next = NULL;
            node.prev = NULL;
        } else {
            curr = drListHead;
            //traverse list until equal or greater (alphabetical) value is found:
            while (curr->value.getLast().compare(node.value.getLast()) < 0 &&
            curr->value.getFirst().compare(node.value.getFirst()) < 0) {
                curr = curr->next;
            }
            if (curr->prev == NULL) {     //if inserting at the beginning of the list
               drListHead = &node;
               node.prev = NULL;
               node.next = curr;
            } else if (curr->next == NULL) { //if the end of the list has been reached
                curr->next = &node;
                node.prev = curr;
                node.next = NULL;
            } else {              //insert the new DoctorNode in the middle:
                curr->next->prev = &node;
                node.next = curr->next;
                curr->next = &node;
                node.prev = curr;
            }
     }

リスト内の各ノードは構造体として定義されます。

    struct DoctorNode {
      Doctor value;
      DoctorNode *next;
      DoctorNode *prev;
    }

したがって、hireDoctor 関数を一度使用した後、John Smith という名前の医師を「雇う」と、drListHead が John Smith を指していると予想されます。しかし、2 回目に Jane Doe を雇ってこの関数を使用すると、drListHead は関数に入った時点で既にJane Doe を指しているように見えます。どこが変更されているのかわかりません。どんな考えでも大歓迎です!

4

2 に答える 2

1

問題はここにあります:

        if (drListHead == NULL) {    //if doctor list is empty,
            drListHead = &node;    //insert the node at the beginning  <------
            node.next = NULL;
            node.prev = NULL;
        } 

ノードはスタック上で初期化され、終了後、hireDoctorスタックのアドレスを指します。次にhireDoctorノードを呼び出すときは、同じアドレスであるJane Doeを再度ポイントします(これは単なる偶然です)。あなたはこれを必要とします:

            if (drListHead == NULL) {    //if doctor list is empty,
                drListHead = new DoctorNode();    //heap allocation 
                drListHead->next = NULL;
                drListHead->prev = NULL;
            }

ただし、未使用のメモリへの解放を実装する必要があることに注意してください。

于 2012-10-10T13:22:13.520 に答える
0

問題はここにあります。 DoctorNode node; そのようにして、ノードは関数内で可視性を持ちます。関数が終了すると、この変数は破棄されます。破棄された変数は再利用可能な RAM ですが、この RAM が他の何かによって使用されなくなるまで変更されないため、正しい値を保持していると考えられます。次の医師の作成では、いくつかの RAM を要求します。「さりげなく」以前の医師と同じ RAM が無料で、新しい医師に使用されます。つまり、頭が指している ram を書き直したということで、古い医者のすべてのデータも失われています (まあ、データはまだここにありますが、データへのポインターがもうないだけなので、ファイルのどこかで失われます) RAM; これは技術的には「ガベージ」と呼ばれます)。

より良い説明を得るために「可変可視性」を探してください

解決策はポインタに変更することです

DoctorNode node*;

「delete」を呼び出してその RAM を明示的に解放するまで、RAM を予約するために「new」を使用します。「削除」を使用して割り当てられたすべてのポインターを解放せずにドクターを破棄すると、ガベージも作成されます。http://www.codeproject.com/Articles/6555/To-new-is-C-To-malloc-is-C-To-mix-them-is-sinを参照してください

よくある問題は、RAM をガベージでいっぱいにすることです。これは、プログラムや OS のクラッシュを引き起こします。

于 2012-10-10T13:20:31.280 に答える