I keep getting the error on the "Rainfall most = NULL;" line when trying to initalize. Cannot convert int to Rainfall. I can't figure out what I am doing wrong. There are four files total and I'll really appreciate any help.
MAIN
// This program demonstrates the linked list template.
#include <iostream>
#include "RainfallList.h"
#include "Rainfall.h"
using namespace std;
int main()
{
// Define a LinkedList object.
RainfallList<Rainfall> list;
Rainfall most = NULL;
//Rainfall least = NULL;
int entries = 0;
bool marker = false;
int month = 0;
int year = 0;
double rainfall = 0.0;
double total = 0.0;
cout << "Enter the number of entries you would like: ";
cin >> entries;
//Create linked list of values
for(int i=1; i<=entries; i++){
marker=false;
while(marker==false){
cout << "Enter the month for entry " << i << " (1-12): ";
cin >> month;
cout << "Enter the year for entry " << i << " (2010-2013): ";
cin >> year;
cout << "Enter the rainfall for entry " << i << " (inches): ";
cin >> rainfall;
if(month>0 && month<13 && year>2009 && year<2014 && rainfall>=0){
marker=true;
}else{
cout << endl << endl << "**ERROR** Make sure the month is a value from 1-12, the year is 2010-2013, and rainfall is 0 or greater!" << endl << endl;
}
}
Rainfall value(year, month, rainfall);
list.appendNode(value);
}
list.displayList();
//find average rainfall
total = list.getAvg();
cout << "The total amount of rainfall is " << total << " inches." << endl;
cout << "The average rainfall is " << total/entries << " inches" << endl;
//find the month with the highest rainfall
most = list.getMost();
cout << "The most rainfall happened in " << most.getMonth() << " of " << most.getYear() << " where it rained " << most.getRainfall() << " inches." << endl;
//find the month with the lowest rainfall
most = list.getLeast();
cout << "The most rainfall happened in " << most.getMonth() << " of " << most.getYear() << " where it rained " << most.getRainfall() << " inches." << endl;
system("Pause");
return 0;
}
LINKEDLIST
// A class template for holding a linked list.
// The node type is also a class template.
#ifndef RainfallList_H
#define RainfallList_H
#include "Rainfall.h"
//*********************************************
// The ListNode class creates a type used to *
// store a node of the linked list. *
//*********************************************
template <class T>
class RainfallListNode
{
public:
T value; // Node value
RainfallListNode<T> *next; // Pointer to the next node
// Constructor
RainfallListNode(T nodeValue)
{
value = nodeValue;
next = NULL;
}
};
//*********************************************
// LinkedList class *
//*********************************************
template <class T>
class RainfallList:Rainfall
{
private:
RainfallListNode<T> *head; // List head pointer
public:
// Constructor
RainfallList()
{
head = NULL;
}
// Destructor
~RainfallList();
// Linked list operations
void appendNode(T);
void insertNode(T);
void deleteNode(T);
void displayList() const;
double getAvg();
Rainfall getMost();
Rainfall getLeast();
};
//**************************************************
// appendNode appends a node containing the value *
// pased into newValue, to the end of the list. *
//**************************************************
template <class T>
void RainfallList<T>::appendNode(T newValue)
{
RainfallListNode<T> *newNode; // To point to a new node
RainfallListNode<T> *nodePtr; // To move through the list
// Allocate a new node and store newValue there.
newNode = new RainfallListNode<T>(newValue);
// If there are no nodes in the list
// make newNode the first node.
if (!head)
head = newNode;
else // Otherwise, insert newNode at end.
{
// Initialize nodePtr to head of list.
nodePtr = head;
// Find the last node in the list.
while (nodePtr->next)
nodePtr = nodePtr->next;
// Insert newNode as the last node.
nodePtr->next = newNode;
}
}
//**************************************************
// displayList shows the value stored in each node *
// of the linked list pointed to by head. *
//**************************************************
template <class T>
void RainfallList<T>::displayList() const
{
RainfallListNode<T> *nodePtr; // To move through the list
// Position nodePtr at the head of the list.
nodePtr = head;
// While nodePtr points to a node, traverse
// the list.
while (nodePtr)
{
// Display the value in this node.
cout << nodePtr->value << endl;
// Move to the next node.
nodePtr = nodePtr->next;
}
}
//**************************************************
// The insertNode function inserts a node with *
// newValue copied to its value member. *
//**************************************************
template <class T>
void RainfallList<T>::insertNode(T newValue)
{
RainfallListNode<T> *newNode; // A new node
RainfallListNode<T> *nodePtr; // To traverse the list
RainfallListNode<T> *previousNode = NULL; // The previous node
// Allocate a new node and store newValue there.
newNode = new RainfallListNode<T>(newValue);
// If there are no nodes in the list
// make newNode the first node
if (!head)
{
head = newNode;
newNode->next = NULL;
}
else // Otherwise, insert newNode
{
// Position nodePtr at the head of list.
nodePtr = head;
// Initialize previousNode to NULL.
previousNode = NULL;
// Skip all nodes whose value is less than newValue.
while (nodePtr != NULL && nodePtr->value < newValue)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
// If the new node is to be the 1st in the list,
// insert it before all other nodes.
if (previousNode == NULL)
{
head = newNode;
newNode->next = nodePtr;
}
else // Otherwise insert after the previous node.
{
previousNode->next = newNode;
newNode->next = nodePtr;
}
}
}
//*****************************************************
// The deleteNode function searches for a node *
// with searchValue as its value. The node, if found, *
// is deleted from the list and from memory. *
//*****************************************************
template <class T>
void RainfallList<T>::deleteNode(T searchValue)
{
RainfallListNode<T> *nodePtr; // To traverse the list
RainfallListNode<T> *previousNode = nullptr; // To point to the previous node
// If the list is empty, do nothing.
if (!head)
return;
// Determine if the first node is the one.
if (head->value == searchValue)
{
nodePtr = head->next;
delete head;
head = nodePtr;
}
else
{
// Initialize nodePtr to head of list
nodePtr = head;
// Skip all nodes whose value member is
// not equal to num.
while (nodePtr != NULL && nodePtr->value != searchValue)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
// If nodePtr is not at the end of the list,
// link the previous node to the node after
// nodePtr, then delete nodePtr.
if (nodePtr)
{
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
}
//**************************************************
// Destructor *
// This function deletes every node in the list. *
//**************************************************
template <class T>
RainfallList<T>::~RainfallList()
{
RainfallListNode<T> *nodePtr; // To traverse the list
RainfallListNode<T> *nextNode; // To point to the next node
// Position nodePtr at the head of the list.
nodePtr = head;
// While nodePtr is not at the end of the list...
while (nodePtr != NULL)
{
// Save a pointer to the next node.
nextNode = nodePtr->next;
// Delete the current node.
delete nodePtr;
// Position nodePtr at the next node.
nodePtr = nextNode;
}
}
template <class T>
double RainfallList<T>::getAvg()
{
double avg = 0.0;
Rainfall obj;
RainfallListNode<T> *nodePtr; // To move through the list
// Position nodePtr at the head of the list.
nodePtr = head;
// While nodePtr points to a node, traverse
// the list.
while (nodePtr)
{
// Display the value in this node.
//cout << nodePtr->value << endl;
obj = nodePtr->value;
avg += obj.getRainfall();
// Move to the next node.
nodePtr = nodePtr->next;
}
return avg;
}
template <class T>
Rainfall RainfallList<T>::getMost()
{
//double avg = 0.0;
Rainfall obj = NULL;
Rainfall obj2 = NULL;
RainfallListNode<T> *nodePtr; // To move through the list
// Position nodePtr at the head of the list.
nodePtr = head;
obj = nodePtr->value;
// While nodePtr points to a node, traverse
// the list.
while (nodePtr)
{
// Display the value in this node.
//cout << nodePtr->value << endl;
obj2 = nodePtr->value;
if (obj.getRainfall() < obj2.getRainfall()){
obj = nodePtr->value;
}
// Move to the next node.
nodePtr = nodePtr->next;
}
return obj;
}
template <class T>
Rainfall RainfallList<T>::getLeast()
{
//double avg = 0.0;
Rainfall obj = NULL;
Rainfall obj2 = NULL;
RainfallListNode<T> *nodePtr; // To move through the list
// Position nodePtr at the head of the list.
nodePtr = head;
obj = nodePtr->value;
// While nodePtr points to a node, traverse
// the list.
while (nodePtr)
{
// Display the value in this node.
//cout << nodePtr->value << endl;
obj2 = nodePtr->value;
if (obj.getRainfall() > obj2.getRainfall()){
obj = nodePtr->value;
}
// Move to the next node.
nodePtr = nodePtr->next;
}
return obj;
}
#endif
RAINFALL CLASS
#ifndef RAINFALL_H
#define RAINFALL_H
#include <iostream>
using namespace std;
//class rainclass;
//ostream &operator << (ostream & , const Rainfall & );
//istream &operator >> (istream & , Rainfall & );
class Rainfall
{
private:
int year;
int month;
double rainfall;
public:
Rainfall(void);
Rainfall(int year, int month, double rainfall);
void setRain(int year, int month, double rainfall);
int getYear();
int getMonth();
double getRainfall();
void print();
// Overloaded operator functions
Rainfall operator + (const Rainfall &); // Overloaded +
//Rainfall operator - (const Rainfall &); // Overloaded -
//Rainfall operator ++ (); // Prefix ++
//Rainfall operator ++ (int); // Postfix ++
bool operator > (const Rainfall &); // Overloaded >
bool operator < (const Rainfall &); // Overloaded <
//bool operator == (const Rainfall &); // Overloaded ==
//bool operator != (const Rainfall &); // Overloaded ==
// Conversion functions
//operator double();
//operator int();
// Friends
friend ostream &operator << (ostream &, const Rainfall &);
//friend istream &operator >> (istream &, Rainfall &);
};
#endif
RAINFALL IMPLEMENTATION
#include "Rainfall.h"
#include <iostream>
using namespace std;
Rainfall::Rainfall(){
year = 0;
month = 0;
rainfall = 0.0;
}
Rainfall::Rainfall(int tempyear, int tempmonth, double temprainfall){
year = tempyear;
month = tempmonth;
rainfall = temprainfall;
}
void Rainfall::setRain(int tempyear, int tempmonth, double temprainfall){
year = tempyear;
month = tempmonth;
rainfall = temprainfall;
}
int Rainfall::getMonth() {
return month;
}
int Rainfall::getYear() {
return year;
}
double Rainfall::getRainfall() {
return rainfall;
}
void Rainfall::print() {
cout << "There was " << getRainfall() << " inches of rainfall in " << getMonth() << " of " << getYear() << endl;
}
//**********************************************
// Overloaded binary + operator. *
//**********************************************
Rainfall Rainfall::operator + (const Rainfall &right)
{
Rainfall temp;
//temp.year = year + right.year;
//temp.month = month + right.month;
temp.rainfall = rainfall + right.rainfall;
return temp;
}
//********************************************************
// Overloaded << operator. Gives cout the ability to *
// directly display FeetInches objects. *
//********************************************************
ostream &operator<<(ostream &strm, const Rainfall &obj)
{
strm << obj.month << " " << obj.year << " " << obj.rainfall << "inches" << endl;
return strm;
}
//************************************************************
// Overloaded > operator. Returns true if the current object *
// is set to a value greater than that of right. *
//************************************************************
bool Rainfall::operator > (const Rainfall &right)
{
bool status;
if (rainfall > right.rainfall)
status = true;
//else if (feet == right.feet && inches > right.inches)
//status = true;
else
status = false;
return status;
}
//************************************************************
// Overloaded < operator. Returns true if the current object *
// is set to a value less than that of right. *
//************************************************************
bool Rainfall::operator < (const Rainfall &right)
{
bool status;
if (rainfall < right.rainfall)
status = true;
//else if (feet == right.feet && inches < right.inches)
//status = true;
else
status = false;
return status;
}
You can initialize a pointer with NULL, but assigning NULL (which is an int behind the scenes) to an object (Rainfall in your case) makes no sense.
Rainfall most;
is enough, because your Rainfall constructor is already initialising the new object with zeros by default.
Related
#include "node.h"
#include <iostream>
// List class
class List
{
node *head; // head is an object that stores the address of the first node
public:
// constructor that initializes every list to null
List()
{
head = NULL;
}
// prtototype of the list member functions
void Print();
void Insert(float sal, int en);
void Delete(float sal, int en);
};
//linklist.h above
#include "linklist.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
/**
* Append a node to the linked list
*/
void List::Insert(float sal, int en)
{
// Create a new node
node* newNode = new node();
newNode->SetData(sal, en);
newNode->setNext(NULL);
// Create a temp pointer
node *tmp = head;
if ( tmp != NULL )
{
// Nodes already present in the list
// Parse to end of list
/*while ( tmp->Next() != NULL )
{
tmp = tmp->Next();
}*/
// Point the last node to the new node
tmp->setNext(head);
}
else
{
// First node in the list
head = newNode;
}
}
/**
* Delete a node from the list
*/
void List::Delete(float salary, int data)
{
// Create a temp pointer
node *tmp = head;
// No nodes
if ( tmp == NULL )
return;
// Last node of the list
if ( tmp->Next() == NULL )
{
delete tmp;
head = NULL;
}
else
{
// Parse thru the nodes
node *prev;
do
{
if ( tmp->Epnum() == data && tmp->Salary()== salary )
break;
prev = tmp;
tmp = tmp->Next();
} while ( tmp != NULL );
// Adjust the pointers
prev->setNext(tmp->Next());
// Delete the current node
delete tmp;
}
}
/**
* Print the contents of the list
*/
void List::Print()
{
// Temp pointer
node *tmp = head;
// No nodes
if ( tmp == NULL )
{
cout << "EMPTY" << endl;
return;
}
// One node in the list
if ( tmp->Next() == NULL )
{
cout << tmp->Salary() + tmp->Epnum();
cout << " --> ";
cout << "NULL" << endl;
}
else
{
// Parse and print the list
do
{
cout << tmp->Epnum();
cout << " --> ";
tmp = tmp->Next();
}
while ( tmp != NULL );
cout << "NULL" << endl;
}
}
//linlist.cpp above
#include <iostream>
#include <cstdlib>
#include "linklist.h"
using namespace std;
void menu(List &);
int main()
{
// New list
List list;
menu(list);
return 0;
}
void menu(List &list)
{ char choice;
int item;
float salary;
do{
system("CLS"); // use #include <cstdlib>
cout << "\t\t\tMain Menu\n\n";
cout << "\tInsert{A}\n";
cout << "\tDelete\n";
cout << "\tPrint{P}\n";
cout << "\tExit\n";
cout << "\t\t What? ";cin >>choice;
choice = toupper(choice);
cin.ignore();
switch (choice)
{ case 'A':
cout << "Enter Employee numbers to insert and salary : "; cin >> item; cin>>salary;
list.Insert(salary, item);
cout << item<< " Inserted \n"; cin.get();
break;
/*case 'D':
cout << "Enter Item to Delete : "; cin >> item;
list.Delete(item);
cout << item<< " Deleted\n";cin.get();
break;*/
case 'P':
list.Print();cin.get();
break;
}
}while (choice != 'E');
}
//main.cpp above
//node.h
//#ifndef NODE_H
#define NODE_H
//node class
class node {
int epnum;
float salary;
node* next;
public:
node()
{} //null constructor
//stores argument passed in func.
void SetData(float _salary, int _epnum){
salary = _salary;
epnum = _epnum;
}
//stores in next the address of the next node
void setNext (node* anext){
next = anext;
}
//returns epnum stored
int Epnum(){
return epnum;
}
float Salary(){
return salary;}
//returns addres of next node
node* Next(){
return next;
}
};
//node.h above
I need to create a linked list that inserts a node at the front of the list as a program and of course print it out. I am unable to insert the node at the front of the list for some reason and I run into an infinte loop while trying to print it. It does something but I do not know exactly what. Please help.
In List::Insert, you have:
node *tmp = head;
followed by
tmp->next = head;
Hence, you have circular link in the object. Its next points to itself. This leads to infinite loop in the print function.
What you need is very simple:
void List::Insert(float sal, int en)
{
// Create a new node
node* newNode = new node();
newNode->SetData(sal, en);
newNode->setNext(head);
head = newNode;
}
In your insert method when you have 1 element already present tmp is set to head, then tmp->setNext(head); will create a reference to itself. This is the reason of infinite loop in your print method. Try the following insert code instead.
void List::Insert(float sal, int en)
{
// Create a new node
node* newNode = new node();
newNode->SetData(sal, en);
newNode->setNext(head);
head = newNode;
}
I would also note that in you print method there is no corner case for the list with 1 element. Your loop will perfectly handle this case. You will get the same result if you omit One node in the list branch.
void List::Print()
{
// Temp pointer
node *tmp = head;
// No nodes
if ( tmp == NULL )
{
cout << "EMPTY" << endl;
return;
}
// Parse and print the list
do
{
cout << tmp->Epnum();
cout << " --> ";
tmp = tmp->Next();
}
while ( tmp != NULL );
cout << "NULL" << endl;
}
void List::Insert(float sal, int en)
{
// Create a new node
node* newNode = new node();
newNode->SetData(sal, en);
newNode->setNext(NULL);
//set the newNode next to point to head
newNode->setNext(head);
//set the new head as the newNode
head = newNode;
// Create a temp pointer
//node *tmp = head;
/*if ( tmp != NULL )
{
// Nodes already present in the list
// Parse to end of list
/*while ( tmp->Next() != NULL )
{
tmp = tmp->Next();
}
// Point the last node to the new node
tmp->setNext(head);
}
else
{
// First node in the list
head = newNode;
}*/
}
/**
* Delete a node from the list
*/
void List::Delete(float salary, int data)
{
// Create a temp pointer
node *tmp = head;
// No nodes
if ( tmp == NULL )
return;
// Last node of the list
if ( tmp->Next() == NULL )
{
delete tmp;
head = NULL;
}
else
{
// Parse thru the nodes
node *prev;
do
{
if ( tmp->Epnum() == data && tmp->Salary()== salary )
break;
prev = tmp;
tmp = tmp->Next();
} while ( tmp != NULL );
// Adjust the pointers
prev->setNext(tmp->Next());
// Delete the current node
delete tmp;
}
}
/**
* Print the contents of the list
*/
void List::Print()
{
// Temp pointer
node *tmp = head;
// No nodes
if ( tmp == NULL )
{
cout << "EMPTY" << endl;
return;
}
// One node in the list
if ( tmp->Next() == NULL )
{
cout << tmp->Salary() + tmp->Epnum();
cout << " --> ";
cout << "NULL" << endl;
}
else
{
// Parse and print the list
do
{
cout << tmp->Epnum();
cout << " --> ";
tmp = tmp->Next();
}
while ( tmp != NULL );
cout << "NULL" << endl;
}
}
nvm i was tired when i was writting this code and just realized what I did wrong.
I am working on some C++ homework and have hit a snag, I cannot run my displayList() function in my linkedlist class. I receive the following error.
Error 1 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'weatherstats' (or there is no acceptable conversion) c:\users\larry\documents\visual studio 2013\projects\weatherstats\weatherstats\linkedlist.h 100 1 WeatherStats
So I need to overload the << operand but I have tried using a few examples I found online but with no luck. Can someone help me with my << overload operator please?
EDIT: Added Weatherstats.cpp
EDIT 2: I created an overloaded << operand in my weatherstats.cpp file, I updated my content below. Instead of outputting my data, it outputs all data I enter as 1. I enter 2 for snow and it prints out 1 when using my displayList() function.
linkedlist.h
#pragma once
#include"WeatherStats.h"
#include<iostream>
#include<string>
using namespace std;
template <class T>
class linkedlist
{
private:
struct ListNode
{
T value; //Current value of node
struct ListNode *next; //Pointer to next node
};
ListNode *head; //Head pointer
public:
/*!
Constructors
!*/
linkedlist()
{
head = NULL;
};
/*!
Destructors
!*/
~linkedlist();
/*!
Prototypes
!*/
void appendNode(T); //Append a node to list
void insertNode(T); //Insert a node to list
void deleteNode(T); //delete a node in list
void searchList(T); //Search a node in list
void displayList() const; //Display the full list
friend ostream &operator << (ostream&, linkedlist<T> &);
};
//**
//Append Node
//**
template <class T>
void linkedlist<T>::appendNode(T newValue)
{
ListNode *newNode; //Point to new node
ListNode *nodePtr; //Move through list
//Assign newValue to new node
newNode = new ListNode;
newNode->value = newValue;
newNode->next = NULL;
if (!head)
{ //If empty assign new node as head
head = newNode;
}
else
{ //Assign head to nodePtr
nodePtr = head;
//Find last node in list
while (nodePtr->next)
{
nodePtr = nodePtr->next;
}
//Insert newNode as the last node
nodePtr->next = newNode;
}
}
//**
//Display List
//**
template <class T>
void linkedlist<T>::displayList()const
{
ListNode *nodePtr;
//Assign head to nodePtr
nodePtr = head;
//While nodePtr pointing to a node, print to screen
while (nodePtr)
{
//Print value
cout << nodePtr->value << endl; //ERROR C2679 HERE
//Move nodePtr to next node
nodePtr = nodePtr->next;
}
}
//**
//Insert Node
//**
template <class T>
void linkedlist<T>::insertNode(T newValue)
{
ListNode *newNode;
ListNode *nodePtr;
ListNode *previousNode = NULL;
//New node
newNode = new ListNode;
newNode->value = newValue;
//If list is empty assign newValue to head
if (!head)
{
head = newNode;
newNode->next = NULL;
}
else
{
//Assign head to nodePtr
nodePtr = head;
//Pass over all nodes who are less than newValue
while (nodePtr != NULL && nodePtr->value < newValue)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
//If new node will be first, insert before all other nodes
if (previousNode == NULL)
{
head = newNode;
newNode->next = nodePtr;
}
else
{
previousNode->next = newNode;
newNode->next = nodePtr;
}
}
}
//**
//Delete Node
//**
template <class T>
void linkedlist<T>::deleteNode(T searchValue)
{
ListNode *nodePtr; //Traverse our list
ListNode *previousNode = NULL; //Points to previous node
//Check if list is empty
if (!head)
{
cout << "This list is empty." << endl;
return;
}
//Delete head if == searchValue
if (head->value == searchValue)
{
nodePtr = head->next;
cout << head->value << " deleted" << endl;
delete head;
head = nodePtr;
}
else
{
//Set nodePtr to head
nodePtr = head;
//Skip nodes not equal num
while (nodePtr != NULL && nodePtr->value != searchValue)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
//Link previous node to the node after nodePtr and then delete
if (nodePtr)
{
previousNode->next = nodePtr->next;
cout << nodePtr->value << " deleted" << endl;
delete nodePtr;
}
}
}
//**
//Search List
//**
template <class T>
void linkedlist<T>::searchList(T searchValue)
{
ListNode *nodePtr; //Traverse our list
ListNode *previousNode = NULL; //Points to previous node
int counter = 0;
//Check if list is empty
if (!head)
{
cout << "This list is empty." << endl;
return;
}
//Check if head == searchValue
if (head->value == searchValue)
{
cout << head->value << " found at position 0" << endl;
}
else
{
//set nodePtr to head
nodePtr = head;
//Pass over all nodes that do not equal searchValue
while (nodePtr != NULL && nodePtr->value != searchValue)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
counter++;
}
//When nodePtr == searchValue
if (nodePtr)
{
cout << nodePtr->value << " found at position " << counter << endl;
}
else
{
cout << "-1: Value not found." << endl;
}
}
}
//**
//Destructor
//**
template <class T>
linkedlist<T>::~linkedlist()
{
ListNode *nodePtr; // To traverse the list
ListNode *nextNode; // To point to the next node
// Position nodePtr at the head of the list.
nodePtr = head;
// While nodePtr is not at the end of the list...
while (nodePtr != NULL)
{
// Save a pointer to the next node.
nextNode = nodePtr->next;
// Delete the current node.
delete nodePtr;
// Position nodePtr at the next node.
nodePtr = nextNode;
}
}
template <class T>
ostream &operator << (ostream stream, linkedlist<T> &obj)
{
stream >> obj.value;
return stream;
}
main.cpp
#include "linkedlist.h"
#include "WeatherStats.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
int int_numMonths; //Hold number of months value
double dbl_rain; //Hold rain value
double dbl_snow; //Hold snow value
double dbl_sunnyDays; //Hold sunny days value
//Create lnk_list object with weatherstats
linkedlist<weatherstats>weather_list;
cout << "Weather Data" << endl;
cout << endl;
cout << "What is the number of months you want to enter data for?: ";
cin >> int_numMonths;
cout << endl;
//Loop to enter each months values
for (int i = 0; i < int_numMonths; i++)
{
cout << "Month " << i + 1 << endl;
cout << "Enter amount of rain: " << endl;
cin >> dbl_rain;
cout << "Enter amount of snow: " << endl;
cin >> dbl_snow;
cout << "Enter number of Sunny Days: " << endl;
cin >> dbl_sunnyDays;
//Create weatherstats obj and pass it rain,snow and sunnyDays
weatherstats month_data(dbl_rain,dbl_snow,dbl_sunnyDays);
weather_list.appendNode(month_data);
}
weather_list.displayList();
}
Weatherstats.cpp
#include "WeatherStats.h"
#include <iostream>
using namespace std;
/*!
Constructors
!*/
weatherstats::weatherstats()
{
dbl_rain = 0;
dbl_snow = 0;
dbl_sunnyDays = 0;
}
weatherstats::weatherstats(double r, double s, double d)
{
dbl_rain = r;
dbl_snow = s;
dbl_sunnyDays = d;
}
/*!
Accessors
!*/
double weatherstats::getRain()
{
return dbl_rain;
}
double weatherstats::getSnow()
{
return dbl_snow;
}
double weatherstats::getsunnyDays()
{
return dbl_sunnyDays;
}
/*!
Mutators
!*/
void weatherstats::setRain(double r)
{
dbl_rain = r;
}
void weatherstats::setSnow(double s)
{
dbl_snow = s;
}
void weatherstats::setsunnyDays(double d)
{
dbl_sunnyDays = d;
}
//Overload Opperator
ostream& operator << (ostream &stream, weatherstats &obj)
{
stream <<&weatherstats::getRain << " - " << &weatherstats::dbl_snow << " - " << &weatherstats::getsunnyDays << endl;
return stream;
}
I'm going to take a stab in the dark with this, as I haven't touched templates or overloading for a couple of years.
Do you have the << operator overloaded for your weatherstats class?
Your error line is trying to print the value member variable. In your ListNode definition you say value is of type T (i.e. a template).
In your main() you are creating a linkedlist with your template type as weatherstats.
Your error also states that it cannot convert the weatherstats type.
So the question is: Are you Overloading << for the weatherstats class ?
Unfortunately, you haven't posted the code for this class, so we can't go any further than this. Edit: Code has been posted - still no evidence of overloading
(Also I think Baget makes a good point about the direction of your stream operator later on)
EDIT2: How should you call a function? Is it &classname::function or object.function()?
isn't stream >> obj.value; need to be stream<<obj.value;
it is OUTPUT stream not INPUT
If you can follow my main below, I run the program, I am able to enter an integer, it finds the next prime number, then asks for data. Once I enter data once, the program hangs. Seems to be in an infinite loop, or something. It doesn't crash. When I pause it, it brings up read.c file with an arrow on line 256. Not sure what this means whatsoever. Any help would be much appreciated.
I have the following class and member function declarations in hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#define TRUE 1
#define FALSE 0
#define VERBOSE 0x01
#define NON_VERBOSE 0x02
#include "linkedlist.h"
class hashTable{
public:
int keys;
int tableSize;
linkedList<int> **table;
hashTable(const int n);
//~hashTable();
void hash(int value);
int search(int value);
int divisionMethod(int value, int sizeOfTable);
int midSquareMethod(int value, int sizeOfTable);
int total();
void printHashTable();
int next_prime(int value, char flag);
};
// constructor
hashTable::hashTable(const int n){
linkedList<int> newList;
tableSize = next_prime(n, VERBOSE);
cout << "Table size is: " << tableSize << "\n"; // for debugging
system("pause"); // for debugging
table = new linkedList<int>*[tableSize];
for (int i = 0; i < tableSize; i++)
table[i] = { new linkedList<int> };
}
// Compute the Hash Function and "Hash" element into table
void hashTable::hash(int value){
table[value % tableSize]->addToHead(value);
keys++;
//divisionMethod(midSquareMethod(value, tableSize), tableSize)
}
// Simple Search Function
// Returns the element searched for if found, 0 otherwise
int hashTable::search(int value){
return(table[value % tableSize]->search(value));
}
// Divsion Method for producing a semi-unique key
int hashTable::divisionMethod(int value, int sizeOfTable){
int key;
key = value % sizeOfTable;
return(key);
}
// Middle Square Method for producing a semi-unique key
int hashTable::midSquareMethod(int value, int sizeOfTable){
int key;
key = ((value * value) & 0x0ff0) >> 4; // pick the middle 8 bits
return(key);
}
// Returns the total number of keys in the table
int hashTable::total(){
return(keys);
}
// Print the hash table (for demonstration purposes
void hashTable::printHashTable(){
int i = 0, valueToPrint;
while (i < tableSize){
cout << i << ": ";
valueToPrint = table[i]->removeFromHead();
while (valueToPrint != 0){
cout << valueToPrint << " -> ";
valueToPrint = table[i]->removeFromHead();
}
cout << "|" << endl;
i++;
}
}
int hashTable::next_prime(int value, char flag){
int FOUND = FALSE;
int n;
while (!FOUND) {
for (n = 2; (n * n) <= value && (value % n) != 0; ++n);
if ((n * n) <= value) {
if (flag == VERBOSE)
cout << value << " is divisible by " << n << "\n";
value++;
}
else {
if (flag == VERBOSE)
cout << "The next largest prime is " << value << "\n";
FOUND = TRUE;
}
}
return(value);
}
#endif
Here is my linkedlist.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
using namespace std;
template <class TYPE>
class Node{
public:
TYPE data;
Node* next;
// constructor
Node(TYPE const& x){
data = x;
next = NULL;
}
};
template <class TYPE>
class linkedList{
//struct Node{
// TYPE data;
// Node *next;
//};
public:
Node<TYPE> *head;
Node<TYPE> *tail;
int size;
// constructor
linkedList(){
head = NULL;
tail = NULL;
size = 0;
}
~linkedList();
void addToHead(TYPE value);
void addToTail(TYPE value);
TYPE removeFromHead();
TYPE removeFromTail();
TYPE search(TYPE searchData);
TYPE isEmpty();
};
//destructor
template <class TYPE>
linkedList<TYPE>::~linkedList(void){
while (head){
Node<TYPE> *temp = head;
head = head->next;
delete temp;
}
}
// Insert an element at the head (start) of the linked list
template <class TYPE>
void linkedList<TYPE>::addToHead(TYPE value){
Node<TYPE> *newNode = new Node<TYPE>(value);
if (isEmpty())
head = newNode;
else{
newNode->next = head;
head = newNode;
}
}
// Add an element to the tail (end) of the linked list
template <class TYPE>
void linkedList<TYPE>::addToTail(TYPE value){
Node<TYPE> *newNode = new Node<TYPE>(value);
Node *tempPtr;
if(isEmpty()){
head = newNode;
tail = newNode;
}
else{
tail->next = newNode;
tail = tail->next;
}
}
// Remove an element from start of Linked List
template <class TYPE>
TYPE linkedList<TYPE>::removeFromHead(){
TYPE tempValue;
Node<TYPE> *temp;
if (head){
tempValue = head->data;
temp = head;
if (head == tail)
head = tail = 0;
else
head = head->next;
delete temp;
return tempValue;
}
else
return 0;
}
// Remove an element from the end of the linked list
template <class TYPE>
TYPE linkedList<TYPE>::removeFromTail(){
TYPE tempValue;
Node *temp;
if (tail){
tempValue = tail->data;
if (head == tail){
delete head;
head = tail = 0;
}
else{
for (temp = head; temp->next != tail; temp = temp->next);
delete tail;
tail = temp;
tail->next = 0;
}
return tempValue;
}
else
return 0;
}
// Search for an element in the linked list
// Will return the element if found, otherwise it returns 0
template <class TYPE>
TYPE linkedList<TYPE>::search(TYPE searchData){
Node<TYPE> *temp;
temp = head;
while (temp->next != tail){
if (tail->data == searchData)
return searchData;
if (temp->data == searchData)
return searchData;
else
temp = temp->next;
}
return 0;
}
// isEmpty() function checks if head == NULL
template <class TYPE>
TYPE linkedList<TYPE>::isEmpty(){
return(head == NULL);
}
#endif
Here is my main:
#include "hashtable.h"
int main(){
int n, input;
cout << "Enter an integer: ";
cin >> n;
cout << "\n\n";
hashTable myHashTable(n);
cout << "Enter some values into the table:" << endl;
cin >> input;
while (input != 0){
myHashTable.hash(input);
cin >> input;
}
myHashTable.printHashTable();
}
Something must be wrong, you have in attribute of your hashTable class ... a hashTable pointer. It must be a linkedlist pointer, nop ?
I did find out what was causing all this. It was the way that I was implementing the linked lists in my array of pointers. Pretty much just programmer error from long nights. Of course there is a lot wrong with my code that I posted here, which I fixed it all, e.g. search function in my hash class, etc.,
Here is what I changed that pretty much fixed a good portion of my problem posted here:
hashTable::hashTable(const int n, char hFunction){
keys = 0;
hashFunction = hFunction;
tableSize = next_prime(n, VERBOSE);
cout << "Table size is: " << tableSize << "\n\n"; // for debugging
system("pause"); // for debugging
table = new linkedList<int>[tableSize];
I also changed my linkedList<int> **table to linkedList<int> *table. If anyone else needs any pointers on the rest of this NOW working hash function, just get a hold of me.
The program should ask the user to enter the ID number of the employee he or she wants to search for. If it is found the employee of that ID number is displayed. I can display the ID numbers and employees just by using the display functions but I can't figure out how to make the search function work and display the employees.
BINARYTREE
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <iostream>
using namespace std;
// This class is a template class that creates a binary
// tree that can hold values of any data type. It has
// functions to insert a node, delete a node, display the
// tree In Order, Pre Order and Post Order, search for a
// value, count the number of total nodes, left nodes,
// and a function to determine the height of the tree.
template <class T>
class BinaryTree
{
private:
struct TreeNode
{
T value; // The value in the node
TreeNode *left; // Pointer to left child node
TreeNode *right; // Pointer to right child node
};
TreeNode *root; // Pointer to the root node
// Private member functions
void insert(TreeNode *&, TreeNode *&);
void destroySubTree(TreeNode *);
void deleteNode(T, TreeNode *&);
void makeDeletion(TreeNode *&);
void displayInOrder(TreeNode *) const;
void displayPreOrder(TreeNode *) const;
void displayPostOrder(TreeNode *) const;
public:
// Constructor
BinaryTree()
{ root = NULL; }
// Destructor
~BinaryTree()
{ destroySubTree(root); }
// Binary tree operations
void insertNode(T);
bool searchNode(int);
void remove(T);
void displayPreOrder() const
{ displayPreOrder(root); }
void displayInOrder() const
{ displayInOrder(root); }
void displayPostOrder() const
{ displayPostOrder(root); }
};
//*********************************************************
// insert function accepts a TreeNode pointer and a *
// pointer to a node. The function inserts the node into *
// the tree pointer to by the TreeNode pointer. This *
// function is call recursively. *
//*********************************************************
template <class T>
void BinaryTree<T>::insert(TreeNode *&nodePtr, TreeNode *&newNode)
{
if (nodePtr == NULL)
nodePtr = newNode; // Insert the node
else if (newNode->value < nodePtr->value)
insert(nodePtr->left, newNode); // Search the left branch
else
insert(nodePtr->right, newNode);// Search the right branch
}
//*********************************************************
// insertNode creates a new node to hold item as its value*
// and passes it to the insert function. *
//*********************************************************
template <class T>
void BinaryTree<T>::insertNode(T item)
{
TreeNode *newNode; // Pointer to a new node
// Create anew node and store num in it
newNode = new TreeNode;
newNode->value = item;
newNode->left = newNode->right = NULL;
// Insert the node
insert(root, newNode);
}
//**********************************************************
// destroySubTree is called by the destructor. It deletes *
// all nodes in the tree. *
//**********************************************************
template <class T>
void BinaryTree<T>::destroySubTree(TreeNode *nodePtr)
{
if (nodePtr)
{
if (nodePtr->left)
destroySubTree(nodePtr->left);
if (nodePtr->right)
destroySubTree(nodePtr->right);
delete nodePtr;
}
}
//**********************************************************
// searchNode determines if a value is present in the tree.*
// If so, the function returns true. Otherwise it returns *
// false.
//**********************************************************
template <class T>
bool BinaryTree<T>::searchNode(T item)
{
TreeNode *nodePtr = root;
while (nodePtr)
{
if (nodePtr->value == item)
return true;
else if (item < nodePtr->value)
nodePtr = nodePtr->left;
else
nodePtr = nodePtr->right;
}
return false;
}
//*********************************************************
// remove calls deleteNode to delete the node whode value *
// member is the same as num *
//*********************************************************
template <class T>
void BinaryTree<T>::remove(T item)
{
deleteNode(item, root);
}
//*********************************************************
// deleteNode deletes the node whose value member is the *
// same as num *
//*********************************************************
template <class T>
void BinaryTree<T>::deleteNode(T item, TreeNode *&nodePtr)
{
if (item < nodePtr->value)
deleteNode(item, nodePtr->left);
else if (item > nodePtr->value)
deleteNode(item, nodePtr->right);
else
makeDeletion(nodePtr);
}
//*********************************************************
// makeDeletion takes a reference to apointer to the node *
// that is to be deleted. The node is removed and the *
// branches of the tree below the node are reattached *
//*********************************************************
template <class T>
void BinaryTree<T>::makeDeletion(TreeNode *&nodePtr)
{
// Define a temporary pointer to use in reattaching
// the left subtree
TreeNode *tempNodePtr;
if (nodePtr == NULL)
cout << "Cannot delete empty node.\n";
else if (nodePtr->right == NULL)
{
tempNodePtr = nodePtr;
nodePtr = nodePtr->left; // Reattach the left child
delete tempNodePtr;
}
else if (nodePtr->left == NULL)
{
tempNodePtr = nodePtr;
nodePtr = nodePtr->right; // Reattach the right child
delete tempNodePtr;
}
}
//*********************************************************
// The displayInOrder function displays the values in the *
// subtree pointed to by nodePtr, via inorder traversal *
//*********************************************************
template <class T>
void BinaryTree<T>::displayInOrder(TreeNode *nodePtr) const
{
if (nodePtr)
{
displayInOrder(nodePtr->left);
cout << nodePtr->value.getEmpID() << " "
<< nodePtr->value.getEmpName() << endl;
displayInOrder(nodePtr->right);
}
}
//*********************************************************
// The displayPreOrder function displays the values in the*
// subtree pointed to by nodePtr, via Preorder traversal *
//*********************************************************
template <class T>
void BinaryTree<T>::displayPreOrder(TreeNode *nodePtr) const
{
if (nodePtr)
{
cout << nodePtr->value.getEmpID() << " "
<< nodePtr->value.getEmpName() << endl;
displayInOrder(nodePtr->left);
displayInOrder(nodePtr->right);
}
}
//*********************************************************
// displayPostOrder function displays the values in the *
// subtree pointed to by nodePtr, via Postorder traversal *
//*********************************************************
template <class T>
void BinaryTree<T>::displayPostOrder(TreeNode *nodePtr) const
{
if (nodePtr)
{
displayInOrder(nodePtr->left);
displayInOrder(nodePtr->right);
cout << nodePtr->value.getEmpID() << " "
<< nodePtr->value.getEmpName() << endl;
}
}
#endif
EMPLOYEEINFO
#ifndef EMPLOYEEINFO_H
#define EMPLOYEEINFO_H
#include <string>
#include <iostream>
using namespace std;
// This class has two data members to hold the employee ID
// and the name of the employee.
class EmployeeInfo
{
private:
int empID; // To hold employee ID number
string empName; // To hold employee name
public:
// Default Constructor
EmployeeInfo();
// Constructor
EmployeeInfo(int, string);
// Mutators
void setEmpID(int);
void setEmpName(string);
// Accessors
int getEmpID();
string getEmpName();
// Overloaded operator. This works directly with
// the insert function of BinaryTree.h more specifically
// line 71. *For my knowledge*
bool operator < (const EmployeeInfo &e)
{
if (empID < e.empID)
return true;
return false;
}
// Overloaded operator for the search function
bool operator == (const EmployeeInfo &e)
{
if (empID == e.empID)
return true;
return false;
}
};
#endif
#include "EmployeeInfo.h"
//*********************************************************
// Default constructor intializes the data members *
//*********************************************************
EmployeeInfo::EmployeeInfo()
{
empName = "";
empID = 0;
}
//*********************************************************
// Constructor sets the data members *
//*********************************************************
EmployeeInfo::EmployeeInfo(int ID, string name)
{
empName = name;
empID = ID;
}
//*********************************************************
// setEmpID stores the employee ID number *
//*********************************************************
void EmployeeInfo::setEmpID(int ID)
{
empID = ID;
}
//*********************************************************
// setEmpName stores the full name of the employee *
//*********************************************************
void EmployeeInfo::setEmpName(string name)
{
empName = name;
}
//*********************************************************
// getEmpID returns the employee ID number *
//*********************************************************
int EmployeeInfo::getEmpID()
{
return empID;
}
//*********************************************************
// getEmpName returns the full name of the employee *
//*********************************************************
string EmployeeInfo::getEmpName()
{
return empName;
}
MAIN
#include "EmployeeInfo.h"
#include "BinaryTree.h"
#include <iostream>
using namespace std;
int main()
{
// Create an instance of BinaryTree
BinaryTree<EmployeeInfo> tree;
// Create an EmployeeInfo object
EmployeeInfo emp1(1021, "John Williams");
EmployeeInfo emp2(1057, "Bill Witherspoon");
EmployeeInfo emp3(2487, "Jennifer Twain");
EmployeeInfo emp4(3769, "Sophia Lancaster");
EmployeeInfo emp5(1017, "Debbie Reece");
EmployeeInfo emp6(1275, "George McMullen");
EmployeeInfo emp7(1899, "Ashley Smith");
EmployeeInfo emp8(4218, "Josh Plemmons");
tree.insertNode(emp1);
tree.insertNode(emp2);
tree.insertNode(emp3);
tree.insertNode(emp4);
tree.insertNode(emp5);
tree.insertNode(emp6);
tree.insertNode(emp7);
tree.insertNode(emp8);
// Search for an employee
char again = 'y'; // To hold yes
int id; // To hold ID number from user
cout << "Would you like to search for an employee?\n";
cout << "Enter Y for yes or N for No: ";
cin >> again;
if (again)
{
do
{
cout << "Enter the ID number of the employee: ";
cin >> id;
// Create an EmployeeInfo object to store the user's
// search parameters
EmployeeInfo info;
info.setEmpID(id);
// If search finds what the user entered display the
// corresponding employee
if (tree.searchNode(info))
{
cout << info.getEmpName() << endl; // Not right?
}
else
cout << "ID not found!" << endl;
cout << "Would you like to search for an employee?\n";
cout << "Enter Y for yes or N for No: ";
cin >> again;
}while (again == tolower('Y'));
}
// Display in order
tree.displayInOrder();
cout << endl;
tree.displayPreOrder();
cout << endl;
tree.displayPostOrder();
}
Ok I changed the code up to get the bool to work and the if (tree.searchNode(info)) but I don't think the cout statement is right. Can someone look at my searchNode function and how I called it in main and let me know what I'm doing wrong?
Problem lies here
info.setEmpID(1021);
info.setEmpID(1057);
info.setEmpID(2487);
info.setEmpID(3769);
info.setEmpID(1017);
info.setEmpID(1275);
info.setEmpID(1899);
info.setEmpID(4218);
info.setEmpName("John Williams");
info.setEmpName("Bill Witherspoon");
info.setEmpName("Jennifer Twain");
info.setEmpName("Sophia Lancaster");
info.setEmpName("Debbie Reece");
info.setEmpName("George McMullen");
info.setEmpName("Ashley Smith");
info.setEmpName("Josh Plemmons");
You are not adding anything to info but every time you call setEmpName() you are updating info object.
You can make few changes in searchNode method as below
template <class T>
bool BinaryTree::searchNode(T &item)
{
TreeNode *nodePtr = root;
while (nodePtr)
{
if (nodePtr->value == item)
{
item.setEmpName(nodePtr->value.getEmpName());
return true;
}
else if (item < nodePtr->value)
nodePtr = nodePtr->left;
else
nodePtr = nodePtr->right;
}
return false;
}
In main() method
do
{
cout << "Enter the ID number of the employee: ";
cin >> id;
BinaryTree<EmployeeInfo> temp;
if ((temp=tree.searchNode(id))!=NULL)
{
cout << temp.getEmpName() << endl;
}
else{
cout<<"ID not found"<<endl;
}
cout << "Would you like to search for an employee?\n";
cout << "Enter Y for yes or N for No: ";
cin >> again;
}while (again == tolower('Y'));
//New changes...
Made change in declaration of searchNode(T) to searchNode(T &)...In your new code the name of employee found was not set in info thats why when you are trying to print EmpName there was not output...So the change is pass the reference of EmployeeInfo to searchitem(T &)
template
bool BinaryTree::searchNode(T &item)
{
TreeNode *nodePtr = root;
while (nodePtr)
{
if (nodePtr->value == item)
{
item.setEmpName(nodePtr->value.getEmpName());
return true;
}
else if (item < nodePtr->value)
nodePtr = nodePtr->left;
else
nodePtr = nodePtr->right;
}
return false;
}
I just implemented a Destructor and I am getting an “Access violation reading location”. I beleive the problem is in my while loop but just can't figure it out.
Below is my code. If needing to reference any other part of my List Class please let me know.
Thanks!
List::List():first(NULL), last(NULL), nodeListTotal(0)
{
}
List::~List()
{
Node* currentNode = first;
while( currentNode != 0 )
{
Node* temp = currentNode->getNext();
delete currentNode;
currentNode = temp;
}
first = 0;
}
Here is my entire List class. I have made the changes recommended, removed the first = 0; and change 0 to nullptr
#include "Node.h"
#include <string>
using namespace std;
class List
{
private:
int nodeListTotal;
Node* first;
Node* last;
public:
//Constructor
List();
//Destructor
~List();
//Copy-Constructor
//List(const List& theList);
//////Overloading Assignment Operator
//List& operator=(const List& L);
void push_back(Node*);
void push_front(Node*);
Node* pop_back();
Node* pop_front();
Node* getFirst() const;
Node* getLast() const;
int getListLength() const;
};
List::List():first(NULL), last(NULL), nodeListTotal(0)
{
}
// Destructor
List::~List()
{
Node* currentNode = first;
while( currentNode != nullptr )
{
Node* temp = currentNode->getNext();
delete currentNode;
currentNode = temp;
}
}
// Copy-Constructor
//List::List(const List& theList)
//{
// Node * tempPtr = new Node;
// tempPtr = theList.first;
// List(tempPtr);
//
// while (tempPtr != NULL)
// {
// Node * copyNode = new Node;
// copyNode = tempPtr;
// tempPtr = tempPtr->getNext();
// nodeListTotal++;
// }
//}
// Overloading Assignemnt Operator
//List& List::operator=(const List& L)
//{
// List* overList;
// Node* temp = L.first;
//
// while( temp != NULL ) {
// overList->getLast();
// temp = temp -> getNext();
//
// return *this;
//}
void List::push_back(Node* newNode)
{
Node* temp = last;
if (temp)
temp->setNext(newNode);
else
first = newNode;
last = newNode;
nodeListTotal++;
}
void List::push_front(Node* newNode)
{
Node* temp = getFirst();
newNode->setNext(temp);
first = newNode;
nodeListTotal++;
if (!temp)
last = first;
}
Node* List::pop_back()
{
Node* old = last;
if (first == last)
{
first = 0;
last = 0;
}
else
{
Node* temp = first;
for (int i = 0; i < (nodeListTotal - 1); i++)
{
temp = temp->getNext();
}
temp->setNext(NULL);
last = temp;
}
nodeListTotal--;
return old;
}
Node* List::pop_front()
{
Node* temp = getFirst();
first = temp->getNext();
if (!first)
last = 0;
nodeListTotal--;
return temp;
}
Node* List::getFirst() const
{
return first;
}
Node* List::getLast() const
{
return last;
}
int List::getListLength() const
{
return nodeListTotal;
}
Node.h
#include <string>
using namespace std;
class Node
{
private:
string dataItem;
string dataUnit;
int unitTotal;
Node* next;
public:
//Constructor
Node();
Node(int, string, string);
string getDescription( )const;
void setDescription(string);
string getQuantityName()const;
void setQuantityName(string);
int getQuantityNumber()const;
void setQuantityNumber(int);
Node* getNext( )const;
void setNext(Node*);
};
Node::Node(void):dataItem("None"), dataUnit("None"), unitTotal(0), next(NULL)
{
}
Node::Node(int q, string i, string u):dataItem(i), dataUnit(u), unitTotal(q), next(NULL)
{
}
string Node::getDescription( ) const
{
return dataItem;
}
void Node::setDescription(string iSetter)
{
dataItem = iSetter;
}
string Node::getQuantityName() const
{
return dataUnit;
}
void Node::setQuantityName(string uSetter)
{
dataUnit = uSetter;
}
int Node::getQuantityNumber() const
{
return unitTotal;
}
void Node::setQuantityNumber(int tSetter)
{
unitTotal = tSetter;
}
Node* Node::getNext() const
{
return next;
}
void Node::setNext(Node* nSetter)
{
next = nSetter;
}
Driver.cpp
int main( )
{
//===============================================
// PART ONE
//===============================================
cout << "\nPart I: push_front and pop_front\n";
cout << "\n----------------------------------\n";
List groceries;
// test push_back function
groceries.push_front(new Node(1, "gallon", "milk") );
groceries.push_front(new Node(2, "loaves", "bread") );
groceries.push_front(new Node(1, "dozen", "eggs" ) );
groceries.push_front(new Node(1, "package", "bacon") );
cout << "\nThe original nodes in the List:\n";
printList(groceries);
cout << "\n----------------------------------\n";
// test push_front function
cout << "\nAdding to the front of the List:\n";
cout << "\n----------------------------------\n";
groceries.push_front(new Node(2, "lbs", "hamburger") );
groceries.push_front(new Node(1, "dozen", "hamburger buns") );
printList(groceries);
cout << "\n----------------------------------\n";
// test pop-front
cout << "\nRemoving the first node from the list.\n";
cout << "\n----------------------------------\n";
Node* item = groceries.pop_front( );
cout << "\nPopped " << item->getDescription( ) << " from the list.\n\n";
printList(groceries);
if (item != NULL)
delete item;
// ===============================================
// PART TWO: Uncomment this block to test part two
// ===============================================
cout << "\n----------------------------------\n";
cout << "\nPart Two: Push_back and pop_back";
// test push_back
groceries.push_back(new Node(2, "cans", "orange juice") );
groceries.push_back(new Node(1, "lb", "swiss cheese") );
cout << "\nAdding two nodes at the end\n";
cout << "\n----------------------------------\n";
printList(groceries);
// test pop-back
cout << "\n----------------------------------\n";
cout << "\nRemove last node from the list\n";
cout << "\n----------------------------------\n";
item = groceries.pop_back( );
cout << "\nPopped " << item->getDescription( ) << " from the list.\n\n";
printList(groceries);
if (item != NULL)
delete item;
// ============================================
// end of part two
// ============================================
// ================================================
// PART THREE: uncomment this block to test part three
// ================================================
/*
// create a second list to test assignment
cout << "\n\n--------------extra credit------------------\n";
cout << "\n\n overloaded assignment operator\n";
cout << "The hardware list ...\n";
cout << "\n-------------------------------------------\n";
List hardware;
hardware.push_back(new Node(2, "lbs", "nails") );
hardware.push_back( new Node(3, "gals", "white paint") );
hardware.push_back(new Node(1, "piece", "plywood") );
printList(hardware);
hardware = groceries;
cout << "\n-------------------------------------------\n";
cout << "\nafter assignment";
cout << "\n-------------------------------------------\n";
printList(hardware);
cout << "\n-------------------------------------------\n";
cout << "\nTest the copy constructor\n";
cout << "\n-------------------------------------------\n";
printFirstNode(hardware);
// ==============================================
// end of part 3
// ==============================================
*/
cout << "\n-------------------------------------------\n";
cout << "\nEnd of Test";
cout << "\n-------------------------------------------\n";
system("PAUSE");
return 0;
}
Looks like pop back does not remove last node from the list, but returns it. Then the node is deleted and in list's destructor you try to delete it second time.
The push_back() method could be your culprit, coupled with the failure to initialize Node:next to zero. If only one node is added to the list using push_back then the value of that node's next member would be unknown and in the destructor an attempt to delete a second node referring to a random memory location would cause the access error.
Either ensure that the nodes values are initialized, or ensure that node.next is set explicitly in push_back() if it's the first node added to the list.
Something to note on pop_back() and pop_front().
Calling pop_back() on an empty list would still decrement nodeListTotal.
Calling pop_front() on an empty list would actually cause an access violation trying to access address 0.
The below deletion of node is causing the problem while cleaning up in the destructor.
if (item != NULL)
delete item;
When you do the pop_back you're deleting that(last) node in main(), but what happens to the node which is before that? it was pointing to the one which you deleted and is not set to NULL.
So, in the destructor when you start deleting the nodes you're checking for the NULL value of the nodes. All goes fine but now for the last one next wasn't set to NULL, instead it is still pointing to the one which you just deleted. Hence, tries to free the node which is already freed.
Then your code crashes.
Set the previous node's next to NULL whenever you're freeing the successive node.