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
Related
Compiles fine but when executed I get segmentation fault (core dumped) error. I've tested each function individually and the add function is the only one giving me this error. Add function is supposed to add the value to the head of the linked list. When running the code, values get added to the list correctly and I can display the list, but the error follows shortly after.
//Homework 11
//Linked List
#include <iostream>
using namespace std;
//Declaring class and Linked List.
class NumberList
{
private:
struct ListNode
{
double value;
struct ListNode *next;
};
ListNode *head;
public:
NumberList()
{ head = NULL;}
~NumberList()
{
ListNode *nodePtr;
ListNode *nextNode;
nodePtr = head;
while (nodePtr != NULL)
{
nextNode = nodePtr->next;
delete nodePtr;
nodePtr = nextNode;
}
}
//Function inserting node at the head.
void add(double x)
{
ListNode *newNode;
ListNode *nodePtr;
ListNode *previousNode = NULL;
newNode = new ListNode;
newNode->value = x;
if (!head)
{
head = newNode;
newNode -> next = NULL;
}
else
{
nodePtr = head;
previousNode = NULL;
}
if (previousNode == NULL)
{
head = newNode;
newNode->next = nodePtr;
}
}
//Function to find matching values.
bool isMember(double x)
{
int pos = 0;
bool flag = false;
if (head == NULL)
{
cout << "List is Empty" << endl;
return flag;
}
ListNode *nodePtr;
nodePtr = head;
while (nodePtr != NULL)
{
pos++;
if (nodePtr->value == x)
{
flag = true;
cout << x << " was found at position " << pos << endl;
}
nodePtr = nodePtr->next;
}
if (!flag)
{
cout << x << " not found in the list." << endl;
}
return flag;
}
//Function to display linked list values.
void display() const
{
ListNode *nodePtr;
if (head == NULL)
{
cout << "List is empty." << endl;
return;
}
nodePtr = head;
cout << "The list goes: " << endl;
while (nodePtr != NULL)
{
cout << nodePtr->value << endl;
nodePtr = nodePtr->next;
}
cout << "End" << endl;
}
//Function to delete a selected value in the list.
void deletNodeAll(double x1)
{
ListNode *nodePtr;
ListNode *previousNode;
if (!head)
return;
if (head->value == x1)
{
nodePtr = head->next;
delete head;
head = nodePtr;
}
else
{
nodePtr = head;
while ( nodePtr != NULL && nodePtr->value != x1)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
if (nodePtr)
{
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
}
};
int main()
{
NumberList Z;
Z.add(3);
Z.add(4);
Z.add(2);
Z.add(5);
Z.add(7);
Z.add(4);
Z.add(7);
Z.add(5);
Z.add(2);
Z.display();
Z.isMember(2);
Z.deletNodeAll(2);
Z.display();
return 0;
}
your add() method causes segmentation fault because for first node you should update the head and head->next and return but you didn't.
if (!head) {
head = newNode;
newNode -> next = NULL;
return ;/* do this else this again check previousNode == NULL also
which is not needed 1st time */
}
Also deletNodeAll() deletes only first occurrence of number you are passing, there is a bug in logic,check it yourself.
When I run my program, it works as intended, except the items in the list have no spaces between them when the displayList() function is called. I have 3 files. The main cpp file is ShoppingList.cpp. Then I have two other files for the linked list classification and implementation.
//ShoppingList.cpp
//Michael Hery
//COP 2001
//11/9/17
//Shopping List
#include <iostream>
#include <string>
#include "strList.h"
#include "strlist.cpp"
using namespace std;
int main()
{
//Define a NumberList object
StrList list;
string item;
string delItem;
int menuSelection;
//Ask the user how many items to
//put in the list
cout << "How many items would you like to put it the list? >> ";
cin >> menuSelection;
while (menuSelection < 1)
{
cout << "Please enter a valid number (greater than 0) >> ";
cin >> menuSelection;
}
for (int i = 0; i < menuSelection; i++)
{
cout << "Please enter item " << i + 1 << ": ";
cin >> item;
list.appendNode(item);
}
list.displayList();
cout << "Which item do you wish to delete from the list? >> ";
cin >> delItem;
while (delItem == "")
{
cout << "Please enter a valid item >> ";
cin >> delItem;
}
list.deleteNode(delItem);
list.displayList();
//Wait for user input to exit program
system("PAUSE");
return 0;
}
//strList.h
#ifndef STRLIST_H
#define STRLIST_H
#include <iostream>
#include <string>
namespace
{
class StrList
{
private:
struct ListNode
{
std::string value;
struct ListNode *next;
};
ListNode *head;
public:
//Constructor
StrList()
{
head = nullptr;
}
//Destructor
~StrList();
//Linked List Operations
void appendNode(std::string item);
void insertNode(std::string item);
void deleteNode(std::string item);
void displayList() const;
};
}
#endif
//strList.cpp
#ifndef STRLIST_CPP
#define STRLIST_CPP
#include <iostream>
#include <string>
#include "strList.h"
void StrList::appendNode(std::string item)
{
ListNode *newNode;
ListNode *nodePtr;
//Allocate a new node and store item there
newNode = new ListNode;
newNode->value = item;
newNode->next = nullptr;
//If there are no nodes in the list
//make newNode the first node
if (!head)
head = newNode;
else //Otherwise, insert newNode at the end
{
//Initialize nodePtr to head of the 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;
}
}
void StrList::insertNode(std::string item)
{
ListNode *newNode;
ListNode *nodePtr;
ListNode *previousNode = nullptr;
//Allocate a new node and store num there
newNode = new ListNode;
newNode->value = item;
//If there are no nodes in the list
//make newNode the first node
if (!head)
{
head = newNode;
newNode->next = nullptr;
}
else //Otherwise, insert newNode
{
//Position nodePtr at the head of list
nodePtr = head;
//Initialize previousNode to nullPtr
previousNode = nullptr;
//Skip all nodes whose values is less than num
while (nodePtr != nullptr && nodePtr->value < item)
{
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
//If the new node is to be the 1st in the list,
//insert it before all the other nodes
if (previousNode == nullptr)
{
head = newNode;
newNode->next = nodePtr;
}
else //Otherwise insert after the previous node
{
previousNode->next = newNode;
newNode->next = nodePtr;
}
}
}
void StrList::deleteNode(std::string item)
{
ListNode *nodePtr; //To traverse the list
ListNode *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 == item)
{
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 != nullptr && nodePtr->value != item)
{
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;
}
}
}
StrList::~StrList()
{
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 != nullptr)
{
//Save a pointer to the next node
nextNode = nodePtr->next;
//Delete the current node
delete nodePtr;
//Position nodePtr at the next node
nodePtr = nextNode;
}
}
void StrList::displayList() const
{
ListNode *display;
display = head;
std::cout << "**********************************" << std::endl;
std::cout << "**** Your Shopping List ****" << std::endl;
std::cout << "**********************************" << std::endl;
while (display)
{
std::cout << display->value;
display = display->next;
}
}
#endif
The problem lies in the displayList(); function towards the end of the file.
Add a separator for between your values.
char const* sep = "";
while (display)
{
std::cout << sep << display->value;
sep = " ";
display = display->next;
}
Head and tail are getting populated, and print out the values, but nodePtr stays empty for some reason. When I debug in VS2015, head and tail number is getting populated, while field this stays empty
Here's Linked_List
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
#include <iostream>
class LinkedList
{
public:
struct Node
{
int number;
Node * next;
Node() : number(NULL), next(NULL) {};
Node(int number_, Node * next_ = NULL)
{
number = number_;
next = next_;
}
}*head, *tail, *nodePtr;
LinkedList();
~LinkedList();
void add(int num);
friend std::ostream& operator<<(std::ostream& out, LinkedList& list);
private:
int size;
};
#endif // _LINKED_LIST_
Implementation file
include "linkedlist.h"
#include <iostream>
using namespace std;
LinkedList::LinkedList() : head(NULL), tail(NULL), nodePtr(NULL)
{
nodePtr = new Node();
}
LinkedList::~LinkedList()
{
Node * curr, *temp;
curr = head;
temp = head;
while (curr != NULL)
{
curr = curr->next;
delete temp;
temp = curr;
}
}
void LinkedList::add(int num)
{
Node * newNode = new Node();
newNode->number = num;
cout << newNode->number;
if (head == NULL)
{
head = newNode;
tail = newNode;
size++;
}
else
{
tail->next = newNode;
newNode->next = NULL;
tail = newNode;
size++;
}
//cout << nodePtr->number; //empty, or some random
//just some tests
cout << head->number;
if (head->next != NULL)
{
cout << head->next->number;
}
cout << tail->number;
cout << endl;
}
std::ostream & operator<<(std::ostream & out, LinkedList & list)
{
out << list.nodePtr->number << endl;
return out;
}
Main.cpp
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main()
{
int num;
LinkedList list;
list.add(1);
list.add(2);
list.add(3);
cout << list;
cout << "Press 1: ";
cin >> num;
return 0;
}
You're missing a fundamental concept here. nodePtr is not some magical node that knows about all your other nodes, or knows about linked lists, or can be used to print all their numbers.
When you do this:
out << list.nodePtr->number << endl;
All you are doing is outputting the value that you initialized when you allocated a new Node and stored a pointer in nodePtr:
nodePtr = new Node();
That called the default constructor for Node which set nodePtr->number to zero. (side-note, you initialized it to NULL, not 0 -- you should not mix integer types with pointer types, so change it to initialize the value to 0).
Its value stays 0 because you never modify it. And nodePtr always points at that single node because you never modified nodePtr.
What you're actually wanting to do is print out your list. Let me suggest the normal way to do this, by starting at head and following the node linkages:
std::ostream & operator<<(std::ostream & out, const LinkedList & list)
{
for( Node *node = list.head; node != nullptr; node = node->next )
{
out << node->number << std::endl;
}
return out;
}
And finally, I suggest you remove nodePtr from your class completely.
You only use nodePtr in the constructor, you never change it's values.
I keep getting a Segmentation fault (core dumped) error every time I try to run my code with g++ on Linux. It compiles fine, but then that happens ... All the functions (remove, add and print) seem to have the same problem, I can't seem to figure out what's wrong... Please heeeelppp.
#include <iostream>
#include <string>
using namespace std;
//Create a node struct
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
//set to NULL
Queue::Queue() {
head = tail = NULL;
size = 0;
}
//destructor
//call remove until empty
Queue::~Queue() {
while (!isEmpty())
remove();
}
//adds a node with the given data at the back of the queue
void Queue::add(int d) {
Node *temp = new Node();
temp->data = d;
temp->next = NULL;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
//removes the node at the head of the queue and returns its data
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *temp = new Node;
temp = head;
int value = head->data;
//moves pointer to next node
head = head->next;
cout << "Removed: " << head->data << endl;
size--;
delete temp;
return value;
}
}
//determines if the queue is empty
bool Queue::isEmpty() {
return (size == 0);
}
//prints the contents of the queue from front to back, or front
//to back, depending on the value of the parameter
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p = new Node;
if (o == true) {
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
p = head;
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
p = tail;
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(8);
return 0;
}
EDIT: I've made some changes to the code... But I'm still getting the same error. I assume I'm not updating the head and the tail and/or the next and prev nodes correctly... I don't know why it's wrong or what I'm missing, though.
#include <iostream>
#include <string>
using namespace std;
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
Queue::Queue() {
head = tail = NULL;
size = 0;
}
Queue::~Queue() {
while (!isEmpty())
remove();
}
void Queue::add(int d) {
Node *temp = new Node;
temp->data = d;
temp->next = NULL;
temp->prev = tail;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
return 0;
} else {
Node *temp = head;
int value = head->data;
cout << "Removed: " << head->data << endl;
//moves pointer to next node
head = head->next;
head->prev = NULL;
size--;
delete temp;
return value;
}
}
bool Queue::isEmpty() {
return (size == 0);
}
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p;
if (o == true) {
p = head;
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
p = tail;
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(9);
q.add(10);
q.add(11);
q.add(12);
q.add(13);
q.add(14);
q.add(15);
q.add(16);
q.remove();
q.remove();
q.printQueue(true);
q.printQueue(false);
return 0;
}
Lots of problems:
You have a double-linked Node but never update its prev member in the add/remove methods.
You are keeping track of both the Queue head/tail but don't properly update them when you add/remove nodes.
Both your forward and reverse loops in printQueue() are wrong and result in an infinite loop for any queue with 2 or more elements. Queue output should be just something like:
Node *p = head;
while (p != NULL)
{
cout << p->data << " ";
p = p->next;
}
Possible null pointer deference in remove() at cout << "Removed: " << head->data << endl; since you've already moved the head pointer by this time. Move the head after the cout.
Memory leak in Queue::remove() at Node *temp = new Node;. Just do Node* temp = head;.
Memory leak in Queue::printQueue() at Node *p = new Node;. You don't need to allocate a node here.
No return value in remove() for an empty queue.
Edit
Don't forget to initialize the tail when adding a node to an empty list:
if (isEmpty()) {
head = temp;
tail = temp;
}
To remove a node from the head of a non-empty list it should be something like:
Node *temp = head;
head = head->next;
if (head) head->prev = NULL;
size--;
delete temp;
if (isEmpty()) tail = NULL;
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.