array transfer constructor function c++ - c++

I am trying to learn constructors in c++. I am working on a list that I defined. I managed to get the copy constructor working, but I have problems with the array transfer constructor. Any help will be appreciated. Thanks!
The array transfer constructor supposedly should take in an array and a size(int) and output a list with that size.
ex: input: data = {1,3,5,6};int = 5;output = {1,3,5,6,0}
edit: change n to i
#include <iostream>
using namespace std;
class list_element{
public:
list_element(int n = 0,list_element* ptr = nullptr):
d(n),next(ptr){}
int d;
list_element* next;
};
class List{
public :
List():head(nullptr),cursor(nullptr){}
List(const int* arr, int n); // copy array transfer data
List(const List& lst); //copy constructor
void prepend(int n);
int get_element()
{
return cursor->d;
}
void advance() { cursor = cursor->next; }
void print();
~List(); //delete
private:
list_element* head;
list_element* cursor;
};
//transfer array
List::List(const int* arr, int n) {
List temp;
int i = 0;
while (i < n)
{
head = new list_element(arr[i], head);
++i;
}
}
//delete
List::~List(){
for (cursor = head; cursor != 0;)
{
cursor = head->next;
delete head;
head = cursor;
}
}
//deep copy constructor
List::List(const List& lst) {
if (lst.head == nullptr)
{
head = nullptr; cursor = nullptr;
}
else
{
cursor = lst.head;
list_element* h = new list_element();
list_element* previous;
head = h;
h->d = lst.head->d;
previous = h;
for (cursor = lst.head; cursor != 0;)
{
h = new list_element();
h->d = cursor->d;
previous->next = h;
cursor = cursor->next;
previous = h;
}
cursor = head;
}
}
void List::prepend(int n)
{
if (head == nullptr)
cursor = head = new list_element(n, head);
else
head = new list_element(n, head);
}
void List::print()
{
list_element* h = head;
while (h != 0)
{
cout << h->d << ',';
h = h->next;
}
cout << "###" << endl;
}
int main()
{
List a, b;
//change size
int data[10] = { 1,3,5,7};
List d(data, 10);
d.print();
return 0;
}

Main Question
With regards to your 'from_array' constructor, you have a temporary List variable that you are not using and is also unnecessary.
Second you are assigning the head pointer each time meaning that by the end of the constructor call, head now points to the last element you constructed.
Third your list_element constructor is taking the old head pointer which points to the previous element meaning the list is tries to advance from the bottom element upwards through the list, causing the reversed read you mentioned in a comment.
You can fix this two ways. First, you could reverse the order you read the input array so it constructs your linked-list back to front.
List::List(const int* arr, int n)
{
int i = n - 1;
list_element* it = new list_element(arr[i], nullptr); ///< Last element
--i;
while (i > -1)
{
it = new list_element(arr[i], it);
--i;
}
head = it; ///< assign head to the last instance of it.
it = nullptr;
}
However, there is a better why that expresses the linking of the elements more intuitively. First you need to pre-construct the next element and give it some default values (I didn't bother implementing a default constructor for list_element but you might want to.) and assign it to next, then assign head to a new list_element passing in the pointer to next. increment i so that you can assign next's value to the second value in the array. Finally incremenet i again so we can loop through the rest of the array. Finally, in the while loop, copy next into a variable called prev. Assign next to a new list_element with the value from the array and a nullptr. Finally assign prev->next to the new next pointer and increment i.
list_element::list_element()
List::List(const int* arr, int n)
{
int i = 0;
list_element* next = new list_element(0, nullptr);
head = new list_element(arr[i], next);
++i;
next->d = arr[i];
++i;
while (i < n)
{
list_element* prev = next;
next = new list_element(arr[i], nullptr);
prev->next = next;
++i;
}
}
Side Notes
Because you stated you are tying to learn about C++ constructors (and I'm assuming data structures) I would suggest starting with a static array type similar to std::array as it's constructors a bit more trivial to implement or even just start with simple classes/struct that just hold simple data like a few ints or whatnot as you can get an idea for the semantics around the various constructors in C++.
Also, the C++ standard library has two linked list types (std::list and std::foward_list)
Finally, you might be better off using a std::initializer_list instead of a raw array as this give you iterators to the data you want to copy which is a bit nicer to use.
Best of luck in your learning journey.

Try to avoid using variable names like 'n', which could be very confusing.
In your copy constructor for transferring the array, you should not access the array using 'n', which is the desired size of the transferred array, nor increment it.
Additionally, sizeof(arr) doesn't work as you would expect. You are querying the size of the pointer.

Related

Linked List: How to implement Destructor, Copy Constructor, and Copy Assignment Operator? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 months ago.
Improve this question
This is my C++ code:
#include <iostream>
using namespace std;
typedef struct Node
{
int data;
Node* next;
}Node;
class LinkedList
{
private:
Node* first;
Node* last;
public:
LinkedList() {first = last = NULL;};
LinkedList(int A[], int num);
~LinkedList();
void Display();
void Merge(LinkedList& b);
};
// Create Linked List using Array
LinkedList::LinkedList(int A[], int n)
{
Node* t = new Node;
if (t == NULL)
{
cout << "Failed allocating memory!" << endl;
exit(1);
}
t->data = A[0];
t->next = NULL;
first = last = t;
for (int i = 1; i < n; i++)
{
t = new Node;
if (t == NULL)
{
cout << "Failed allocating memory!" << endl;
exit(1);
}
t->data = A[i];
t->next = NULL;
last->next = t;
last = t;
}
}
// Deleting all Node in Linked List
LinkedList::~LinkedList()
{
Node* p = first;
Node* tmp;
while (p != NULL)
{
tmp = p;
p = p->next;
delete tmp;
}
}
// Displaying Linked List
void LinkedList::Display()
{
Node* tmp;
for (tmp = first; tmp != NULL; tmp = tmp->next)
cout << tmp->data << " ";
cout << endl;
}
// Merge two linked list
void LinkedList::Merge(LinkedList& b)
{
// Store first pointer of Second Linked List
Node* second = b.first;
Node* third = NULL, *tmp = NULL;
// We find first Node outside loop, smaller number, so Third pointer will store the first Node
// Then, we can only use tmp pointer for repeating process inside While loop
if (first->data < second->data)
{
third = tmp = first;
first = first->next;
tmp->next = NULL;
}
else
{
third = tmp = second;
second = second->next;
tmp->next = NULL;
}
// Use while loop for repeating process until First or Second hit NULL
while (first != NULL && second != NULL)
{
// If first Node data is smaller than second Node data
if (first->data < second->data)
{
tmp->next = first;
tmp = first;
first = first->next;
tmp->next = NULL;
}
// If first Node data is greater than second Node data
else
{
tmp->next = second;
tmp = second;
second = second->next;
tmp->next = NULL;
}
}
// Handle remaining Node that hasn't pointed by Last after while loop
if (first != NULL)
tmp->next = first;
else
tmp->next = second;
// Change first to what Third pointing at, which is First Node
first = third;
// Change last pointer from old first linked list to new last Node, after Merge
Node* p = first;
while (p->next != NULL)
{
p = p->next;
}
last = p;
// Destroy second linked list because every Node it's now connect with first linked list
// This also prevent from Double free()
b.last = NULL;
b.first = NULL;
}
int main()
{
int arr1[] = {4, 8, 12, 14, 15, 20, 26, 28, 30};
int arr2[] = {2, 6, 10, 16, 18, 22, 24};
int size1 = sizeof(arr1) / sizeof(arr1[0]);
int size2 = sizeof(arr2) / sizeof(arr2[0]);
LinkedList l1(arr1, size1);
LinkedList l2(arr2, size2);
l1.Display();
l2.Display();
// Merge two linked list, pass l2 as reference
l1.Merge(l2);
l1.Display();
return 0;
}
I'm beginner on C++ and in this code, I practice how to Merge two linked list. This actually works perfectly. I've successfully Merge the two Linked List in sorted order.
But, there's people said that I should've follow the Rule of Three on C++. Which implement: Destructor, Copy Constructor, and Copy Assignment Operator.
I've watched many videos about that. I do understand that is basically handle Shallow Copy especially when we don't want two different object point to the same address of memory. But, for my problem is, I still don't know how to Implement it on a Class that working on a Linked List just like my code above.
Someone said, in my main(), this code: l1.Merge(l2); is somehow incorrect because I don't have explicit Copy Constructor.
And if you look at my Merge() function, in Last line, if I didn't to this: b.last = NULL; and b.first = NULL; , which simply destroy pointer of Second Linked list, the Compiler give me warning: Double free() detected.
So, I think my question is:
How can this code: l1.Merge(l2); is have something to do with Copy Constructor?
Is Double free() happened because I don't implement the Rule of Three? If yes, how to address them?
How to write the Rule of Three based on my code? When or How to use them?
Based on this Code, is there something wrong? Do I still need the Rule of Three if my Program only want to Merge Linked List?
Thank You. I hope someone can explain to me like I'm 10 years old. and hope someone can write me some Code.
But, for my problem is, I still don't know how to Implement [Rule of Three] on a Class that working on a Linked List just like my code above.
You simply implement the copy constructor and copy assignment operator to iterate the input list, making a copy of each node and inserting them into your target list. You already have a working destructor. In the case of the copy assignment operator, you can usually use the copy-swap idiom to implement it using the copy constructor to avoid repeating yourself.
Someone said, in my main(), this code: l1.Merge(l2); is somehow incorrect because I don't have explicit Copy Constructor.
Then you were told wrong. Your Merge() code has nothing to do with a copy constructor.
And if you look at my Merge() function, in Last line, if I didn't to this: b.last = NULL; and b.first = NULL;, which simply destroy pointer of Second Linked list, the Compiler give me warning: Double free() detected.
Correct. Since you are moving the nodes from the input list to the target list, you need to reset the input list so it doesn't point at the moved nodes anymore. Otherwise, the destructor of the input list will try to free them, as will the destructor of the target list.
How can this code: l1.Merge(l2); is have something to do with Copy Constructor?
It doesn't have anything to do with it.
Is Double free() happened because I don't implement the Rule of Three?
Not in your particular example, as you are not performing any copy operations. But, in general, not implementing the Rule of Three can lead to double frees, yes.
How to write the Rule of Three based on my code?
See the code below.
Do I still need the Rule of Three if my Program only want to Merge Linked List?
No. Only when you want to make copies of lists.
With that said, here is an implementation that includes the Rule of Three:
#include <iostream>
#include <utility>
struct Node
{
int data;
Node *next;
};
class LinkedList
{
private:
Node *first;
Node *last;
public:
LinkedList();
LinkedList(const LinkedList &src);
LinkedList(int A[], int num);
~LinkedList();
LinkedList& operator=(const LinkedList &rhs);
void Display() const;
void Merge(LinkedList &b);
};
// Create Linked List using default values
LinkedList::LinkedList()
: first(NULL), last(NULL)
{
}
// Create Linked List using Array
LinkedList::LinkedList(int A[], int n)
: first(NULL), last(NULL)
{
Node **p = &first;
for (int i = 0; i < n; ++i)
{
Node *t = new Node;
t->data = A[i];
t->next = NULL;
*p = t;
p = &(t->next);
last = t;
}
}
// Create Linked List by copying another Linked List
LinkedList::LinkedList(const LinkedList &src)
: first(NULL), last(NULL)
{
Node **p = &first;
for (Node *tmp = src.first; tmp; tmp = tmp->next)
{
Node* t = new Node;
t->data = tmp->data;
t->next = NULL;
*p = t;
p = &(t->next);
last = t;
}
}
// Deleting all Node in Linked List
LinkedList::~LinkedList()
{
Node *p = first;
while (p)
{
Node *tmp = p;
p = p->next;
delete tmp;
}
}
// Update Linked List by copying another Linked List
LinkedList& LinkedList::operator=(const LinkedList &rhs)
{
if (&rhs != this)
{
LinkedList tmp(rhs);
std::swap(tmp.first, first);
std::swap(tmp.last, last);
}
return *this;
}
// Displaying Linked List
void LinkedList::Display() const
{
for (Node *tmp = first; tmp; tmp = tmp->next)
std::cout << tmp->data << " ";
std::cout << std::endl;
}
// Merge two linked list
void LinkedList::Merge(LinkedList& b)
{
if ((&b == this) || (!b.first))
return;
if (!first)
{
first = b.first; b.first = NULL;
last = b.last; b.last = NULL;
return;
}
// Store first pointer of Second Linked List
Node *second = b.first;
Node *third, **tmp = &third;
// We find first Node outside loop, smaller number, so Third pointer will store the first Node
// Then, we can only use tmp pointer for repeating process inside While loop
// Use while loop for repeating process until First or Second hit NULL
do
{
// If first Node data is smaller than second Node data
if (first->data < second->data)
{
*tmp = first;
tmp = &(first->next);
first = first->next;
}
// If first Node data is greater than second Node data
else
{
*tmp = second;
tmp = &(second->next);
second = second->next;
}
*tmp = NULL;
}
while (first && second);
// Handle remaining Node that hasn't pointed by Last after while loop
*tmp = (first) ? first : second;
// Change first to what Third pointing at, which is First Node
first = third;
// Change last pointer from old first linked list to new last Node, after Merge
Node *p = first;
while (p->next)
{
p = p->next;
}
last = p;
// Destroy second linked list because every Node it's now connect with first linked list
// This also prevent from Double free()
b.first = b.last = NULL;
}
int main()
{
int arr1[] = {4, 8, 12, 14, 15, 20, 26, 28, 30};
int arr2[] = {2, 6, 10, 16, 18, 22, 24};
int size1 = sizeof(arr1) / sizeof(arr1[0]);
int size2 = sizeof(arr2) / sizeof(arr2[0]);
LinkedList l1(arr1, size1);
LinkedList l2(arr2, size2);
LinkedList l3(l1);
LinkedList l4;
l1.Display();
l2.Display();
l3.Display();
l4.Display();
// Merge two linked list, pass l2 as reference
l3.Merge(l2);
l4 = l3;
l1.Display();
l2.Display();
l3.Display();
l4.Display();
return 0;
}
Demo
There are several questionable practices applied in this code, and there is also a bug.
First, the bug. When you create a list, it news all its nodes and keeps track of them using pointers. When you assign a list to another, you literally copy the pointer values. Not only have you now lost the nodes of the assigned list (because you overwrote them) and got a memory leak (because now there's no pointer pointing to the allocated nodes), you also now have the same pointers on two different lists, pointing to the same nodes. When the lists are destroyed, both of them try to delete their nodes, and you end up freeing the same memory twice. Yuk.
The solution to this bug is to implement the assignment operator.
Then, the questionable practices:
using namespace std; (Why is "using namespace std;" considered bad practice?)
You're assigning the members of LinkedList in the constructor body, instead of passing the values directly to their constructor in the initialization list. (What is this weird colon-member (" : ") syntax in the constructor?)
Declaring an array parameter (int[]) is declaring a pointer. Just be aware of it.
new cannot return NULL! It's useless to check its return value. If it can't allocate, it will simply throw an exception.
NULL is the inappropriate constant to use. You can use nullptr, it's the C++ equivalent of NULL, except it's type safe.
Manual memory management with new and delete is tricky to get right (as you figured out yourself). You might be interested in using std::unique_ptr or std::shared_ptr to alleviate the burden. They would have caught the bug.
Now, please: do not write in C++ like it's C with classes. I understand that you may not have encountered all of the features I presented here, but anyway now you know about them :)

segmentation fault only after accessing struct in linked list for a second time

Sorry for the unclear title, I really don't know how to describe this issue. I'm in my first year of computer science so I really don't know much about C++ yet. However, trying to look up this issue did not help.
The issue:
In the main function, the "printRawData" friend function is called twice. The function is supposed to print each element of the linked list stored by the the class "LinkedList". It works the first time, but the second time I get a segmentation fault. I really have no idea what I'm doing wrong. My T.A. said he thinks that the struct's string variable "element_name" is being corrupted when accessed.
Sorry for the messy code, if I'm not explaining my issue well, or if I'm breaking any kind of stackoverflow etiquette. I appreciate any help I get.
//Note: C++ 11 is needed, due to to_string use
#include <iostream>
#include <string>
using namespace std;
struct Node {
string element_name;
int element_count;
Node* next;
};
class LinkedList{
private:
Node* first;
public:
LinkedList();
~LinkedList();
bool isEmpty();
void AddData(string name, int count);
friend void printRawData(LinkedList l);
};
//where the error occurs
void printRawData(LinkedList l){
Node* n = l.first;
while (n != NULL) { //iterates through the linked list and prints each element
cout << n->element_name << " : " << n->element_count << endl;
n = n->next;
}
}
LinkedList::LinkedList(){
first = NULL;
}
LinkedList::~LinkedList(){
Node* n = first;
while (n != NULL) {
Node* temp = n;
n = temp->next;
delete temp;
}
}
bool LinkedList::isEmpty(){
return first == NULL;
}
void LinkedList::AddData(string name, int count){
Node* newnode = new Node;
newnode->element_name = name;
newnode->element_count = count;
newnode->next = NULL;
Node* n = first;
//if the linked list is empty
if(n == NULL){
first = newnode;
return;
}
//if there's only one element in the linked list,
//if the name of first element comes before the name of new element,
//first element's pointer is to the new element.
//otherwise, the new node becomes the first and points to the previous first
//element.
if (n->next == NULL){
if (n->element_name < newnode->element_name){
n->next = newnode;
return;
} else {
newnode->next = first;
first = newnode;
return;
}
}
//if the first element's name comes after the new element's name,
//have the new element replace the first and point to it.
if (n->element_name > newnode->element_name){
newnode->next = first;
first = newnode;
return;
}
//iterating through linked list until the next element's name comes after
//the one we're inserting, then inserting before it.
while (n->next != NULL) {
if (n->next->element_name > newnode->element_name){
newnode->next = n->next;
n->next = newnode;
return;
}
n = n->next;
}
//since no element name in the linked list comes after the new element,
//the node is put at the back of the linked list
n->next = newnode;
}
main(){
LinkedList stack;
stack.AddData("Fish", 12);
stack.AddData("Dog", 18);
stack.AddData("Cat", 6);
printRawData(stack);
printRawData(stack);
}
The function void printRawData(LinkedList l) passes the parameter by value, so it gets a copy of the LinkedList object.
However, the copy contains a copy of the first pointer, but doesn't copy any of the nodes. So when this copy is destroyed, the LinkedList destructor will delete all the nodes.
And then the original is damaged.
You might want to pass a reference instead of creating a copy.
This is also the reason why the std::list has copy constructors and assignment operators that perform a "deep copy", where the nodes are also copied (not just the list head).

c++ linked list inside another one

I'm trying to make a linked list inside another one, here is my code
template<typename T>
class List {
private:
int length;
class Node {
public:
T data;
Node* next;
} *head;
public:
List();
~List();
void insert(T item);
void remove(T item);
void empty();
T* getAll();
int count() const;
};
template<typename T>
void List<T>::insert(T item)
{
if (head == NULL)
{
head = new Node();
head->data = item;
head->next = NULL;
length = 1;
return;
}
Node* p = new Node();
p->data = item;
p->next = head;
head = p;
++length;
}
struct Remainder {
Date dt;
List<int> notes;
};
void getDayEvents(Date dt, List<Remainder> l)
{
Remainder* arr = new Remainder[l.count()];
arr = l.getAll();
for (int i = 0; i < l.count(); i++)
{
if (arr[i].dt.day == dt.day && arr[i].dt.month == dt.month && arr[i].dt.year == dt.year)
{
int* nArr = new int[arr[i].notes.count()];
nArr = arr[i].notes.getAll();
for (int j = 0; j < arr[i].notes.count(); j++)
{
cout << nArr[j] << endl;
}
}
}
}
int _tmain() {
Date dt1, dt2;
dt1.setDate(17, 7, 2015);
dt2.setDate(5, 11, 2015);
Remainder r1, r2;
r1.dt = dt1;
r1.notes.insert(1);
r1.notes.insert(2);
r2.dt = dt2;
r2.notes.insert(5);
List<Remainder> l;
l.insert(r1);
l.insert(r2);
getDayEvents(dt1, l);
//----------------------------------------------------------
int pause;
cin >> pause;
return 0;
}
just when insert r1 or r2 in the list, the data inside lists of notes inside each remainder just disappeared or destroyed
I don't know why? Where is the mistake?
You're passing your objects into the insert function by value.
That means copy constructors and destructors are being called.
You did not declare the copy constructor of List so it's presumably
being generated by the compiler, and presumably is making a
"shallow" copy of the List when the copy constructor
of Remainder makes copies of the members of the input Remainder.
I think this copies the pointer head from one List to another
so that now you have
two List objects whose head pointers point to the same object.
You haven't shown the definition of the List destructor,
but depending on what you do in that destructor it could be deleting
a Node that the destroyed List points to while another List
still has a pointer to the same Node.
That may sound confusing, and frankly I'm not sure I can count the
invocations of constructors and destructors correctly myself,
so best to just make sure they can never be used unsafely.
A good start might be to define your own copy constructor and
operator = for List in such a way that the new List has
newly-allocated copies of everything that was in the old List.
Never let two head pointers point to the same object.
After you've inserted one List into another, you should be able to
confirm in the debugger that the new copy of the List

copy constructor for a linked list classes

So I want to copy a whole linked list classes, I have trouble figuring it out how to do so,
class list{
public:
list(const list &t);
private:
struct Node{
int x;
Node *next;
}*p;
I started with something like this:
list::list(const list &t){
Node* q;
q=new Node;
while (p!=NULL){
q->x= p->x;}
}
but I'm not sure if I am on the right track or what. I also have trouble how should I test such a copy constructor? For example I have list l1, then i insert couple integers into a list and then how I can copy it?
In your example it never will work if you initialized p or will work forever if p != NULL. You must allocate new nodes while traversing through t list:
p = NULL;
Node* copy = l.p;
Node* insert = p;
Node* inserted_el = NULL;
while (copy){
insert = new Node();
insert->x = copy->x;
insert->next = NULL;
if (inserted_el) {
inserted_el->next = insert; //copy memory pointer to next element
} else {
p = insert; //copy memory pointer to list head
}
copy = copy->next;
inserted_el = insert;
}
This is basic idea. Also don't forget to implement assign operator and destructor.
Usage:
list t1;
//insert nodes
list t2(t1);
The biggest trouble in your code is that you do not duplicate each node of the list while you need to do so.
Here is the code of the ctor:
list::list(const list &t)
{
p = NULL; // Init the head of the list this is vital important.
// Loop over the elements of the passed list if any.
Node *pt = t.p;
Node *last_local_element = NULL;
while (pt != NULL)
{
// Allocate a new node and set the fields there.
Node *q = new Node;
q->x= pt->x;
     q->next = NULL;
// Add new node to the local list.
if (last_local_element != NULL) {
last_local_element->next = q;
} else {
p = q;
}
last_local_element = q;
// Shift the loop variable along the passed list.
pt = pt->next;
}
}
There are 2 most often cases when the copy ctor is called:
list my_list1;
list my_list2(my_listl); // Explicit call.
list my_list3 = my_listl; // Assignment in the definition statement.
With your design of class, you need to be careful with memory management. This is the code:
list::list(const list& t) {
Node* n = t.p;
Node* m = p;
while (n) {
if (!m) {
m = new Node(); // Allocate memory.
if (!p) p = m;
}
m->x = n->x;
m = m->next;
n = n->next;
}
if (m) { // Original list is longer, delete the rest of the list.
Node * tmp = m;
m = m->next;
delete tmp;
}
}

Trouble with insertion function for ordered linked list class in C++

I have a template class OList that is an ordered linked list (elements are ordered in ascending order). It has a function called void insert(const T & val) that inserts an element into the correct place in the list. For example, If I had an OList of ints with the values { 1,3,5 } and called insert(4), the 4 would be inserted between the 3 and the 5, making OList { 1,3,4,5 }.
Now, what I have works fine when inserting elements into EMPTY OLists. However, when I use the following code:
OList<char> list;
for (int i = 0; i < 3; i++) {
list.insert('C');
list.insert('A');
}
printInfo(list);
printList(list) should output:
List = { A,A,A,C,C,C } Size = 6 Range = A...C
Instead, it outputs:
List = { A,C,C,C,
followed by a runtime error.
I have been messing with this for about 5 hours now, but I don't seem to be making any progress (aside from getting DIFFERENT wrong outputs and errors).
There are three relevant pieces of code: OList's default constructor, operator<<, printInfo(), insert(), and a helper function for insert that finds the node to insert the element. I don't see any reason to provide operator<< nor printInfo() since these seem to work fine elsewhere.
// default constructor
OList() {
size = 0;
headNode = new Node<T>;
lastNode = new Node<T>;
headNode->next = lastNode;
lastNode->next = NULL;
}
void insert(const T & val) {
if ( isEmpty() ) {
lastNode->data = val;
}
else {
Node<T> * pre = headNode;
Node<T> * insertPoint = findInsertPoint(pre, val);
Node<T> * insertNode = new Node<T>;
insertNode->data = val;
insertNode->next = insertPoint;
pre->next = insertNode;
// why is pre equal to headNode?
// I thought I changed that when using it
// with findInsertPoint()
cout << (pre == headNode) << endl;
}
size++;
}
// returns the node AFTER the insertion point
// pre is the node BEFORE the insertion point
Node<T> * findInsertPoint(Node<T> * pre, const T & val) {
Node<T> * current = pre->next;
for (int i = 0; (i < getSize()) && (val > current->data); i++) {
pre = current;
current = current->next;
}
return current;
}
lastNode is simply the last node in the list.
headNode is a "dummy node" that contains no data and is only used as a starting place for the list.
Thanks in advanced. I'm really embarrassed to be asking for homework help on the internet, especially since I'm sure the main problem is my lack of a thorough understanding of pointers.
You are passing the pointer to pre by value into findInsertPoint, so it is copied, and the function changes the copy of pointer, and when the function returns, it is still the old pre, not the pre from inside the function.
If you want to change the pointer, you must pass pointer to the pointer to the function (or reference to pointer).