c++ - Doubly-linked List copy constructor (can't copy tail-to-head) -
so, i'm trying implement copy constructor that, upon instantiating object, can choose copy list head-to-tail (normal) or tail-to-head (reverse). now, when use copy constructor, copies head tail, if enters reverse condition.
here header file:
#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 empty: true or false? int getnumnodes() {return numnodes;} // how many nodes in list void append(student *); // append new node head or tail of list void insert(student *); // inserts new node in // appropriate location in list void deletenode(string); //search , delete specific node void displayascending();// display list head tail void displaydescending(); // display list tail head // input student::data student pointer. void input(student*, string, string, string, string, string); node *gethead() const {return head;} // ptr head. node *gettail() const {return tail;} //ptr 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 list };
here copy constructor.
list::list(list &list) { // copy constructor head = null; // head pointer set null tail = null; // tail pointer set null empty = true; forward = true; // copies head-to-tail default. numnodes = 0; string flag; // stores prompt value. cout << "copy head tail? (y/n): "; cin >> flag; // prompt user. if(flag == "n") forward = false; node *curr = null; //initialize curr in function scope. if(flag == "n") { forward = false; curr = list.gettail(); // curr points list tail. cout << "copying in reverse order...\n" << endl; } else { // forward == true curr = list.gethead(); // curr points list head. cout << "copying 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 = ( curr->getdata()->getage() ); node *nodeptr = null; // node that's pointing // using point creation of // new node student *stuptr = new student; // creates stud pointer on // heap of student class in // order store stud info input(stuptr,f,m,l,s,a); // input student::data stuptr. append(stuptr); // append node stuptr head or tail // of list. if(!forward) curr = curr->getprev(); else curr = curr->getnext(); } // end while*/ cout << "done copying!\n" << endl; } // end copy constructor
also, here's append() function if need see how appends list.
void list::append(student *newstudent) { node *newnode = new node(newstudent); // new node containing student arg. newnode->getdata(); // data of student arg. if(isempty()) { // tail=null, no list. cout << "list empty. inserting first node.\n" << endl; head = newnode; tail = newnode; // new node becomes head & tail. } else { if(forward) { // append tail of list. tail->setnext(newnode); // next ptr of tail points newnode. newnode->setprev(tail); // newnode's prev points former tail. tail = newnode; // newnode becomes new tail. } else { // append head of list. head->setprev(newnode); // prev ptr of head points newnode. newnode->setnext(head); // newnode's next points former head. head = newnode; // newnode becomes new head. } // end if/else } // end if/else numnodes++; }
the reason seem copying head tail your code unkempt , tries same thing in more 1 way @ once. if try copy tail head, write new list tail head and read old list tail head. these 2 cancel each other out. think it.
the reason compiler errors if try make argument const
you're querying gettail()
, gethead()
, have not made const
.
edit:
let's go design , think how tail-to-head copying should work. there 2 ways it, read head-tail , write tail-to-head:
| | v v a-b-c-d | | 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
or vise-versa:
| | 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 if try both, cancel out:
| | 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
all have choose one. if choose first one, change copy ctor:
curr = list.gethead(); // curr points list head. cout << "reading head-to-tail...\n" << endl; while(curr) { ... append(stuptr); // append node stuptr head or tail of list. curr = curr->getnext(); } // end while*/
and works. if choose second, leave ctor alone , change append(...)
:
if(isempty()) { // tail=null, no list. cout << "list empty. inserting first node.\n" << endl; head = newnode; tail = newnode; // new node becomes head & tail. } else { tail->setnext(newnode); // next ptr of tail points newnode. newnode->setprev(tail); // newnode's prev points former tail. tail = newnode; // newnode becomes new tail. } // end if/else
generally speaking, way avoid problems start small , simple, add complexity little @ time, test @ every step, test new features in isolation first, , never add code doesn't work. way find non-obvious bugs take code , simplify, removing complexity piecemeal until reach simplest version still exhibits buggy behavior-- or more bug becomes obvious along way.
Comments
Post a Comment