List class with Student type
Jul 3, 2013 at 4:33pm UTC
I am trying to use a class Student and declare it as a list type. I can pushback but without changing the List.h or Node.h how can I print the data in list2?
Node.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#ifndef NODE_H
#define NODE_H
#include <string>
#include <iostream>
using namespace std;
template <typename T>
class Node {
private :
T data;
Node<T>* next;
public :
Node(T);
virtual ~Node(); // base class destructor must be virtual
template <typename U> friend class List;
};
template <typename T>
Node<T>::Node(T d) {
data = d;
next = NULL;
}
template <typename T>
Node<T>::~Node() {
}
#endif /* STRNODE_H */
List.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
#ifndef LIST_H
#define LIST_H
#include "Node.h"
// Singly linked list
template <typename T>
class List {
private :
Node<T>* head; // pointer to the first node
Node<T>* tail; // pointer to the last node
int count; // number of nodes in the list
public :
class OutOfRangeException{ }; // empty inner class for exception handling
List();
virtual ~List();
void push_back(T item);
void insert(int index, T item);
void remove(int index);
int indexOf(T item);
T get(int position); // OutOfRangeException is generated
bool isEmpty();
int size();
void print();
};
template <typename T>
List<T>::List() {
head = tail = NULL;
count = 0;
}
template <typename T>
List<T>::~List() {
Node<T>* discard;
while (head != 0) {
discard = head;
head = head->next;
delete discard;
}
}
// append an item at the end of the StrList
template <typename T>
void List<T>::push_back(T item) {
try {
Node<T>* newNode = new Node<T>(item);
if (head == 0) {
head = tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
++count;
} catch (bad_alloc &e) {
cout << "memory allocation exception: " << e.what() << endl;
exit(1);
}
}
// insert an item at the specified index
template <typename T>
void List<T>::insert(int index, T item) {
try {
if (index < 0 || index > count) // push_back() if index == count
throw OutOfRangeException();
Node<T>* newNode = new Node<T>(item);
if (head == 0) { // empty
head = tail = newNode;
} else if (index == 0) { // at the start
newNode->next = head;
head = newNode;
} else if (index == count) { // at the end
tail->next = newNode;
tail = newNode;
} else { // insert in the middle
Node<T>* prevNode;
Node<T>* currNode = head;
for (int i = 0; i < index; i++) {
prevNode = currNode;
currNode = currNode->next;
}
// insert between 'prevNode' and 'currNode'
prevNode->next = newNode;
newNode->next = currNode;
}
++count;
} catch (bad_alloc &e) {
cout << "memory allocation exception: " << e.what() << endl;
exit(1);
}
}
// is the StrList empty?
template <typename T>
bool List<T>::isEmpty() {
return count == 0;
}
// remove the item at specified index
template <typename T>
void List<T>::remove(int index) {
if (index < 0 || index >= count)
throw OutOfRangeException();
if (index == 0) { // at the start
Node<T>* discard = head;
head = head->next;
delete discard;
} else {
Node<T>* prevNode;
Node<T>* currNode = head;
for (int i = 0; i < index; i++) {
prevNode = currNode;
currNode = currNode->next;
}
// remove 'currNode'
prevNode->next = currNode->next; // bypass
delete currNode;
if (index == count - 1) // last node was removed. Update 'tail'
tail = prevNode;
}
--count;
if (count == 0)
tail = NULL;
}
// retrieve the item at the given position of the StrList. position starts from 0.
// throws OutOfRangeException if invalid position value is given.
template <typename T>
T List<T>::get(int position) {
if (position < 0 || position >= count)
throw OutOfRangeException();
int loc = 0;
Node<T>* curr = head;
while (loc < position) {
++loc;
curr = curr->next;
}
return curr->data;
}
// Requirement:
// != operator of <class T> is used
template <typename T>
int List<T>::indexOf(T item) {
if (head == 0) {
return -1; // not found
} else {
int index = 0;
Node<T>* currNode = head;
while (currNode->data != item && currNode != NULL) {
currNode = currNode->next;
++index;
}
if (currNode == NULL) // not found thru the end
return -1;
else
return index;
}
}
// number of nodes in the StrList
template <typename T>
int List<T>::size() {
return count;
}
// Requirement:
// << operator for <class T> is used.
template <typename T>
void List<T>::print() {
cout << "*** StrList contents ***" << endl;
for (int i = 0; i < count; i++) {
cout << i << ": " << get(i) << endl;
}
}
#endif
Student.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
#include "List.h"
class Student {
private :
string name;
int id;
public :
Student();
Student(string a);
virtual ~Student();
};
Student::Student() {
}
Student::Student(string a) {
name = a;
}
Student::~Student() {
}
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include <iostream>
using namespace std;
#include "Student.h"
int main() {
cout << "\n*** StrList Test ***" << endl;
List<string> list;
list.push_back("zero" );
list.push_back("one" );
list.push_back("two" );
list.push_back("three" );
list.push_back("four" );
list.push_back("five" );
list.print();
list.insert(1, "inserted at position 1" );
list.insert(0, "inserted at position 0" );
list.insert(4, "inserted at position 4" );
list.print();
cout << "removing at indexes 3, 0" << endl;
list.remove(3);
list.remove(0);
list.print();
list.insert(2, "inserted at position 2" );
list.print();
cout << "five is at index " << list.indexOf("five" ) << endl;
cout << "two is at index " << list.indexOf("two" ) << endl;
//Test for my Student class implementation
// Student<string> st1; //Create new student Ryan Martin with id of 1
List<Student> list2;
Student stu("Ryan Martin" );
list2.push_back(stu);
//list2.print();
//list2.push_back("Ryan");
//list2.PrintStudents(); //Test that the Student class successfully stored and can access
return 0;
}
Jul 3, 2013 at 4:54pm UTC
You'll need to define a stream operator for Student, so that the line:
cout << i << ": " << get(i) << endl;
in list.h can work with it.
Jul 3, 2013 at 5:07pm UTC
alright so i added an operator within my student class but my program crashes when it attempts to print it...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#include "List.h"
class Student {
private :
string name;
int id;
public :
Student();
Student(string a);
virtual ~Student();
friend ostream& operator <<(ostream &os, const Student& p);
};
Student::Student() {
}
Student::Student(string a) {
name = a;
}
Student::~Student() {
}
ostream& operator <<(ostream &os, const Student& p)
{
return os << p;
}
Jul 3, 2013 at 5:11pm UTC
Sorry i just realized i needed to change p to p.name
Jul 3, 2013 at 5:28pm UTC
Ok so now I have that working my last problem is implementing an != operator so if there are two Students with the same name and id then they are identical. How could i test it with what I have:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#include "List.h"
class Student {
private :
string name;
int id;
public :
Student();
Student(string a);
virtual ~Student();
friend ostream& operator <<(ostream &os, const Student& p);
bool operator !=(const Student &p) const ;
bool operator ==(const Student &p) const ;
};
Student::Student() {
}
Student::Student(string a) {
name = a;
}
Student::~Student() {
}
ostream& operator <<(ostream &os, const Student& p) {
return os << p.name;
}
bool Student::operator ==(const Student &p) const {
// Compare the values, and return a bool result.
if (name == p.name)
return true ;
else
return false ;
}
bool Student::operator !=(const Student &p) const {
return !(*this == p);
}
Jul 3, 2013 at 5:38pm UTC
If you require both name and id to be equal you can use && to test both.
1 2 3 4
if (name == p.name && id == p.id)
return true ;
else
return false ;
You don't actually need an if statement. You can just return the condition directly.
return name == p.name && id == p.id;
Jul 3, 2013 at 7:25pm UTC
Awesome that worked great! Thanks for your help on this.
Topic archived. No new replies allowed.