Again there's something wrong with addresses..

Heya again, sorry for the bombardment of threads I'm creating.
Once again I'm in need of your assistment as I only get an address printed out, which wasn't the intentions.

Including the entire code this time.

Node.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef NODE_H
#define NODE_H

class Node {
	
public:
	Node(std::string d) : data(d) {};
	Node(std::string d, Node *n);
	std::string getText() const { return data; }
	Node* getNext() const { return next; }
	void setNext(Node* other) { next = other; }
	
private:
	std::string data;
	Node *next;
	
};

#endif 


Node.cpp
1
2
3
4
5
6
7
8
#include <iostream>
#include "Node.h"
using namespace std;

Node::Node(string d, Node *n) {
	next = new Node(n->getText());
	data = d;
}


LinkedList.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "Node.h"

class LinkedList {
	
public:
	
	LinkedList() : size(0) {};
	int getSize() const { return size; }
	std::string getFirst() const { return first->getText(); }
	void insert(std::string item);	
	std::string toString() const;
	
private:
	
	Node *first, *last;
	int size;
	
};

#endif 


LinkedList.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include "Node.h";
#include "LinkedList.h"
using namespace std;

void LinkedList::insert(string item) {
	
	if(first == NULL) {
		
		first = last = new Node(item);
		
	}
	
	else {
		
		string temp = "Hi";
		Node* header = new Node(temp, first);
		bool done = false;
		while(header->getNext() != NULL && !done) {
			int result = item.compare(header->getText());
			if(result < 0) {
				Node* newNode = new Node(item, header->getNext());
				header->setNext(newNode);
				if(newNode->getNext() == first)
					first = newNode;
				done = true;
			}
			else
				header = header->getNext();
		}
		
		if(!done) {
			Node* newNode = new Node(item);
			last->setNext(newNode);
			last = newNode;
		}
		
	}
	
	size++;
	
}

string LinkedList::toString() const {
	
	if(first == NULL)
		return "[]";
	
	string result = "[" + first->getText();
	Node* temp = first->getNext();
	
	while(temp != NULL) {
		
		result += ", " + temp->getText();
		temp = temp->getNext();
		
	}
	
	return result + "]";
	
}

ostream& operator<< (ostream& outs, const LinkedList* obj) { return outs << obj->toString(); }


And finally, main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include "Node.h"
#include "LinkedList.h"
using namespace std;

int main() {
	
	LinkedList* list = new LinkedList();
	string text1 = "Hi";
	string text2 = "Yo";
	
	list->insert(text1);
	list->insert(text2);
	cout << list << endl;
	return 0;
	
}


Most likely there's something wrong with the toString() things I have in LinkedList.cpp but the problem might be deeper down..

Thanks again for your help!
Here, you make list a pointer:

LinkedList* list = new LinkedList();


And here, you pass a pointer to cout:

cout << list << endl;

A pointer is an object that holds a single value; an address. If you pass a pointer to cout, you get that single value; an address. If you want cout to print out something else, like a string, you must pass it that string.

That LinkedList::toString function looks like what you need to get a string of all the contents.
Last edited on
Yes but.. according to the last thread I made here about this problem, I create the custom cout operator<< to take a pointer and then dereference it as seen here:

 
ostream& operator<< (ostream& outs, const LinkedList* obj) { return outs << obj->toString(); }


This was the solution I got from the other thread and it worked great! .. until I decided to split the files into header files and source files.
I had a look in your code for a custom operator<< but I can't see one. Where is it?

Edit: Oh, there it is, at the bottom. I'd expect to see it in your class declaration. What happens if you move it to there?
Last edited on
That's what I had expected too when I first tried to implement it.
If I move it inside the class I get a compiler error, saying that the method only accepts 1 argument and not 2 like I have.
I've always found operator overloading a pain and I've not much experience of it; I know that some overloads can be part of your class definition and some can't. What happens if you move your definition to above when you actually use it?

Edit: Hang on... if you overload an operator with a class definition, one of the two operands is assumed to be the class itself, so you only need to specify one operand. Could that be the cause of the error message you got when you put it in the class definition?

Alternatively, as it is now, but in the header, outside the actual class definition.
Last edited on
ostream& operator<< (ostream& outs, const LinkedList* obj) { return outs << obj->toString(); }

This is unintuitive.

People will (or at least should) expect an address to be printed when they output a pointer. If they want the data to be printed they will output an object:

1
2
3
4
5
6
7
8
9
LinkedList* p = whatever;

cout << p;  // this should print an address
cout << *p;  // this should print whatever that address points to (data)

LinkedList obj;

cout << obj;  // this should print the data
cout << &obj;  // this should print an address 


This is typical. It's what any C++ programmer would expect.

You are changing this behavior and making a pointer output data instead of the address. This is very confusing.

You really should change that code to this:

ostream& operator<< (ostream& outs, const LinkedList& obj) { return outs << obj.toString(); }
The problem with that is that then it won't work to output it..
 
ostream& operator<< (ostream& outs, const LinkedList& obj) { return outs << obj.toString(); }


And then call it with:

 
cout << list << endl;


it will output an address. Doing this instead:

 
cout << *list << endl;


will result in a compiler error.

I don't really understand how you mean I should change the code.. :/
Doing this instead:

cout << *list << endl;

will result in a compiler error.


If 'list' is a LinkedList* (which it is), that code will not give you a compiler error. It will work just as you expect.

Try it. It will be fine.
I did try it, gave me this:

main.cpp: In function ‘int main()’:
main.cpp:16: error: no match for ‘operator<<’ in ‘std::cout << * list’
you need to put your << operator overload in the header file. main.cpp can't see it if it is in a separate cpp file.

Delete the operator from your cpp file and put this in your header file instead:

1
2
3
4
5
inline ostream& operator<< (ostream& outs, const LinkedList& obj)
{
  outs << obj.toString();
  return outs;
}


(make special note of the inline keyword)
linked lists are beginner? thats kind of disappointing.
I'm not sure how I would do that :o
Do you mean in the headerfile INSIDE the class? Or outside the class?

Tried both. Outside class:
1
2
3
4
5
}; // Class ends

inline ostream& operator<< (ostream& outs, const LinkedList& obj) { return outs << obj.toString(); }

#endif 

That gave me this:

In file included from LinkedList.cpp:12:
LinkedList.h:31: error: expected initializer before ‘&’ token


Inside class:
1
2
3
4
5
6
7
public:
LinkedList() : size(0) {};
int getSize() const { return size; }
std::string getFirst() const { return first->getText(); }
void insert(std::string item);	
std::string toString() const;
inline ostream& operator<< (ostream& outs, const LinkedList& obj) { return outs << obj.toString(); }

That gave me this:

In file included from LinkedList.cpp:12:
LinkedList.h:23: error: ISO C++ forbids declaration of ‘ostream’ with no type
LinkedList.h:23: error: ‘ostream’ declared as an ‘inline’ field
LinkedList.h:23: error: expected ‘;’ before ‘&’ token
LinkedList.h:25: error: expected `;' before ‘private’


Sorry if I'm really newbie...
@acorn: What do you mean?? This is a beginners forum, isn't it..? :o
Tanax:

Yeah sorry -- I'm not reading your code closely enough.

ostream needs <iostream> to work. So do it like this:

linkedlist.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef LINKEDLIST_H
#define LINKEDLIST_H

#include <iostream>  // <- include iostream here
#include "Node.h"

class LinkedList {
	// class here
};

// then the operator here
//  but be sure to use std:: prefix for ostream:

inline std::ostream& operator<< (std::ostream& outs, const LinkedList& obj) { return outs << obj.toString(); }

#endif  


That should finally work.

Sorry I was only giving you half instructions before.
Ah! Ofcourse, didn't think of that!
Thank you for the help, it works now the way it should!

I am encountering another error however, don't know if I should start a new thread for it. Think I'm just gonna use this one instead. Basically, it just adds some values to the list and some are not added.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main() {
	
	LinkedList* list = new LinkedList();
	
	string text1 = "Hi";
	string text2 = "Yo";
	string text3 = "Nope";
	
	list->insert(text1);
	list->insert(text2);
	list->insert(text3);
	
	cout << *list << endl;
	
	return 0;
	
}


This will output correctly:

[Hi, Yo, Nope]


However, if I change "Nope" to "Byee" the output becomes:

[Hi, Yo]


and discard the 3rd Node.. I assume this has something to do with the insert method inside the LinkedList.cpp. Would you mind taking a look at it? I'm trying to figure it out but can't really do it
Disch wrote:
(make special note of the inline keyword)
Why inline instead of separate declaration and definition?

@Tanax: could you explain your code. Why do you create 2 nodes when insert? (one with the magic word "Hi"
Is a sorted list?
1
2
//LinkedList* list = new LinkedList();
LinkedList list;


Edit: You don't initialize your pointers to NULL. Node::next, List::first, List::last

1
2
3
4
Node::Node(string d, Node *n) {
	next = new Node(n->getText()); //why it creates another node?
	data = d;
}
Last edited on
Why inline instead of separate declaration and definition?


Because then it won't be inlined.
Topic archived. No new replies allowed.