Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 双链表复制构造函数(不能将尾部复制到头部)_C++_Copy Constructor_Doubly Linked List - Fatal编程技术网

C++ 双链表复制构造函数(不能将尾部复制到头部)

C++ 双链表复制构造函数(不能将尾部复制到头部),c++,copy-constructor,doubly-linked-list,C++,Copy Constructor,Doubly Linked List,因此,我试图实现一个复制构造函数,在实例化一个对象时,我可以选择从头部到尾部(正常)或从尾部到头部(反向)复制一个列表。现在,当我使用复制构造函数时,它总是从头到尾复制,即使它进入相反的条件 这是我的头文件: #include <iostream> #include "Student.h" #include "Node.h" using namespace std; class List { public: List(); // Default constructor

因此,我试图实现一个复制构造函数,在实例化一个对象时,我可以选择从头部到尾部(正常)或从尾部到头部(反向)复制一个列表。现在,当我使用复制构造函数时,它总是从头到尾复制,即使它进入相反的条件

这是我的头文件:

#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 
};
#包括
#包括“Student.h”
#包括“Node.h”
使用名称空间std;
班级名单{
公众:
List();//默认构造函数
List(const List&);//复制构造函数(二合一,见实验表)
~List();//析构函数
bool isEmpty();//列表为空:TRUE还是FALSE?
int getNumNodes(){return numNodes;}//列表中有多少个节点
void append(Student*);//将新节点追加到列表的开头或结尾
void insert(Student*);//在
//列表中的适当位置
void deleteNode(字符串);//搜索并删除特定节点
void displaysensings();//从头到尾显示列表
void displaydensing();//从尾部到头部显示列表
//将Student::数据输入到Student指针中。
无效输入(学生*,字符串,字符串,字符串,字符串,字符串,字符串);
Node*getHead()常量{return head;}//ptr to head。
Node*getTail()常量{return tail;}//ptr to tail。
私人:
void printer(Node*);//递归函数w/in displayDescending()
节点*头;
节点*尾部;
布尔空;
bool forward;//forward=从头到尾,即true
int numNodes;//列表中的节点数
};
这是我的复制构造函数

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
List::List(List&List){//复制构造函数
head=NULL;//头指针最初设置为NULL
tail=NULL;//尾部指针最初设置为NULL
空=真;
forward=true;//默认情况下从头到尾复制。
珠心=0;
字符串标志;//存储提示值。
cout>flag;//提示用户。
如果(标志==“n”)
正向=假;
Node*curr=NULL;//在函数范围内初始化curr。
如果(标志==“n”){
正向=假;
curr=list.getTail();//curr指向列表尾部。
coutgetmid());
字符串l=(curr->getData()->getLast());
字符串s=(curr->getData()->getSocial());
字符串a=(curr->getData()->getAge());
Node*nodePtr=NULL;//指向的节点
//使用它来指向
//新节点
Student*stuPtr=new Student;//在上创建一个螺柱指针
//一大堆学生在教室里上课
//订购以存储螺柱信息
输入(stuPtr,f,m,l,s,a);//将Student::data输入stuPtr。
append(stuPtr);//将带有stuPtr的节点追加到head或tail
//名单的一部分。
如果(!向前)
curr=curr->getPrev();
其他的
curr=curr->getNext();
}//结束时*/
cout setPrev(newNode);//头部的PREV ptr指向newNode。
newNode->setNext(head);//newNode的下一个指向前一个head。
head=newNode;//newNode成为新的head。
}//如果结束/else
}//如果结束/else
节点++;
}

通过使用
const
参数,可以调用const对象上的非const成员函数。非
const
函数不承诺不修改对象。您可以将这些成员函数声明为
const
,以避免此错误:

Node *getHead() const
。。等等

关于你的第一个问题,我还不知道如何解决,我有一些建议:

  • 使用
    NULL ptr
    代替
    NULL
    0
  • 用于字符串:
    stringf{curr->getData()->getFirst()}

我建议您使用一个好的调试器工具,如VisualStudio,逐行调试代码;它将帮助你在几分钟内解决你的问题。如果您仍然不确定,您可以将要测试的代码量减少到几行,然后发布。

您总是从头到尾地复制代码的原因是您的代码杂乱无章,并且试图一次以多种方式执行相同的操作。如果你试着从一个尾巴到另一个头部复制,你会从另一个尾巴到另一个头部写下新的列表,然后从另一个尾巴到另一个头部阅读旧的列表。这两者相互抵消。想想看

如果您试图使参数
const
,则会出现编译器错误的原因是您正在使用
getTail()
getHead()
对其进行查询,而您没有使用
const

编辑:

让我们回到设计上来,考虑一下从尾部到头部的复制应该如何工作。基本上有两种方法,读头-尾和写尾-头:

|                |
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
但如果我们同时尝试这两种方法,它们会抵消:

      |          |
      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
我们所要做的就是选择一个。如果我们选择第一个,我们将更改复制系数:

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*/

一般来说,避免此类问题的方法是从小处着手,一次增加一点复杂性,在每一步都进行测试,首先单独测试新特性,永远不要添加不起作用的代码。找到不明显的错误的方法是将代码简化,逐段消除复杂性,直到您得到仍然显示错误行为的最简单版本——或者更可能的是,错误在过程中变得明显。

这回答了部分问题,但顶部还有另一个问题。谢谢Oleksiy!这解决了常数问题。现在剩下的就是从尾到头的复制问题。@Oleksiy:我听说过使用nullptr有一段时间了,但是我还没有GCC编译器,我相信我的教授也没有。关于列表初始化的问题,你能澄清一下你的意思吗?@baph0mt点击“列表初始化”链接-我最近发表了一篇关于itI的帖子,我可以理解你的意思,但我没有
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*/
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