0

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.

3 Answers 3

2

Another approach.

  1. Keep Database::Node:print() very simple -- print the data on the object only.
  2. 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;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, it compiles without errors but print only the addresses of the objetcs.
Change cout << data; to cout << *data;
That may be due to error in creating in the list of nodes.
2

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

3 Comments

Doing so causes two compilation errors: class Database::Node is private
@Medvednic Ahh, I'm sorry; there are two ways to get around that problem, one is to define the operator inline (i.e. where it is declared in the nested class), the second is to add a second line friend ostream& operator<<( ostream&, const Node*& pNode ); within the outer class.
Error of invalid conversion from const to non const here: Databse::Node* pCurrNode = pNode; why the implementation doesn't have a return type?
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.