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 5 years ago.
Improve this question
I know the segmentation fault is occurring in this while loop: (while(temp != NULL){temp = temp->next;}), but I have no idea why.
#include<iostream>
using namespace std;
class zDepthList {
typedef struct node {
int data;
node* next;
node* prev;
} Node;
public:
zDepthList() {
head = NULL;
}
zDepthList(int array[], int length) {
Node *temp, *ptr;
int i = 0;
while(i != length - 1) {
temp = head;
ptr = new Node;
ptr->data = array[i];
i++;
ptr->next = NULL;
if(head == NULL) {
head = ptr;
ptr->prev = NULL;
}
else {
while(temp != NULL) {
temp = temp->next;
}
}
temp->next = ptr;
ptr->prev = temp;
}
}
void out(const char order) {
cout << head->data << endl;
return;
}
private:
Node *head;
};
For starters you have to initialize the head to NULL.
And after this while loop
else {
while(temp != NULL) {
temp = temp->next;
}
}
temp->next = ptr;
ptr->prev = temp;
the pointer temp is equal to NULL because it is the condition to interrupt the loop. Thus this statement
temp->next = ptr;
results in undefined behavior.
If you have a double-linked list it is natural to introduce also data member tail that it could be easy to append new nodes.
So you should include
class zDepthList {
//...
private:
Node *head, *tail;
};
In this case the constructors can look the following way
zDepthList() : head( nullptr ), tail( nullptr )
{
}
zDepthList( const int a[], size_t n ) : head( nullptr ), tail( nullptr )
{
for ( size_t i = 0; i < n; i++ )
{
Node *tmp = new Node { a[i], nullptr, tail };
tail == nullptr ? head = tmp : tail->next = tmp;
tail = tmp;
}
}
Here is a demonstrative program
#include <iostream>
class zDepthList {
typedef struct node {
int data;
node* next;
node* prev;
} Node;
public:
zDepthList() : head(nullptr), tail(nullptr)
{
}
zDepthList(const int a[], size_t n) : head(nullptr), tail(nullptr)
{
for (size_t i = 0; i < n; i++)
{
Node *tmp = new Node{ a[i], nullptr, tail };
tail == nullptr ? head = tmp : tail->next = tmp;
tail = tmp;
}
}
std::ostream & out( std::ostream &os = std::cout ) const
{
for (Node *current = head; current; current = current->next)
{
os << current->data << ' ';
}
return os;
}
private:
Node *head, *tail;
};
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
zDepthList l(a, sizeof(a) / sizeof(*a));
l.out() << std::endl;
}
The program output is
0 1 2 3 4 5 6 7 8 9
You never set head but you access it. This means it is uninitialized and this is an UB.
You have 2 ctors and you initialize head only then, when it is called without any parameter.
Related
I am a beginner learning c++, and currently making a singly linked list. I have faced some problems and I thought for a very long time, searched a lot but still do not have an answer for this code so I am begging for some help..
So this is my linked.h
template <class T>
class Node {
public:
T data;
Node<T>* next;
};
template <class T>
class List {
private:
Node<T> *head;
public:
List() : head(NULL) {};
~List() {
Node<T>* ptr, tmp;
for(ptr = head->next; ptr == NULL; ptr = head->next) {
delete ptr;
}
}
List(T* arr, int n_nodes) {
head = NULL;
Node<T> *tmp = head;
for(int i = 0; i < n_nodes; i++) {
Node<T>* node = new Node<T>;
node->data = arr[i];
if(head == NULL) {
head->next = node;
tmp = node;
}
else {
tmp->next = node;
node->next = NULL;
tmp = node;
}
}
}
friend std::ostream& operator<<(std::ostream& out, List<T>& rhs) {
Node<T>* cur = rhs.head;
out << cur;
while(cur != NULL) {
if(cur->next != NULL) {
out << cur->data << ", ";
cur = cur->next;
}
else
out << cur->data << " ";
}
return out;
}
};
and this is my main.cc file.
#include <iostream>
#include "linked.h"
int main() {
int array[5] = {12, 7, 9, 21, 13};
List<int> li(array, 5);
std::cout << li;
return 0;
}
I keep on getting segmentation fault when running the constructor and I don't get why. Where am I making a mistake? Any help would be appreciated!
You could cover the issue with a pointer to pointer:
List(T* arr, int n_nodes)
{
Node<T>** tmp = &head; // tmp *pointing* to uninitialized(!) head pointer
for(int i = 0; i < n_nodes; i++)
{
Node<T>* node = new Node<T>();
node->data = arr[i];
// now the trick:
*tmp = node; // !!!
// you now have assigned the new node to whatever pointer
// the tmp pointer points to - which initially is - guess - head...
// but we now need to advance!
tmp = &node->next;
}
// tmp now points to latestly created node's next pointer
// (or still head, if no nodes where created because of n_nodes == 0)
// be aware that this one still is not initialized! so:
*tmp = nullptr;
}
Your destructor necessarily fails, too:
Node<T>* ptr, tmp;
for(ptr = head->next; ptr == NULL; ptr = head->next)
{
delete ptr; // you delete ptr, but advancing (ptr = head->next)
// is done AFTERWARDS, so you'd access already deleted memory
// undefined behaviour
}
Additionally, you don't delete the head node! And if head is nullptr, you again have undefined behaviour.
Try it this way:
while(head)
{
Node<T>* tmp = head; // need a copy of pointer
head = head->next; // need to advance BEFORE deleting
delete tmp; // now can delete safely
}
I am trying to write a code making a single linked list. I want to put all my array elements into each node and link them. But when I run my code I keep getting the segmentation fault error. I do not get why I am getting this error.
Can anybody help?? Thanks!!
linked_list_main.cc
#include <iostream>
#include "linked_list.h"
int main() {
int array[5];
List<int> list(array, 5);
std::cout << list;
return 0;
}
template <class T>
class Node {
public:
T data;
Node<T>* next;
};
This is my linked_list.h file.
class List {
private:
Node<T> *head;
public:
List() : head(NULL) {};
~List() {
Node<T>* ptr;
for(ptr = head; ptr == NULL; ptr = head->next)
delete ptr;
}
List(T* arr, int n_nodes){
Node<T>* tmp = head;
for(int i = 0; i < n_nodes; i++ ) {
Node<T>* node = new Node<T>;
node->data = arr[i];
if(tmp != NULL) {
node->next = tmp;
tmp = node;
}
}
}
friend std::ostream& operator<<(std::ostream& out, List<T>& rhs) {
Node<T>* cur = rhs.head;
while(cur != NULL) {
if(cur->next == NULL)
out << cur->data << " ";
else
out << cur->data << ", ";
cur = cur->next;
}
}
};
You need to change this
List(T* arr, int n_nodes){
Node<T>* tmp = head;
...
}
to this
List(T* arr, int n_nodes){
Node<T>* tmp = NULL;
...
head = tmp;
}
Pointers are tricky, learn to use a debugger. Will be the best hour you've ever spent when learning how to program.
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 5 years ago.
Improve this question
I'm just learning C++ right now, so I wanted to create a simple linked list program to learn how to write C++. (I come from Java and Python). Sometimes (not every time) I get an EXC_BAD_ACCESS error.
Here is my code:
#include <iostream>
#include <string>
using namespace std;
class LinkedList
{
struct Node
{
int value;
Node *next;
};
private:
Node *head;
public:
LinkedList()
{
head = NULL;
}
void addNode(int value, int index)
{
Node *node = new Node;
node->value = value;
Node *n = head;
if (index == 0)
{
node->next = n;
head = node;
return;
}
int size = getSize();
for (int i = 0; i < size - 1; i++)
{
if (i == index - 1)
{
node->next = n->next;
n->next = node;
}
n = n->next;
}
}
void addNode(int value)
{
Node *node = new Node;
node->value = value;
if (!head)
{
node->next = NULL;
head = node;
return;
}
Node *n = head;
int size = getSize();
for (int i = 0; i < size - 1; i++)
{
n = n->next;
}
n->next = node;
}
int getSize()
{
Node *_node = new Node;
_node->value = head->value;
_node->next = head->next;
int size = 1;
while (_node != NULL)
{
_node = _node->next;
size++;
}
return size - 1;
}
string printList()
{
Node *n = head;
string output = to_string(n->value);
int size = getSize();
for (int i = 0; i < size - 1; i++)
{
n = n->next;
output.append(" -> " + to_string(n->value));
}
return output;
}
};
I get this error in the method "getSize()" on the line "_node = _node->next;" I have no idea what's wrong.
Inside addNode you are not initializing the next pointer of Node to NULL when there is a head node.
You must initialize it to NULL.
I got a problem with my doubly linked list. How can i make the input unique ( i don`t want it to be repeated )
for example i can input 1 and then again 1 i will have a list of 1 and 1. I need to forbid this somehow :) so the list can contain only not repeating numbers.
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
node* prev;
};
class Node
{
public:
Node();
~Node();
void setKopa();
void printForward();
private:
node* head;
node* tail;
node* n;
};
Node::Node()
{
setKopa();
}
Node::~Node()
{
delete n;
}
void Node::setKopa()
{
int lenght;
do
{
cout << "Input list lenght (how many elements): ";
cin >> lenght;
if(lenght<2)
cout << "Error list has to have atleast 2 elements!" <<endl;
}
while(lenght<2);
int fill;
cout << "Input "<< lenght <<" elements: "<<endl;
for (int i=0; i<lenght; i++)
{
cin>>fill;
n = new node;
n->data = fill;
if (i==0)
{
n->prev = NULL;
head = n;
tail = n;
}
else if (i+1==lenght)
{
n->prev = tail;
tail->next = n;
tail = n;
tail->next = NULL;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
}
void Node::printForward()
{
node* temp = head;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp-> next;
}
cout << endl;
}
int main()
{
Node a;
a.printForward();
system("pause");
return 0;
}
When you read input, go through the list to see if the input is already there.
With that (simple) answer out of the way, I would like to address some other things regarding your code. The first is that you have a memory leak in that you never delete the list. The second is that you don't need the class member variable n, it might as well be a local variable inside the setKopa loop.
Your way of adding new nodes is also, well, weird. It should, in my opinion, be more general instead of using the loop counter to check what to do. What I suggest is that you make a member function to add new nodes, taking the integer data as argument. This way you can call this function to add nodes anywhere, and not just in the setKopa function. In fact, I think the list should not handle that input at all, instead it should be a free-standing function called from main and which calls the addNode function.
Also the node structure doesn't need to be in the global namespace, it could be a private structure in the Node class. And speaking of the Node class, shouldn't it really be called List instead?
So if I may suggest, you might want to do something like this:
#include <iostream>
class List
{
public:
List()
: head(nullptr), tail(nullptr)
{}
~List();
void addNode(const int data);
void printAll() const;
private:
struct node
{
node()
: next(nullptr), prev(nullptr)
{}
node* next;
node* prev;
int data;
};
node* head;
node* tail;
};
List::~List()
{
for (node* next, *cur = head; cur; cur = next)
{
next = cur->next;
delete cur;
}
}
void List::addNode(const int data)
{
node* n = new node;
n->data = data;
if (tail == nullptr)
{
// First node in list
head = tail = n;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
void List::printAll() const
{
std::cout << "{ ";
for (node* cur = head; cur != nullptr; cur = cur->next)
std::cout << cur->data << ' ';
std::cout << "}\n";
}
int main()
{
List list;
for (int i = 0; i < 10; ++i)
list.addNode(i);
list.printAll();
}
The above code should print
{ 0 1 2 3 4 5 6 7 8 9 }
Replace the node-adding loop with your own.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I implement a queue myself. when testing, I expect the dequeue to reutrn when the queue is empty by testing if the tail pointer point to the head node. However, the address of the head node and the one pointer point are different when the point indeed points to the head, hence the queue never stop dequeue even if there is nothing in it.
This confuse me a lot. Any suggestion on this?
thanks a lot.
//header
#ifndef QUEUE_H
#define QUEUE_H
struct node
{
int val;
struct node* next;
};
class queue
{
private:
node head;
node* tail;
public:
queue();
void enqueue(int val);
void dequeue(int& holder, bool& v);
};
#endif
// queue.cpp
#include "queue.h"
using namespace std;
queue::queue()
{
tail = &head;
}
void queue::enqueue(int val)
{
node* tmp = new node;
tmp->val = val;
if(tail == &head)
{
tail = tmp;
tmp->next = &head;
head.next = tmp;
}
else
{
node* holder = head.next;
head.next = tmp;
tmp->next = &head;
holder->next = tmp;
}
}
void queue::dequeue(int& holder,bool& v)
{
if(tail == &head)
{
v = false;
}
else
{
node* cur = tail;
tail = tail->next;
holder = cur->val;
v = true;
delete cur;
}
}
//test.cpp
#include <iostream>
#include "queue.h"
using std::cout;
using std::endl;
int main()
{
int ary[] = {1,2,3,4,5};
queue myq;
for(int i = 0;i< sizeof(ary);i++)
{
myq.enqueue(ary[i]);
}
int tmp;
bool flag;
for(int i = 0;i<=7;i++)
{
myq.dequeue(tmp,flag);
if(flag)
cout<<"number is "<<tmp<<endl;
else
cout<<"queue empty"<<endl;
}
return 0 ;
}
I could give you the exact fix, but that would teach you absolutely nothing, you'd just copy and paste that into your code and go away do something else. So I'm going to help you with a line of code to add to show what the current value of &head is, and thus help identify what the actual problem is...
Add this line to enqueue (at the top of the function) and dequeue:
std::cout << __FUNCTION__ << ": " << &head << std::endl;
It will print the name of the function and the address off head. (You may need to include iostream as well)
Pay particular attention to how many printouts you get!
Working code below: (Learn to use a debugger)
#include <iostream>
using namespace std;
//header
#ifndef QUEUE_H
#define QUEUE_H
struct node {
int val;
struct node* next;
};
class queue {
private:
struct node* head;
struct node* tail;
public:
queue();
void enqueue(int val);
void dequeue(int& holder, bool& v);
};
#endif
using namespace std;
queue::queue() {
tail = NULL;
head = NULL;
}
void queue::enqueue(int val) {
node* tmp = new node;
tmp->val = val;
if (head == NULL && NULL == tail) {//No nodes Empty
head = tail = tmp;
tmp->next = NULL;
}else if (tail == head) { //Single node
tail = tmp;
tmp->next = head;
head->next = tmp;
} else {
tail->next = tmp;
tmp->next = head;
tail = tmp;
}
}
void queue::dequeue(int& holder, bool& v) {
if (NULL == tail || NULL == head) {
v = false;
return;
} else if (tail == head) {// single node
holder = head->val;
delete head;
head = NULL;
tail = NULL;
v = true;
} else { //more than one node
//Go to the last but one node and chop the tail
node* cur = head;
while (cur->next != tail)
cur = cur->next;
cur->next = head;
holder = tail->val;
delete tail;
tail = cur;
v = true;
}
return;
}
using std::cout;
using std::endl;
int main() {
int ary[] = { 1, 2, 3, 4, 5 };
queue myq;
for (int i = 0; i < 5; i++) {
myq.enqueue(ary[i]);
}
int tmp;
bool flag;
for (int i = 0; i <= 7; i++) {
myq.dequeue(tmp, flag);
if (flag) {
cout << "number is " << tmp << endl;
}
else {
cout << "queue empty" << endl;
}
}
return 0;
}