I'm designing a template class for creating and modifying linked lists, and I'm having a slight problem. When I first call printList after creating an empty list, it correctly prints "The list is empty", but when I call it after adding a new node using the add() function, then call printList() again, it prints a blank line, indicating that nothing is being inserted into the cout statement within the printList() function. Does anyone know why this is happening?
EDIT: I tried changing the cout statement to print a word after the element being printed, but that didn't appear either, so I'm going to guess that the entire cout statement isn't working...
Here is how I am creating the object and calling the function:
1 2 3 4
LinkedList<int> *myList = new LinkedList<int>();
myList->printList();
myList->add(5);
myList->printList();
And here is the LinkedList header file containing the class and struct:
/**
* This header file was designed to make creation and modification of linked lists easier.
* Author - packetpirate
* Last Update - 05/18/2011 11:19 PM
**/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
using std::cout;
using std::endl;
// Begin linklist namespace.
namespace linklist
{
// Begin node structure.
template< typename T >
struct node {
T data; // Contains data of specified type.
node<T> *link; // Contains link to next node. NULL if this node is last in the list.
};
// End node structure.
// Begin LinkedList class declaration.
template< typename T >
class LinkedList {
public:
LinkedList(); // Creates a new blank list.
LinkedList(node<T> *start); // Creates a new list with a specified first node.
~LinkedList();
// Functions for appending the list.
void add(node<T> *next); // Adds a node to the list.
void add(T nextData); // Adds a new node to the list.
// Get and Set functions for the list.
T get(int pos);
void set(int pos, T newData);
// Size-based functions.
int length();
bool isEmpty();
// Position-based functions.
T begin(); // Returns the data of the first node in the list.
T end(); // Returns the data of the last node in the list.
// Print functions.
void printList();
void printElem(int pos);
private:
node<T> *first; // The first node in the list.
node<T> *last; // The last node in the list.
int size; // Size of the list.
};
// End LinkedList class declaration.
// Begin LinkedList class definitions.
// Begin Constructors & Destructors
template< typename T >
LinkedList<T>::LinkedList() {
first = NULL;
last = NULL;
size = 0;
}
template< typename T >
LinkedList<T>::LinkedList(node<T> *start) {
first = start;
last = start;
size = 1;
}
template< typename T >
LinkedList<T>::~LinkedList() {
}
// End Constructors & Destructors
// Begin list modifying functions.
template< typename T >
void LinkedList<T>::add(node<T> *next) {
if(first == NULL) {
first = next;
last = next;
size++;
} else {
last->link = next;
last = next;
last->link = NULL;
size++;
}
}
template< typename T >
void LinkedList<T>::add(T nextData) {
node<T> *next = new node<T>;
next->data = nextData;
next->link = NULL;
if(first == NULL) {
first = next;
last = next;
size++;
} else {
last->link = next;
last = next;
last->link = NULL;
size++;
}
}
// End list modifying functions.
// Begin get/set functions.
template< typename T >
T LinkedList<T>::get(int pos) {
if(pos > size) {
cout << "That position is out of bounds." << endl;
} else {
int i = 0;
node<T> *current;
for(current = first;current->link != NULL;current = current->link) {
if(i == pos) {
return current->data;
}
i++;
}
}
return 0;
}
template< typename T >
void LinkedList<T>::set(int pos, T newData) {
if(pos > size) {
cout << "That position is out of bounds." << endl;
} else {
int i = 0;
node<T> *current;
for(current = first;current->link != NULL;current = current->link) {
if(i == pos) {
current->data = newData;
}
i++;
}
}
}
// End get/set functions.
// Begin size-based functions.
template< typename T >
int LinkedList<T>::length() {
return size;
}
template< typename T >
bool LinkedList<T>::isEmpty() {
return (first == NULL);
}
// End size-based functions.
// Begin position-based functions.
template< typename T >
T LinkedList<T>::begin() {
if(!isEmpty()) {
return first->data;
} else {
return NULL;
}
}
template< typename T >
T LinkedList<T>::end() {
if(!isEmpty()) {
return last->data;
} else {
return NULL;
}
}
// End position-based functions.
// Begin print functions.
template< typename T >
void LinkedList<T>::printList() {
if(!isEmpty()) {
node<T> *current;
for(current = first;current->link != NULL;current = current->link) {
cout << current->data << " ";
}
} else {
cout << "The list is empty." << endl;
}
}
template< typename T >
void LinkedList<T>::printElem(int pos) {
if(pos > size) {
cout << "That position is out of bounds." << endl;
} else {
int i = 0;
node<T> *current;
for(current = first;current->link != NULL;current = current->link) {
if(i == pos) {
cout << current->data << endl;
break;
}
i++;
}
}
}
// End print functions.
// End LinkedList class definitions.
}
// End linklist namespace.
#endif
I think the problem is the test condition in the for loop on line 184. for(current = first;current->link != NULL;current = current->link)
When the first node is added first->link = NULL is assigned.
The condition should be: current != NULL instead.
Try adding more nodes. I think your current printList() will display all but the last element (the one for which link = NULL).
Nope, I hadn't figured that out. Thanks for the help, that fixed it.
I'm still getting used to pointers and I must have gotten confused when writing that condition. But once it gets to the last element, the pointer isn't NULL... the link for the last node should be NULL... so I don't quite understand why this fix works.
You're welcome.
About the confusion regarding when NULL is encountered.
But once it gets to the last element, the pointer isn't NULL... the link for the last node should be NULL...
Remember, link is a pointer to the next node. last->link may be NULL but last is not so last->data is valid.
On the next iteration current = current->link will make current == NULL true. This is when to stop.
I hope that helped.