Linked List output crash - c++

My program hangs when outputting contents of my linked list. I can't change the header, only the cpp file.
playlist.h:
class PlayList {
private:
struct SongNode {
Song data;
SongNode* next;
SongNode (const Song& s, SongNode* nxt = 0)
: data(s), next(nxt)
{}
};
friend std::ostream& operator<< (std::ostream& out, const PlayList& s);
SongNode* first; // head of a list of songs, ordered by title, then artist
//Snip...
inline
std::ostream& operator<< (std::ostream& out, const PlayList& pl)
{
for (PlayList::SongNode* current = pl.first; current != 0; current = current->next)
out << current->data << std::endl;
return out;
}
playlist.cpp
using namespace std;
PlayList::PlayList()
: totalTime(0,0,0)
{
}
void PlayList::operator+= (const Song& song)
{
SongNode* newNode = new SongNode(song, first);
first = newNode;
}
When outputting the list all of the data that is supposed to print, does print, but then the program hangs.

In the constructor of class PlayList, you need to initialise first:
public:
PlayList() : first(NULL) {}
Otherwise, in your operator<<, you reach the end of the list and instead of encountering NULL, you just get a junk pointer.

You forgot to initialize first in the constructor.

Related

How to access the child class through the parent class object with shared pointers

I have a linked list using a parent Node class and a child Node class (called Transaction). The linked list class (called Ledger) is using shared pointers to access the Node and Transaction class.
My goal is to use the << operator with a shared pointer of Node, called endPtr (the linked list uses a tail instead of a head, going from last to first), and traverse each Node instance and access the Transaction class variables of that parent Node and print them out.
This is my Node header file:
#pragma once
#include <memory>
#include <string>
#include <vector>
using namespace std;
class Node {
protected:
shared_ptr<Node> prev;
string nodeType;
public:
Node();
Node(shared_ptr<Node>);
shared_ptr<Node> getPrev() const;
void setPrev(shared_ptr<Node>);
string getType();
};
My Transaction header file that inherits from Node:
#pragma once
#include "Node.h"
class Transaction: public Node {
private:
string toName;
string fromName;
int amount;
public:
Transaction();
Transaction(string, string, int);
string getToName() const;
string getFromName() const;
int getAmount() const;
void setToName(string);
void setFromName(string);
void setAmount(int);
shared_ptr<Transaction> getPrev();
void setPrev(shared_ptr<Transaction>);
};
And this is the Ledger header and cpp files:
class Ledger {
private:
string toName;
string fromName;
int amount;
vector<pair<string, int>> ledgerVector;
shared_ptr<Node> endPtr;
int count = 0;
public:
Ledger();
Ledger& operator+=(Transaction);
Ledger& operator-=(shared_ptr<Transaction>);
void Add(Transaction);
friend ostream& operator<<(ostream& os, const Ledger&);
};
cpp:
Ledger& Ledger::operator+=(Transaction newTxn) {
shared_ptr<Transaction> newTransaction = make_shared<Transaction>(newTxn);
shared_ptr<Node> newPointer = make_shared<Node>(newTxn);
if (endPtr != nullptr) {
newPointer->setPrev(endPtr);
endPtr = newPointer;
}
else
endPtr = newPointer;
}
ostream& operator<<(ostream& os, const Ledger& ledger) {
weak_ptr<Node> newNode = ledger.endPtr;
auto node = newNode.lock();
while (node != nullptr) {
if (node->getType() == "TRANSACTION") {
shared_ptr<Transaction> transNode = make_shared<Transaction>(node.get());
string fromName = transNode->getFromName();
cout << fromName << endl;
}
node = node->getPrev();
}
}
Finally, main.cpp:
Transaction t1 = Transaction("Albert", "Bob", 100);
Transaction t2 = Transaction("James", "Alice", 50);
Ledger myLedger;
myLedger += t1;
myLedger += t2;
cout << myLedger;
As you can see in the += operator, that is how I'm adding new transaction nodes, by converting the Transaction into a smart pointer and then creating a Node smart pointer from the same Transaction. At which point, I've assigned it the endPtr of the Ledger class.
This is what the endPtr looks like, as seen through Node instances:
The endPtr has two Node instances, as attempted in the main(), but I have no idea if the content of the Transaction is stored in them as well, nor do I know how to access it.
I understand there is no reason to go about it this way, as it may not be optimal, but any guidance on accessing inherited class variables through a parent object instance while using smart pointers would be greatly appreciated.
Your Ledger's operator+= (and presumably Add()) and operator<< are implemented incorrectly. Try this instead:
class Ledger {
...
public:
...
Ledger& operator+=(const Transaction&);
...
void Add(const Transaction&);
friend ostream& operator<<(ostream& os, const Ledger&);
};
void Ledger::Add(const Transaction &newTxn)
{
auto newPointer = make_shared<Transaction>(newTxn);
newPointer->setPrev(endPtr);
endPtr = newPointer;
}
Ledger& Ledger::operator+=(const Transaction &newTxn) {
Add(newTxn);
return *this;
}
ostream& operator<<(ostream& os, const Ledger& ledger) {
auto node = ledger.endPtr;
while (node != nullptr) {
auto transNode = dynamic_pointer_cast<Transaction>(node);
if (transNode != nullptr) {
os << transNode->getFromName() << endl;
}
node = node->getPrev();
}
return os;
}

C++: Making a function friend of multiple classes?

Here's a Doubly Linked List class that I wrote:
template <class T>
class DLL
{
class Node
{
T m_data;
Node* m_prev;
Node* m_next;
Node(const T& data) :m_data{ data }, m_prev{ nullptr }, m_next{ nullptr }{}
friend class DLL;
friend std::ostream& operator<<(std::ostream& out, const Node& node)
{
out << node.m_data;
return out;
}
};
Node* m_first = nullptr;
public:
DLL& add(const T& data)
{
Node* temp = new Node{ data };
if (m_first)
{
temp->m_next = m_first;
m_first->m_prev = temp;
m_first = temp;
}
else {
m_first = temp;
}
return *this;
}
friend std::ostream& operator<<(std::ostream& out, const DLL& dll)
{
Node* trav = dll.m_first;
while (trav)
{
out << *trav << ' ';
trav = trav->m_next; //C2248: Cannot access private member declared in class DLL::Node.
}
return out;
}
~DLL()
{
Node* trav = m_first->m_next;
Node* foll = m_first;
while (trav)
{
delete foll;
foll = trav;
trav = trav->m_next;
}
delete foll;
}
};
In the DLL's friend function to output the DLL into stream, there's an error that pops up saying the function cannot access a private member of the class Node.
After a couple of tries, I came up with a solution by declaring this friend function as a friend of the Node class as seen below:
class Node
{
T m_data;
Node* m_prev;
Node* m_next;
Node(const T& data) :m_data{ data }, m_prev{ nullptr }, m_next{ nullptr }{}
friend class DLL;
friend std::ostream& operator<<(std::ostream& out, const Node& node)
{
out << node.m_data;
return out;
}
friend std::ostream& operator<<(std::ostream& out, const DLL& dll);
};
Now the function std::ostream& operator<<(std::ostream& out, const DLL& dll) is able to access m_next in the Node class and everything's working fine...or so I think.
My question here is: Can a function be a friend of more than one class as we see here or does what I've done invoke undefined behavior?
Yes, a function can be a friend of more than one class.
But friends are not inherited, so even if operator<< is a friend of DLL<T> and DLL<T> a friend of DLL<T>::Node, it doesn't automatically make operator<< a friend of DLL<T>::Node, hence it can't access the private DLL<T>::Node::m_next.
The solution is to declare it a friend of DLL<T>::Node, like you did.
A friend function declaration in some class only designates the function as a friend of that class, not as a member. You can absolutely make a function friend of multiple classes. For example:
class B;
class A {
int a = 2;
friend auto operator+(A a, B b) -> int;
};
class B {
int b = 5;
friend auto operator+(A a, B b) -> int;
};
auto operator+(A a, B b) -> int {
return a.a + b.b;
}
Demo

friend function can't access private struct

I'm trying to write a friend function to go through a linked list and output the characters in the list, but for some reason I can't declare Nodes within the friend function. Here is my code:
This is the function:
std::ostream& operator<<(std::ostream& out, LinkedList& list)
{
Node *tempNode = nullptr;
*tempNode = *beginningOfList;
std::cout << "list: ";
while(tempNode)
{
std::cout << tempNode->letter;
if (tempNode->next)
std::cout << ", ";
tempNode = tempNode->next;
}
return out;
}
Here is the header file:
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
#include <ostream>
class LinkedList
{
public:
LinkedList();
~LinkedList();
void add(char ch);
bool find(char ch);
bool del(char ch);
friend std::ostream& operator<<(std::ostream& out, LinkedList& list);
private:
struct Node
{
char letter;
Node *next;
};
Node *beginningOfList;
};
#endif // _LINKED_LIST_
When I try to compile it, I get the messages "Node was not declared in this scope," as well as "*tempNode was not declared in this scope" and "*beginningOfList was not declared in this scope." I'm guessing the problem has to do with namespaces, but I'm really not sure.
It's telling the truth. Node etc were not declared in that scope. Your operator is a global function but those things are in the scope of LinkedList. Try calling them LinkedList::Node, list->beginningOfList etc.

How to overload << operator in nested class

I have three classes: Client Database and Node as a nested class in Database.
Data of a Node is a pointer to a Client object, the Client class has it's own overloaded << operator.
I need to have an overloaded << operator that will output all of the linked list's data.
The problem that I encounter is not being able to iterate through all of the list using the << overloaded operator, the best thing that I can do is to output the head node's data using getData member, for some reason Node::Print won't output all of the lists Client *data.
Here is the Database class and two of the mentioned methods << and print().
Databse.h
class Databse
{
private:
class Node //node as nested class
{
public:
Node();
void setNode(Client*&);
Node* nextNode(Node*&);
Client getData();
void print (Node*);
private:
Client* data; //holds pointer to Client object
Node* next; //holds pointer to next node in list
};
Node *head; //holds the head node
int nClients;
public:
Databse();
friend ostream& operator<<(ostream&, const Databse&);
Node* getHead() const;
~Databsey();
};
Databse.cpp relevant methods:
ostream& operator<<(ostream& out, const Databse& obj)
{
out << endl << "The databse holds" << obj.nClients << " clients:" << endl;
out << obj.head->getData();
obj.head->print(obj.getHead());
return out;
}
void Database::Node::print (Node* str)
{
Node* current = str ;
while (current->next)
{
cout << current->data;
current = current->next;
}
}
Thanks.
Another approach.
Keep Database::Node:print() very simple -- print the data on the object only.
Let ostream& operator<<(ostream& out, const Database& obj) take care of iterating over the nodes in the list and print each node.
Here's the updated code.
class Database
{
private:
class Node //node as nested class
{
public:
Node();
void setNode(Client*&);
Node* nextNode(Node*&);
// Need this to allow iteration of the list of nodes
// of a Database object.
Node* nextNode() const
{
return next;
}
Client getData();
// Print the data associated with just one node.
void print(ostream& out) const
{
cout << data;
}
private:
Client* data; //holds pointer to Client object
Node* next; //holds pointer to next node in list
};
Node *head; //holds the head node
int nClients;
public:
Database();
friend ostream& operator<<(ostream&, const Database&);
Node* getHead() const;
~Database();
};
ostream& operator<<(ostream& out, const Database& obj)
{
out << endl << "The databse holds" << obj.nClients << " clients:" << endl;
// Iterate over the nodes of the Database object
// and print each one.
Database::Node* current = obj.head;
for ( ; current != NULL; current = current->nextNode() )
{
current->print(out);
// Printing a whitespace between nodes makes the
// output more readable.
out << " ";
}
return out;
}
Just add the overloaded operator<< as you would with any other class, for instance:
class Databse
{
private:
class Node //node as nested class
{
public:
Node();
void setNode(Client*&);
Node* nextNode(Node*&);
Client getData();
friend ostream& operator<<( ostream&, const Node*& pNode );
private:
Client* data; //holds pointer to Client object
Node* next; //holds pointer to next node in list
};
Node *head; //holds the head node
int nClients;
public:
Databse();
friend ostream& operator<<(ostream&, const Databse&);
friend ostream& operator<<( ostream&, const Node*& pNode );
Node* getHead() const;
~Databsey();
};
And then implement it as follows:
ostream& operator<<( ostream& out, const std::add_lvalue_reference<Databse::Node*>::type pNode )
{
Databse::Node* pCurrNode = pNode;
while( pCurrNode )
{
std::cout << pCurrNode->data;
pCurrNode = pCurrNode->next;
}
return out;
}
fix print that accept ostream
ostream& Database::Node::print (ostream& out, Node* str)
{
Node* current = str ;
while (current) //bugfix
{
out << current->data;
current = current->next;
}
return out
}
and then you can call
ostream& operator<<(ostream& out, const Databse& obj)
{
out << endl << "The databse holds" << obj.nClients << " clients:" << endl;
out << obj.head->getData();
obj.head->print(out,obj.getHead());
return out;
}

Ambiguous overload for ‘operator<<’ in ‘std::cout <<

I have the following main.cpp file
#include "listtemplate.h"
//#include <iostream>
using namespace std;
int main()
{
int UserChoice;
cout << "Hello, World!" << endl;
cin >> UserChoice;
cout << UserChoice;
}
In it's current form, everything works. I enter an integer, and that integer is printed to the screen. However, when I uncomment the cout << "Hello, World!" << endl line, I get the following error
main.cpp:10: error: ambiguous overload for ‘operator<<’ in ‘std::cout << "Hello, World!"’
I can also make it work by commenting out #include "listtemplate.h", uncommenting the hello world line, and including <iostream> in main (currently accessible through the template. Can anyone see what I'm missing here?
listtemplate.h
#ifndef LISTTEMPLATE_H
#define LISTTEMPLATE_H
#include "list.h"
using namespace std;
// Default constructor
template <class Type>
list<Type> :: list() : Head(NULL) {}
// Destructor
template <class Type>
list<Type> :: ~list()
{
Node *Temp;
while (Head != NULL)
{
Temp = Head;
Head = Head -> Next;
delete Temp;
}
}
// Copy constructor
template <class Type>
list<Type> :: list (const Type& OriginalList)
{
Node *Marker;
Node *OriginalMarker;
OriginalMarker = OriginalList.Gead;
if (OriginalMarker == NULL) Head = NULL;
else
{
Head = new Node (OriginalMarker -> Element, NULL);
Marker = Head;
OriginalMarker = OriginalMarker -> Next;
while (OriginalMarker != NULL)
{
Marker -> Next = new Node (OriginalMarker -> Next);
OriginalMarker = OriginalMarker -> Next;
Marker = Marker -> Next;
}
}
}
// Copy assignment operator
template <class Type>
list<Type>& list<Type> :: operator= (const list<Type>& Original)
{
Node *Marker;
Node *OriginalMarker;
// Check that we are not assigning a variable to itself
if (this != &Original)
{
// First clear the current list, if any
while (Head != NULL)
{
Marker = Head;
Head = Head -> Next;
delete Marker;
}
// Now build a new copy
OriginalMarker = Original.Head;
if (OriginalMarker == NULL) Head = NULL;
else
{
Head = new Node (OriginalMarker -> Element, NULL);
Marker = Head;
OriginalMarker = OriginalMarker -> Next;
while (OriginalMarker != NULL)
{
Marker -> Next = new Node (OriginalMarker -> Element, NULL);
OriginalMarker = OriginalMarker -> Next;
Marker = Marker -> Next;
}
}
}
return (*this);
}
// Test for emptiness
template <class Type>
bool list<Type> :: Empty() const
{
return (Head == NULL) ? true : false;
}
// Insert new element at beginning
template <class Type>
bool list<Type> :: Insert (const Type& NewElement)
{
Node *NewNode;
NewNode = new Node;
NewNode -> Element = NewElement;
NewNode -> Next = Head;
return true;
}
// Delete an element
template <class Type>
bool list<Type> :: Delete (const Type& DelElement)
{
Node *Temp;
Node *Previous;
// If list is empty
if (Empty()) return false;
// If element to delete is the first one
else if (Head -> Element == DelElement)
{
Temp = Head;
Head = Head -> Next;
delete Temp;
return true;
}
// If the list has only one element which isn't the specified element
else if (Head -> Next == NULL) return false;
// Else, search the list element by element to find the specified element
else
{
Previous = Head;
Temp = Head -> Next;
while ((Temp -> Element != DelElement) && (Temp -> NExt != NULL))
{
Previous = Temp;
Temp = Temp -> Next;
}
if (Temp -> Element == DelElement)
{
Previous -> Next = Temp -> Next;
delete Temp;
return true;
}
else return false;
}
}
// Print the contents of the list
template <class Type>
void list<Type> :: Print (ostream& OutStream) const
{
Node *Temp;
Temp = Head;
while (Temp != NULL)
{
OutStream << Temp -> Element << " ";
Temp = Temp -> Next;
}
}
// Overloaded output operator
template <class Type>
ostream& operator<< (ostream& OutStream, const list<Type>& OutList)
{
OutList.Print (OutStream);
return OutStream;
}
#endif
list.h
#ifndef LIST_H
#define LIST_H
#include <iostream>
#include <cstddef>
using namespace std;
template <class Type>
class list
{
private:
struct Node
{
public:
Type Element;
Node *Next;
Node() : Next(NULL) {} // Default constructor
Node (Type Data, Node *PNode = NULL) : // Non-default constructor
Element (Data),
Next (PNode) {}
};
Node *Head;
public:
list();
~list();
list (const Type& OriginalList);
bool Empty() const;
bool Insert (const Type& NewElement);
bool Delete (const Type& DelElement);
void Print (ostream& OutStream) const;
list& operator= (const list<Type>& Original);
};
template <class Type>
ostream& operator<< (ostream& OutStream, const Type& OutList);
#endif
This is in fact an interesting question. The main issue is, as others have pointed before that you have declared the following signature:
template <typename T>
std::ostream& operator<<( std::ostream&, T const & );
And that triggers the ambiguity, as it is a catch-all template. But why is it that the compiler can insert (unambiguously) an integer into cout but it cannot insert a const char*?
The reason for that is in the definition of the std::basic_ostream template and free functions that are required in the standard. In particular, the template class basic_ostream contains member functions to insert basic types, including int. On the other hand, the insertion of const char* into streams is defined as a templated free function. Bringing the three declarations together:
namespace std {
template <typename CharT, typename traits = char_traits<CharT> >
class basic_ostream {
// ...
basic_ostream<CharT,traits>& operator<<(int n); // [1]
// ...
};
template<class charT, class traits> // [2]
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const char*);
}
template <typename T> // [3]
std::ostream& operator<<( std::ostream&, T const & ); // user defined
Now, when the compiler encounters the expression std::cout << 5, it finds that [1] is a non-templated perfect match. It is non-templated as std::cout is an object of a concrete instantiation of the basic_ostream class template, when the compiler considers the members of that class, the type is fixed. The method itself is not templated.
The template [3] could match the same use, but because [1] is not templated it takes precedence in the overload resolution, and there is no ambiguity.
Now, when the compiler sees the expression std::cout << "Hello world";, it performs the lookup and it finds (among other options that cannot be matched and are thus discarded) options [2] and [3]. The problem is that now, both options are templates, the first one can be resolved by matching CharT = char and traits = char_traits<char>, while the second can be matched by making T = const char* (the first argument is a concrete instantiated type). The compiler cannot make up its mind (there is no partial order that defines which option it should follow), and it triggers the ambiguity error.
The really interesting point in the question is that while both [1] and [2] seem to be templated on the arguments CharT and traits basically in the same way they are not considered in the same way by the compiler, the reason for that is that lookup finds [1] as a member of std::cout, that means that in [1], basic_ostream<char,char_traits<char> > is the concrete known type of the first argument and it is fixed. The template is the class, not the function, and the class instantiation types are fixed before lookup considers the member functions. On the other hand, when it ADL finds [2] and tries to match against the call, basic_ostream<CharT, traits> is a generic type that can be matched to the type of cout.
I hope this is not too confusing, but I think it is nice to know the subtle difference of similarly looking code.
I think that the problem is that in your header you've prototyped this function:
template <class Type>
ostream& operator<< (ostream& OutStream, const Type& OutList);
instead of this one:
template <class Type>
ostream& operator<< (ostream& OutStream, const list<Type>& OutList);
The version you've prototyped says that it's an operator << that can print out anything, not lists of anything. Consequently, when you write
cout << "Hello, world!" << endl;
The compiler can't tell which function it's supposed to call - the standard output function or the one you've defined in your list header.
declared as:
ostream& operator<< (ostream& OutStream, const Type& OutList);
in the function definition as:
ostream& operator<< (ostream& OutStream, const list<Type>& OutList)