1

そのため、オブジェクトをインスタンス化するときに、リストを頭から尾 (通常) または尾から頭 (逆) にコピーすることを選択できるコピー コンストラクタを実装しようとしています。これで、コピー コンストラクターを使用すると、逆の状態になっても、常に先頭から末尾までコピーされます。

これが私のヘッダーファイルです:

#include <iostream>
#include "Student.h"
#include "Node.h"
using namespace std;

class List {

public:
    List(); // Default constructor
    List(const List&); // Copy constructor (2-in-1, see lab sheet)
    ~List(); // Destructor

    bool isEmpty(); // List is empty: TRUE or FALSE?
    int getNumNodes() {return numNodes;} // How many Nodes in List

    void append(Student *); // Append new Node to head or tail of List
    void insert(Student *); // Inserts new Node in the
                            // Appropriate location in List
    void deleteNode(string); //Search for and delete specific Node
    void displayAscending();// Display List HEAD to TAIL
    void displayDescending(); // Display List TAIL to HEAD

    // input Student::data into Student pointer.
    void input(Student*, string, string, string, string, string);

    Node *getHead() const {return head;} // ptr to head. 
    Node *getTail() const {return tail;} //ptr to tail.

private:
    void printer(Node *); //recursive function w/in displayDescending()
    Node *head;
    Node *tail;

    bool empty;
    bool forward; // forward = head-to-tail i.e. true
    int numNodes; // number of nodes in the list 
};

これが私のコピーコンストラクタです。

List::List(List &list) { // Copy constructor
    head = NULL; // Head pointer set to NULL initially
    tail = NULL; // Tail pointer set to NULL initially

    empty = true;
    forward = true; // Copies head-to-tail by default.
    numNodes = 0;

    string flag; // Stores prompt value.
    cout << "Copy from head to tail? (y/n): ";
    cin >> flag; // prompt for user.
    if(flag == "n")
        forward = false;

    Node *curr = NULL; //initialize curr in function scope.

    if(flag == "n") {
        forward = false;
        curr = list.getTail(); // curr points to list tail.
        cout << "Copying in reverse order...\n" << endl;
    } else { // forward == true
        curr = list.getHead(); // curr points to list head.
        cout << "Copying from head-to-tail...\n" << endl;
    } // end if/else 

    while(curr) {
        string f = ( curr->getData()->getFirst()  );
        string m = ( curr->getData()->getMid()    );
        string l = ( curr->getData()->getLast()   );
        string s = ( curr->getData()->getSocial() );
        string a = ( curr->getData()->getAge()    );

        Node *nodePtr = NULL; // a node that's pointing 
                              // using it to point to creation of
                              // a new node
        Student *stuPtr = new Student; // creates a stud pointer on
                                       // heap of Student class in
                                       // order to store stud info 
        input(stuPtr,f,m,l,s,a); // input Student::data into stuPtr.      
        append(stuPtr); // append the node with stuPtr to head or tail
                        // of list.

        if(!forward)
            curr = curr->getPrev();
        else
            curr = curr->getNext();
    }  // end while*/
    cout << "Done copying!\n" << endl;
} // end copy constructor

また、リストに追加する方法を確認する必要がある場合は、append() 関数を次に示します。

void List::append(Student *newStudent) {
    Node *newNode = new Node(newStudent); // new Node containing student arg.

    newNode->getData(); // get data of student arg.

    if(isEmpty()) {  // tail=NULL, no list.
        cout << "List is empty. Inserting first Node.\n" << endl;
        head = newNode;
        tail = newNode; // new Node becomes head & tail.
    } else { 
        if(forward) { // append to tail of list.
            tail->setNext(newNode); // NEXT ptr of tail points to newNode.
            newNode->setPrev(tail); // newNode's PREV points to former tail.
            tail = newNode; // newNode becomes the new tail.
        } else { // append to head of list.
            head->setPrev(newNode); // PREV ptr of head points to newNode.
            newNode->setNext(head); // newNode's NEXT points to former head.
            head = newNode; // newNode becomes the new head.
        } // end if/else
    } // end if/else
    numNodes++;
}
4

2 に答える 2

2

あなたが常に頭から尻尾までコピーしているように見える理由は、あなたのコードが空っぽで、一度に複数の方法で同じことをしようとするからです。末尾から先頭にコピーしようとすると、末尾から先頭に新しいリストを書き、末尾から先頭古いリストを読み取ります。これらの 2 つは互いに打ち消し合います。考えてみてください。

引数を作成しようとするとコンパイラ エラーが発生する理由は、作成していないandをconst使用してクエリを実行しているためです。getTail()getHead()const

編集:

設計に戻って、末尾から先頭へのコピーがどのように機能するかを考えてみましょう。これを行うには、基本的に 2 つの方法があります。ヘッド テールを読み取る方法と、テール ツー ヘッドを書き込む方法です。

|                |
v                v
A-B-C-D          A

  |            |
  v            v
A-B-C-D        B-A

    |        |
    v        v
A-B-C-D      C-B-A

      |    |
      v    v
A-B-C-D    D-C-B-A

またはその逆:

      |    |
      v    v
A-B-C-D    D

    |        |
    v        v
A-B-C-D    D-C

  |            |
  v            v
A-B-C-D    D-C-B

|                |
v                v
A-B-C-D    D-C-B-A

Bur両方を実行しようとすると、キャンセルされます。

      |          |
      v          v
A-B-C-D          D

    |          |
    v          v
A-B-C-D        C-D

  |          |
  v          v
A-B-C-D      B-C-D

|          |
v          v
A-B-C-D    A-B-C-D

私たちがしなければならないのは、1つを選択することだけです。最初のものを選択した場合、コピー ctor を変更します。

curr = list.getHead(); // curr points to list head.
cout << "Reading from head-to-tail...\n" << endl;

while(curr) {
  ...
  append(stuPtr); // append the node with stuPtr to head or tail of list.

  curr = curr->getNext();
}  // end while*/

そして、それは機能します。2 番目を選択した場合は、ctor をそのままにして、次のように変更しますappend(...)

if(isEmpty()) {  // tail=NULL, no list.
  cout << "List is empty. Inserting first Node.\n" << endl;
  head = newNode;
  tail = newNode; // new Node becomes head & tail.
} else {
  tail->setNext(newNode); // NEXT ptr of tail points to newNode.
  newNode->setPrev(tail); // newNode's PREV points to former tail.
  tail = newNode; // newNode becomes the new tail.
} // end if/else

一般的に言えば、このような問題を回避する方法は、小さくシンプルに開始し、少しずつ複雑さを追加し、すべてのステップでテストし、最初に新しい機能を個別にテストし、機能しないコードに決して追加しないことです。明らかでないバグを見つける方法は、コードを単純化して、バグのある動作を示す最も単純なバージョンに到達するまで複雑さを少しずつ取り除くことです。または、途中でバグが明らかになる可能性が高くなります。

于 2013-08-16T00:11:18.910 に答える