Print Function - Linked-List c++ - c++

I am trying to figure out what I am doing wrong with this printList Function. I am getting the following compiler error:
No operator "<<" matches these operands.
The function is as follows:
void printList(const List& theList)
{
for(Node* i = theList.getFirst(); i != theList.getLast(); ++i)
{
cout << *i << " ";
cout << endl;
}
}
I have the following as well,
#include "List.h"
#include <iostream>
I am thinking my print function is just way off base. Can anyone point me in the right direction?
Here are my classes, I don't have a List::Iterator. What would you suggest?
class List
{
private:
int nodeListTotal;
Node* first;
Node* last;
public:
//Constructor
List();
void push_back(Node*);
void push_front(Node*);
Node* pop_back();
Node* pop_front();
Node* getFirst() const;
Node* getLast() const;
int getListLength() const;
void retrieve(int index, int& dataItem) const;
};
class Node
{
private:
string dataItem;
string dataUnit;
int unitTotal;
Node* next;
public:
//Constructor
Node();
Node(int, string, string);
string getDescription( );
void setDescription(string);
string getQuantityName();
void setQuantityName(string);
int getQuantityNumber();
void setQuantityNumber(int);
Node* getNext( );
void setNext(Node*);
};

You need to overload operator<< for Node type:
std::ostream& operator<<(std:::ostream& os, const Node& node)
{
os << node.getQuantityName() << " " << node.getDescription();
return os;
}

As the error message says
No operator "<<" matches these operands.
you don't have the << operator defined for your class.

In your printList() function, replace cout << *i << " "; with
cout << i->getDescription() << endl;

Related

Invalid use of template name ' ' without an argument list

I'm trying to create simple stack using linked lists in C++. Suddenly I encountered the problem which is (I think) connected with templates. I lack knowledge in that structures thats why I tried to create something and learn with it.
My problem is with node * top; what should I change ? any idea?
My code is :
#include <iostream>
#include <cstdlib>
using namespace std;
template<typename T>
class node {
public:
T object;
node * next;
};
node *top = NULL;
template<typename T>
class Stack{
public:
void push(T obj);
void pop();
void display(ostream & out) const;
};
void Stack :: push(T obj){
node * tempNode = new node;
tempNode->object = obj;
tempNode->next = top;
top = tempNode;
}
void Stack :: display(ostream & out) const{
if(top == NULL){
cout << "Stack is Empty"<<endl;
return;
}
else{
node *temp = top;
while(temp!=NULL){
cout << "Here is your elements :"<<"\n";
cout << temp->object<<endl;
temp = temp->next;
}
cout <<endl;
}
}
void Stack :: pop(){
if (top = NULL){
cout << "List is Empty"<<endl;
return;
}
cout << "Your object: "<<top->object << " is removed"<<endl;
top = top->next;
}
ostream & operator << (ostream & out, const Stack & s){
s.display(out);
return out;
}
I'm guessing top should be a member of Stack not a global variable? You also need to specify the template type of node:
template<typename T>
class Stack{
node<T> *top = NULL;
public:
void push(T obj);
void pop();
void display(ostream & out) const;
};
When defining methods of templated classes out of line you need to specify the template type for the class:
template<typename T>
void Stack<T> :: push(T obj){
Your << operator also needs to be a template:
template<typename T>
ostream & operator << (ostream & out, const Stack<T> & s){
s.display(out);
return out;
}

C++ overloaded << operation only prints memory address of LinkedList

I am trying to make a Linked List Container LLC and overload the << operator as a friend. It seems like no mater what I do it either prints the memory address or throws a segmentation fault. I dont totally understand c++ yet so it is probably something obvious.
in LLC.cpp
ostream& operator<<(ostream& os, const LLC* list){
Node *curr = list.first;
for(curr; curr != NULL; curr= curr -> next){
os << curr -> data << "\n";
}
return os;
}
int main(int argc, char *argv[]){
string arr [] = {"a","b","c","d","e","f"};
LLC* link = new LLC(arr);
cout<<"testing: ";
cout<<(link);
}
in LLC.h
struct Node {
std::string data;
Node *next;
};
class LLC {
private:
Node *first;
Node *last;
public:
int main(int argc, char *argv[]);
LLC(){
first=NULL;
last=NULL;
}
friend std::ostream& operator<<(std::ostream& os, const LLC*);
std::ostream already has an operator<< that takes a pointer (via void*) as input. That is why you get hex output. Your operator<< overload should be taking in the LLC object by const reference, not by const pointer, to avoid ambiguities.
You did not post enough code to demonstrate the segfault error, but I suspect it is because you are not managing your node instances correctly inside the list, so when your operator<< tries to access them, it encounters a bad pointer along the way and crashes.
Try something more like this:
LLC.h
#ifndef LLCH
#define LLCH
#include <iostream>
#include <string>
struct Node {
std::string data;
Node *next;
Node(const std::string& d);
};
class LLC {
private:
Node *first;
Node *last;
public:
LLC();
template<size_t N>
LLC(std::string (&arr)[N])
: first(NULL), last(NULL) {
for(size_t i = 0; i < N; ++i) {
addToBack(arr[i]);
}
}
// other constructors, destructor, etc...
void addToBack(const std::string &s);
// other methods ...
friend std::ostream& operator<<(std::ostream& os, const LLC& list);
// other operators ...
};
#endif
LLC.cpp
#include "LLC.h"
Node::Node(const std::string& d)
: data(d), next(NULL) {
}
LLC::LLC()
: first(NULL), last(NULL) {
}
// other constructors, destructor, etc...
void LLC::addToBack(const std::string &s) {
Node *n = new Node(s);
if (!first) first = n;
if (last) last->next = n;
last = n;
}
// other methods ...
std::ostream& operator<<(std::ostream& os, const LLC& list) {
for(Node *curr = list.first; curr != NULL; curr = curr->next) {
os << curr->data << "\n";
}
return os;
}
// other operators ...
Main.cpp
#include <iostream>
#include <string>
#include "LLC.h"
int main(int argc, char *argv[]) {
std::string arr[] = {"a", "b", "c", "d", "e", "f"};
LLC* link = new LLC(arr);
cout << "testing: " << *link;
delete link;
/* or simply:
LLC link(arr);
cout << "testing: " << link;
*/
return 0;
}

Compiler not understanding recursive function to print tree level-order C++

I'm currently attempting to solve the following problem:
Write a function void TreeNode::levelOrder(int n) with wrapper void Tree::levelOrder() to print a tree level-order using recursion
This is the class header:
#ifndef TREE_H
#define TREE_H
#include <algorithm>
class TreeNode {
private:
int key;
TreeNode *left;
TreeNode *right;
public:
TreeNode(int key);
void insert(int key);
void display(TreeNode *p, int lvl);
void preOrder();
void inOrder();
void postOrder();
int size();
int height();
};
class Tree {
private:
TreeNode *root;
public:
Tree();
Tree(int *a, int n);
void insert(int key);
void preOrder();
void inOrder();
void postOrder();
void display(TreeNode *p);
int size();
int height();
};
void TreeNode::display(TreeNode *p, int lvl){
if (p!=NULL){
if (p->left) display(p->left, lvl + 4);
if (p->right) display(p->right, lvl + 4);
if (lvl) {
std::cout << std::setw(lvl) << ' ';
}
cout << p->key << "\n";
}
}
void Tree::display(TreeNode *p){
if (p!=NULL){
return display(p,0);
}
With these two functions, I am still getting the following error:
"./Tree.h:139:20: error: too many arguments to function call, expected single
argument 'p', have 2 arguments
return display(p,3);
~~~~~~~ ^
./Tree.h:137:1: note: 'display' declared here
void Tree::display(TreeNode *p){ "
I don't understand why the compiler can't recognize to call the function from TreeNode class with 2 arguments. Instead, the compiler is telling me the recursive function should only expect one argument.
I know I'm most likely not understanding the bigger picture here so could anyone try and clear this issue up for me? Thanks alot.
The issue is in this method:
void Tree::display(TreeNode *p){
if (p!=NULL){
return display(p,0);
}
return display(p,0); means return this->display(p,0); and the compiler is right.
What you probably meant is p->display(p, 0);.
As a side note, the display() methods in both classes seem to be static methods (and they don't have any reason to be); they don't use the properties of the object used to invoke them.
In order to be correct OOP, you should rewrite them as follows:
void TreeNode::display(int lvl)
{
if (left) {
left->display(lvl + 4);
}
if (right) {
right->display(lvl + 4);
}
if (lvl) {
std::cout << std::setw(lvl) << ' ';
}
cout << key << "\n";
}
void Tree::display(){
if (root) {
root->display(0);
}
}

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;
}

template using another template

Here is a cut-down version of a template List code (adapted from http://www.daniweb.com/software-development/cpp/threads/237391/c-template-linked-list-help)
List complains (compile error) that "Node is not a type". Why is this, and what is the fix?
I tried replacing the "class Node" with a "struct Node" (and related changes), and the struct version worked fine. So the main question seems to be: how does a template-class access another template-class?
#include <iostream>
using namespace std;
template <typename T>
class Node
{
public:
Node(){}
Node(T theData, Node<T>* theLink) : data(theData), link(theLink){}
Node<T>* getLink( ) const { return link; }
const T getData( ) const { return data; }
void setData(const T& theData) { data = theData; }
void setLink(Node<T>* pointer) { link = pointer; }
private:
T data;
Node<T> *link;
};
template <typename T>
class List {
public:
List() {
first = NULL;
last = NULL;
count = 0;
}
void insertFirst(const T& newData) {
first = new Node(newData, first);
++count;
}
void printList() {
Node<T> *tempt;
tempt = first;
while(tempt != NULL){
cout << tempt->getData() << " ";
tempt = tempt->getLink();
}
}
~List() { }
private:
Node<T> *first;
Node<T> *last;
int count;
};
int main() {
List<int> myIntList;
cout << "Inserting 1 in the list...\n";
myIntList.insertFirst(1);
myIntList.printList();
cout << endl;
List<double> myDoubleList;
cout << "Inserting 1.5 in the list...\n";
myDoubleList.insertFirst(1.5);
myDoubleList.printList();
cout << endl;
}
You are using
new Node(newData, first);
within the List template. At that point, Node does not refer to a type, but to a template. But of course to create an instance of a type with new, you need a type there.
The most probable thing you want to do is to make it a type by instantiating the template, i.e.
new Node<T>(newData, first);