I'm writing a linked list, and using my main function to test it. Here's my code:
#include <iostream>
using namespace std;
class LinkedList {
int value;
LinkedList* next;
public:
LinkedList(int valueIn, LinkedList* nextIn) {
value = valueIn;
next = nextIn;
}
LinkedList(int valueIn) {
value = valueIn;
}
int getValue() {
return value;
}
void addNode(LinkedList* node) {
next = node;
}
LinkedList& getNext() {
return *next;
}
};
int main() {
cout << "starting..." << std::endl;
LinkedList list1(1);
LinkedList list2(2, &list1);
cout << list1.getValue() << " --> " << list1.getNext().getValue() << std::endl;
return 0;
}
I expect the output to be 1 --> 2, but I get 1 -->. As far as I understand, getNext() should return a reference to another list (list2 in this case), but something seems to be going wrong. My debugging efforts show me that list2 does have the correct value 2 when it's initialized, but when it's referenced for the final output, it doesn't seem to have anything for value. I can't for the life of me figure out why this is. Could someone help me to understand?
You are insertin list1(which is actually a node) to the end of list2, not the other way around, yet you call getNext() on list1. You should change the code in main to the below:
int main() {
std::cout << "starting..." << std::endl;
LinkedList list1(1);
LinkedList list2(2, &list1);
std::cout << list2.getValue() << " --> " << list2.getNext().getValue() << std::endl;
return 0;
}
Please note that there are a couple of other things which would be better to change:
Create a list class and a Node class woud make things clearer
Initializing the pointer to be NULL(or nullptr from C++11) in the LinkedList(int valueIn) constructor
Return the pointer to the node in getNext() rather than copy the node
You are not getting a blank value. Actually your program is crashing when you are trying to call list1.getNext().getValue() as getNext() is returning reference to a NULL.
You are doing the opposite of what you want to do.
Your list2 is pointing to list1 and list1 is pointing to NULL.
You should change your code with this:
LinkedList list2(2);
LinkedList list1(1, &list2);
cout << list1.getValue() << " --> " << list1.getNext().getValue() << std::endl;
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm working on creating a doubly linked list. I seem to be having issues with the pushBack function (supposed to add a node to the end of the list). Somehow it just replaces the first node and points to itself as both the previous and next node. When I go to print the list, it just goes on forever because the next node isn't NULL (because as I said, it's pointing to itself for some reason). Posted below is the entire program. I think I might be having an issue with scope or possible am using the pointers incorrectly.
#include <iostream>
class Node {
public:
Node();
Node(int *val, Node *nx = NULL, Node *prev = NULL) {
value = val; next = nx; previous = prev;
}
void setPrev(Node* prev) { previous = prev; }
void setNext(Node* nx) { next = nx; }
void setVal(int* x) { value = x; }
Node* getPrev() { return previous; }
Node* getNext() { return next; }
int* getVal() { return value; }
private:
int* value;
Node *next;
Node *previous;
};
class LinkedList {
public:
LinkedList() : front(NULL), back(NULL) {}
bool empty() { return front == NULL; }
void pushBack(Node *nd) {
if (back == NULL) {
front = nd;
back = nd;
}
else {
back->setNext(nd);
nd->setPrev(back);
back = nd;
}
std::cout << "Front: " << *front->getVal() << std::endl;
std::cout << "Back: " << *back->getVal() << std::endl;
}
Node* topFront() { return front; }
void printFront() {
int *x = front->getVal();
std::cout << *x << std::endl;
}
void print() {
if (empty()) {
std::cout << "List is empty" << std::endl;
}
else {
std::cout << "Print list" << std::endl;
Node *x = front;
int count = 1;
// First just print the first element, then the rest
int *y = front->getVal();
std::cout << count << ": ";
std::cout << *y << std::endl;
x = x->getNext();
while (x != NULL) {
std::cout << count << ": ";
int *z = x->getVal(); std::cout << *z << std::endl;
x = x->getNext();
}
}
}
private:
Node* front;
Node* back;
};
int main() {
LinkedList ll;
char input;
char const *menu = {"Options:\n\n" \
"0. Quit\n" \
"1. Print linked-list\n" \
"2. pushBack -- add to the end of the LinkedList\n"};
while (input != '0') {
std::cout << menu << std::endl;
std::cout << ":";
std::cin >> input;
if (input == '1') {
ll.print();
}
else if (input == '2') {
std::cout << "Value: ";
static int init;
std::cin >> init;
static Node x(&init);
ll.pushBack(&x);
}
}
return 0;
}
Below is the input that I used. I printed some values to try to debug the program. You'll notice, I just tried putting the nodes with values 1, 2, 3 and 4 into the list
Options:
0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList
:2
Value: 1
Front: 1
Back: 1
Node Prev: 0
Node Next: 0
Options:
0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList
:2
Value: 2
Front: 2
Back: 2
Node Prev: 0x602300
Node Next: 0x602300
Options:
0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList
:2
Value: 3
Front: 3
Back: 3
Node Prev: 0x602300
Node Next: 0x602300
Options:
0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList
:2
Value: 4
Front: 4
Back: 4
Node Prev: 0x602300
Node Next: 0x602300
Options:
0. Quit
1. Print linked-list
2. pushBack -- add to the end of the LinkedList
:0
There are lots of good tips here, but none so far will solve the fundamental problem: you need to allocate the Node instances on the heap instead of the stack.
To make this easier, I'm going to suggest you store the ints by value instead of a pointer. Change all the places you use int* to just plain 'int'.
Then change the code to push a node on the back to this:
else if (input == '2') {
std::cout << "Value: ";
int init;
std::cin >> init;
Node *x = new Node(init);
ll.pushBack(x);
}
I've tested this with your code and it worked for me.
When you do something like this:
else if (input == '2') {
std::cout << "Value: ";
int init;
std::cin >> init;
Node x(init);
ll.pushBack(&x);
}
You're allocating a Node on the stack, which means as soon as you exit the "else" block the Node 'x' is destroyed and the pointer you added to your list is no longer valid. You need to allocate Node on the heap with the new operator. That will keep the Node alive and in memory until you delete it later.
Speaking of delete -- once you get this part working, you'll want to write a destructor that iterates over all the nodes in your list and deletes them. But for now, I'd focus on getting your other operations correct.
As you are using a static variable in below code all your node will have first value you entered.
static int init;
std::cin >> init;
static Node x(&init);
Correct it like below and try again
int *init = new int;
std::cin >> *init;
Node *x = New Node(init);
Your pushBack method look good for me. Just make above change and try.
may i know why if i'll get something like address from the output.
Can anyone tell me how to make it output as a value?
I'm new to pointer and going to do linked list.
struct node{
int x;
node *next;
};
int main(){
node *root;
root = new node;
root->next = 0;
root->x = 5;
cout << root << endl;
return 0;
}
Well if you really wanted to, you could overload operator<< to output the value of the node class/struct, I'm currently not near a compiler but I assume it would go something as so:
inline std::ostream& operator<< (std::ostream& os, const node* myNode)
{
os << myNode->x;
return os;
}
//Usage:
std::cout << root << std::endl;
Though if you just want to get the value in the simplest way possible, you could always just use
operator-> as shown below:
std::cout << root->x << std::endl;
Same as you assigned value to x
cout << root->x << endl;
you can also access value of x as:
cout<<(*root).x<<endl;
I am having troubles with my code. the calling linkedlist does not seem to get "updated" with the values or they are not saved or something. Could use some help, Thanks.
template <class T>
void LinkedList<T>::insert_front(const T& x)
{
LinkedList* p = this;
LinkedList* tmp = new LinkedList(x,p);
p = tmp;
cout<<p->m_data<<endl;
cout<<tmp->m_data<<endl;
The calling function is
//TEST : Inserting 10 numbers to a
cout << endl << "TEST : Inserting 10 numbers to A" << endl;
for (int k=0; k<10; k++){
A.insert_front(k+1);
}
cout << A << endl;
cout << "Size of a = " << A.size() << endl;
I get an output of 1122334455667788991010
which is the tmp data value and the p data value each call
The values go to the code, and they are the right values, just when I go to print A nothing is shown just an empty list. Thanks, I'm new here but love the community.
Your design of the linked list and of the method are wrong.
In the method you defined local variable p and assigned to it tmp. After exiting the method this local variable will be destroyed. So nothing was occured with the list itself. Neither its data member was changed. Also there is a memory leak.
template <class T>
void LinkedList<T>::insert_front(const T& x)
{
LinkedList* p = this;
LinkedList* tmp = new LinkedList(x,p);
p = tmp;
cout<<p->m_data<<endl;
cout<<tmp->m_data<<endl;
You should split you class into two classes. The first one will define the node of the list and the second one will control operations withy the list and contain the head of the list as its data member.
for some reason my nodes don't seem to be deleting. it looks as though it traverses to the end ok but after the node is "deleted" it still has the data in it. i've also tried
free(bNode) and bNode = NULL instead of delete bNode but they all give the same result.
The cout and display functions were just put in when I was trying to debug. I just don't understand why its not working, i hope i'm not missing something simple.
struct
Book{
char title [50];
char url [75];
Book *left;
Book *right;
};
void deleteAllBooks (Book *bNode){
if(bNode==NULL) return;
if(bNode->left !=NULL){
cout << endl << "deleting left" << endl;
deleteAllBooks(bNode->left);
}
if(bNode->right !=NULL){
cout << endl << "deleting right" << endl;
deleteAllBooks(bNode->right);
}
cout << endl << "deleting node " << bNode->title << endl;
delete bNode;
displayBookTree(bNode);
}
void displayBookTree(Book *bNode){
if(bNode==NULL){
cout << "No books" << endl;
return;
}
if(bNode->left !=NULL){
displayBookTree(bNode->left);
}
if(bNode->right !=NULL){
displayBookTree(bNode->right);
}
cout <<"Title: " << bNode->title << endl;
cout <<"URL: " << bNode->url <<endl;
}
"Use 0. The "NULL" macro is not type-safe; if you feel that you must
use "null", make it a const int instead of the C-style "#define". Also
see "The C++ Programming Language" for Stroustrup's argument against
the usage of "NULL"."
I would try to change:
if (bNode==NULL) { ... }
with
if (!bNode) { ... }
And
if (bNode->left !=NULL) { ... }
if (bNode->right !=NULL) { ... }
with
if (bNode->left) { ... }
if (bNode->right) { ... }
And then take a look to this answer on how correctly delete a Struct!
Easiest solution:
struct Book{
std::string title;
std::string url;
std::unique_ptr<Book> left;
std::unique_ptr<Book> right;
};
void deleteAllBooks (std::unique_ptr<Book> bNode)
{
// No code necessary. Literally. But usually you wouldn't even
// bother with this function, the default Book::~Book is fine.
}
Your solution is correct, but your observations are wrong. When you delete an object, the destructor will be executed for that object. In your case, this destructor has no visible side effect, because all your data members are plain old data types that do not have a destructor on there own. Using an object after it was deleted, invokes undefined behavior and your observation is one possible incarnation of "undefined behavior".
Your test for != 0 before calling deleteAllBooks() is redundant:
void deleteAllBooks ( Book *node )
{
if( node )
{
deleteAllBooks( node->left );
deleteAllBooks( node->right );
delete node;
}
}
does the same, but might be easier to understand.
And don't mix free/alloc with new/delete. If you've allocated an object with new, you have to return it with delete. Otherwise, you will get undefined behavior.
I'm trying to create a doubly linked list where each list has a first node, last node, and num_elements. However, for some reason, when I try to test the code in a UseList.cpp file, I can't get the num_elements to set to zero as default.
Let me show you what I mean:
In List.h:
template <class L>
class List
{
private:
Node<L> *first;
Node<L> *last;
int num_elements;
public:
// constructors and destructors
List();
[...]
}
[...]
template <class L>
List<L>::List() {
first = NULL;
last = NULL;
num_elements = 0;
}
[...]
This is the show method lower down in list.h:
template <class L>
// Print out the data in each node separated by a space.
void List<L>::show() {
cout << num_elements << endl;
Node<L> *current_node = first;
while (current_node != NULL) {
cout << current_node->data << " ";
current_node = current_node->next;
}
cout << endl;
}
Note that there is a cout statement there to print the num_elements.
This is the relevant part of UseList.cpp:
int main (int argc, char *argv[]) {
cout << "-----------------------------------------" << endl;
cout << "----------------LIST ONE-----------------" << endl;
cout << "-----------------------------------------" << endl;
List<int> *list1;
srand(time(NULL));
list1->show();
[...]
When show is called, it prints out "1" and gives me a segmentation fault. Why is num_elements defaulting to "1" instead of "0"?
When I do a cout in List<L>::List() {, nothing is printed... (this implies that the constructor never runs?)
Thanks for the help!
You are declaring a pointer to a List<int> and not initializing it to anything.
You have created a pointer to a List<int> object, but no object. So, currently, your program will segmentation fault because the pointer is "dangling". When you try to dereference it with ->, you are accessing memory that isn't yours, and it fails. To fix this, simply allocate a new List object:
List<int> *list1 = new List<int>();
Don't forget to free it later:
delete list1;
Your other option is to just not use dynamic memory. You shouldn't use it if you don't have to.
List<int> list1;
list1.show()
List<int> *list1;
Declares list1 to be a pointer.
List<int> *list1 = new List<int>();
Would actually create an instance of List