User input linked list - c++

I'm trying to get user input to insert element in the linked list. It works if I try to add at 1st or 2nd position. Even though list has more than 3 element, if I put 3 in it, it never works and returns nothing showing no syntax error. Is it wrong use with variable or loop. I'm super confused.
#include<stdlib.h>
#include<stdio.h>
struct Node
{
int data;
Node *next;
};
Node *head;
void insert(int data, int n)
{
Node* temp1 = new Node;
temp1->data = data;
temp1->next = NULL;
if(n == 1)
{
temp1->next = head;
head = temp1;
return;
}
else{
Node *temp2 = head;
for(int i = 0; i = n - 2; i++)
{
temp2 = temp2->next;
}
temp1->next = temp2->next;
temp2->next = temp1;
return;
}
}
void print()
{
Node *temp = head;
while(temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
int main()
{
head = NULL;
insert(3, 1);
insert(33, 1);
insert(384, 2);
insert(384, 1);
insert(432, 3);
insert(34, 4);
print();
}

The obvious mistakes have been already elaborated in the comment. Something additional.
If this is intended to be C++, then you should also use C++ language, especially classes.
Then from your design. Please do not mix up the "Node" with the "Linked List". A node is a part of a linked list. It is contained within the linked list. And it should not be exposed to the outside world.
I you want to read a little bit about needed functionality of a linked list, then you may check the CPP reference. For example here
And an example, from which you can take more ideas is listed below.
But first you need to read a book, this thing made out of real paper :-)
#include <iostream>
#include <iterator>
#include <initializer_list>
#include <algorithm>
// Very simple implementation of a forward list
template <class T>
class SinglyLinkedList {
// The node
struct Node {
T data{}; // Data. Would normally be a templated argument
Node* next{}; // And the pointer to the next node
Node(const T& i, Node* n = nullptr) : data(i), next(n) {}; // Simple constructor to set a value and next pointer
};
Node* head{}; // This is the start of the list
// It would be advisable to have a tail pointer. We use the more inefficient approach here
Node* getLast() const { Node* n{ head }; while (n and n->next) n = n->next; return n; }
public:
// Constructor / Destructor --------------------------------------------------------------------------------------------------------
~SinglyLinkedList() { clear(); }
// Default constuctor
SinglyLinkedList() {} // Default
// From an initialization list
SinglyLinkedList(const std::initializer_list<T>& il) { clear(); for (const T& i : il) push_back(i); } // From initializer list
// Copy constructor
SinglyLinkedList(const SinglyLinkedList& other) { clear(); for (const T& i : other) push_back(i); }
// Move constructor. Will steal the elements from the other
SinglyLinkedList(SinglyLinkedList&& other) noexcept { head = other.head; other.head = nullptr; }
// Assignment operator
SinglyLinkedList& operator = (const SinglyLinkedList& other) { clear(); for (const T& i : other) push_back(i); }
// Move assignment operator
SinglyLinkedList& operator = (SinglyLinkedList&& other) { head = other.head; other.head = nullptr; }
// Housekeeping --------------------------------------------------------------------------------------------------------------
void clear() { Node* tmp{ head }; while (tmp) { Node* toDelete{ tmp }; tmp = tmp->next; delete toDelete; } head = nullptr; }
int empty() const { return head == nullptr; }
int size() const { int k{}; Node* n{ head }; while (n) { ++k; n = n->next; } return k; }
// Modify content --------------------------------------------------------------------------------------------------------------
void push_front(const T& i) { Node* n = new Node(i); n->next = head; head = n; };
void push_back(const T& i) { Node* n = new Node(i); Node* l = getLast(); if (l) l->next = n; else head = n; }
void pop_front() { if (head) { Node* tmp = head->next; delete head; head = tmp; } }
void pop_back() { // This is a little bit more difficult in a singly linked list
if (head) {
Node* n{ head }, * previous{};
while (n and n->next) {
previous = n;
n = n->next;
}
delete n;
if (previous)
previous->next = nullptr;
else
head->next = nullptr;
}
}
// Access elements --------------------------------------------------------------------------------
T& front() const { return head ? head->data : 0; };
T back() const { Node* n = getLast(); return n ? n->data : 0; }
// Add iterator properties to class ---------------------------------------------------------------
struct iterator { // Local class for iterator
Node* iter{}; // Iterator is basically a pointer to the node
// Define alias names necessary for the iterator functionality
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
// Constructor
iterator() {}
iterator(Node* n) : iter(n) {}
// Dereferencing
reference operator *() const { return iter->data; }
pointer operator ->() const { return &iter->data; }
// Aithmetic operations
iterator& operator ++() { if (iter) iter = iter->next; return *this; }
iterator operator ++(int) { iterator temp{ *this }; ++* this; return temp; }
iterator operator +(const difference_type& n) const { iterator temp{ *this }; difference_type k{ n }; while (k--)++temp; return temp; }
iterator& operator +=(const difference_type& n) { difference_type k{ n }; while (k--)++* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return iter < other.iter; }
bool operator > (const iterator& other) const { return iter > other.iter; }
bool operator <= (const iterator& other) const { return iter <= other.iter; }
bool operator >= (const iterator& other) const { return iter >= other.iter; }
// Difference. Also complicated, because no random access
difference_type operator-(const iterator& other) const {
difference_type result{};
Node* n{ iter };
while (n and n != other.iter) {
++result;
n = n->next;
}
return result;
}
};
// Begin and end function to initialize an iterator
iterator begin() const { return iterator(head); }
iterator end() const { return iterator(); }
// Functions typcical for forward lists ----------------------------------------------------------------------
// Easy, becuase we can operate form the current iterator and do not need the "previous" element
iterator insertAfter(iterator& pos, const T& i) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* n = new Node(i, pos.iter->next);
pos.iter->next = n;
result = n;
}
return result;
}
iterator eraseAfter(iterator& pos) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* tmp = pos.iter->next->next;
delete pos.iter->next;
pos.iter->next = tmp;
result = pos.iter->next;
}
return result;
}
};
// Test/Driver Code
int main() {
// Example for initilizer list
SinglyLinkedList<int> sllbase{ 5,6,7,8,9,10,11,12,13,14,15 };
// Show move constructor
SinglyLinkedList<int> sll(std::move(sllbase));
// Add some values in the front
sll.push_front(4);
sll.push_front(3);
sll.push_front(2);
sll.push_front(1);
// Delete 1st element (Number 1)
sll.pop_front();
// Delete last element
sll.pop_back();
// Use a std::algorithm on our custom linked list. Works because we have an interator
SinglyLinkedList<int>::iterator iter = std::find(sll.begin(), sll.end(), 8);
// Now add an element after 8
iter = sll.insertAfter(iter, 88);
// End delete the 9
iter = sll.eraseAfter(iter);
// Use range based for loop. Works because, we have iterators
for (int i : sll)
std::cout << i << ' ';
return 0;
}

Your mistake is in this for loop
for(int i = 0; i = n - 2; i++)
There is assignment operator(=) instead of equal to operator(==), also logic is wrong.
This is how it should be
#include<cstdlib>
#include<cstdio>
struct Node
{
int data;
Node *next;
};
Node *head;
void insert(int data, int n)
{
Node* temp1 = new Node;
temp1->data = data;
temp1->next = NULL;
if(n == 1)
{
temp1->next = head;
head = temp1;
return;
}
else{
Node *temp2 = head;
for(int i = 1; i < n - 1; i++)
{
temp2 = temp2->next;
}
temp1->next = temp2->next;
temp2->next = temp1;
return;
}
}
void print()
{
Node *temp = head;
while(temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
int main()
{
head = nullptr;
insert(3, 1);
insert(33, 1);
insert(384, 2);
insert(384, 1);
insert(432, 3);
insert(34, 4);
print();
}

Related

Finding all permutations of given string and storing them in linked list

I am new to C++ and am trying to learn the syntax better. I have created a function that finds all possible permutations of a given string and stores them in a linked list. The linked list is returned at the end of the function. So far what I have goes to the point where the length of the word is 1 then seg faults. I believe it is seg faulting before it enters the if conditional but I am unsure why.
Note: I am trying to do this function iteratively, I realize recursively would be much easier.
List :: List()
{
head = NULL;
}
Node :: Node()
{
word = "";
next = NULL;
}
List allAnagrams(string input_str)
{
int length = input_str.length();
List *list = new List();
Node *new_head = new Node;
new_head->word = input_str;
list->head = new_head;
Node *curr = new Node;
curr = new_head;
std::sort(input_str.begin(), input_str.end());
if (length == 0) {
return *list;
}
do {
cout << "\n" + input_str;
curr = curr->next;
curr->word = input_str;
}
while(std::next_permutation(input_str.begin(), input_str.end()));
return *list;
}
In my opinion, your solution is by far too complicated.
For example: Do not create a new list in your function and return the derefenced value. This will lead to problems.
Then I do not understand your whole logic for adding new nodes to a list.
In the below example, I show you 2 different but a very simple solutions, to add the next new word always to the front of the list (which will give you a somehow reversed list), and the standard implementation by adding new nodes at the end of the list. Here a special handling for the empty list is neeeded.
Additionally, if you allocate memory with new, you must release it with delete.
But in this case the recommendation would be to use either smart pointers or even better, use a std::list in the first place.
Anyway, please see the below
#include <iostream>
#include <string>
#include <algorithm>
// A rudimentary node for demo purposes
struct Node {
std::string word{};
Node *next{};
};
// A rudimentary list for demo purposes
struct List{
Node* head{};
};
// Create all anagrams and add to front of list
List allAnagrams1(std::string& str) {
// Define the list, which we will return
List list{};
// If the input string is empty, we will do nothing
if (not str.empty()) {
// Necessary for calculating the permutation
std::sort(str.begin(),str.end());
// Do for all permutations of the word
do{
// Create a new node for the next permutation
Node *nextWord = new Node{str,list.head};
// Replace head by this
list.head = nextWord;
} while(std::next_permutation(str.begin(), str.end()));
}
return list;
}
// Create all anagrams and add to end of list
List allAnagrams2(std::string& str) {
// Define the list, which we will return
List list{};
// If the input string is empty, we will do nothing
if (not str.empty()) {
// Necessary for calculating the permutation
std::sort(str.begin(),str.end());
// Do for all permutations of the word
do{
// Create a new node for the next permutation
Node *nextWord = new Node{str,nullptr};
// If the list is empty
if (list.head == nullptr) {
// EMpty list. The just vreated node will be the new head
list.head = nextWord;
}
else {
// List was not empty, find last element of list
Node* iter = list.head;
while (iter and iter->next)
iter = iter->next;
// Last element found. Add new node
iter->next = nextWord;
}
} while(std::next_permutation(str.begin(), str.end()));
}
return list;
}
int main()
{
// Test string
std::string s{"Hello"};
// Get all permutations
List list = allAnagrams2(s) ;
// Now show all elements in the list
Node *node = list.head;
while (node) {
std::cout << node->word << '\n';
node = node->next;
}
// Release memory
node = list.head;
while (node) {
// Store the next node pointer into a temporary
Node *temp = node->next;
// Release memory and delete the node
delete node;
// Set the node* to next
node = temp;
}
}
.
.
.
.
And as a bonus, please see an example of a Singly Linked List
#include <iterator>
#include <algorithm>
#include <iostream>
#include <initializer_list>
// Very simple implementation of a forward list
template <class T>
class SinglyLinkedList {
// The node
struct Node {
T data{}; // Data. Would normally be a templated argument
Node* next{}; // And the pointer to the next node
Node(const T& i, Node* n = nullptr) : data(i), next(n) {}; // Simple constructor to set a value and next pointer
};
Node* head{}; // This is the start of the list
// It would be advisable to have a tail pointer. We use the more inefficient approach here
Node* getLast() const { Node* n{ head }; while (n and n->next) n = n->next; return n; }
public:
// Constructor / Destructor --------------------------------------------------------------------------------------------------------
~SinglyLinkedList() { clear(); }
// Default constuctor
SinglyLinkedList() {} // Default
// From an initialization list
SinglyLinkedList(const std::initializer_list<T>& il) { clear(); for (const T& i : il) push_back(i); } // From initializer list
// Copy constructor
SinglyLinkedList(const SinglyLinkedList& other) { clear(); for (const T& i : other) push_back(i); }
// Move constructor. Will steal the elements from the other
SinglyLinkedList(SinglyLinkedList&& other) noexcept { head = other.head; other.head = nullptr; }
// Assignment operator
SinglyLinkedList& operator = (const SinglyLinkedList& other) { clear(); for (const T& i : other) push_back(i); }
// Move assignment operator
SinglyLinkedList& operator = (SinglyLinkedList&& other) { head = other.head; other.head = nullptr; }
// Housekeeping --------------------------------------------------------------------------------------------------------------
void clear() { Node* tmp{ head }; while (tmp) { Node* toDelete{ tmp }; tmp = tmp->next; delete toDelete; } head = nullptr; }
int empty() const { return head == nullptr; }
int size() const { int k{}; Node* n{ head }; while (n) { ++k; n = n->next; } return k; }
// Modify content --------------------------------------------------------------------------------------------------------------
void push_back(const T& i) { Node* n = new Node(i); Node* l = getLast(); if (l) l->next = n; else head = n; }
void push_front(const T& i) { Node* n = new Node(i); n->next = head; head = n; };
void pop_back() { // This is a little bit more difficult in a singly linked list
if (head) {
Node* n{ head }, * previous{};
while (n and n->next) {
previous = n;
n = n->next;
}
delete n;
if (previous)
previous->next = nullptr;
else
head->next = nullptr;
}
}
void pop_front() { if (head) { Node* tmp = head->next; delete head; head = tmp; } }
// Access elements --------------------------------------------------------------------------------
T back() const { Node* n = getLast(); return n ? n->data : 0; }
T front() const { return head ? head->data : 0; };
// Add iterator properties to class ---------------------------------------------------------------
struct iterator { // Local class for iterator
Node* iter{}; // Iterator is basically a pointer to the node
Node* head{};
// Define alias names necessary for the iterator functionality
using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
// Constructor
iterator() {}
iterator(Node* n, Node* h) : iter(n), head(h) {}
// Dereferencing
reference operator *() const { return iter->data; }
pointer operator ->() const { return &iter->data; }
// Aithmetic operations
iterator& operator ++() { if (iter) iter = iter->next; return *this; }
iterator& operator --() { Node* tmp = head; while (tmp and tmp->next != this->iter) tmp = tmp->next; iter = tmp; return *this; }
iterator operator ++(int) { iterator temp{ *this }; ++* this; return temp; }
iterator operator --(int) { iterator temp{ *this }; --* this; return temp; }
iterator operator +(const difference_type& n) const {
iterator temp{ *this }; difference_type k{ n }; if (k > 0) while (k--)++temp; else while (k++)--temp; return temp; }
iterator operator +=(const difference_type& n) {
difference_type k{ n }; if (k > 0) while (k--)++* this; else while (k++)--* this; return *this; };
iterator operator -(const difference_type& n) const {
iterator temp{ *this }; difference_type k{ n }; if (k > 0) while (k--)--temp; else while (k++)++temp; return temp; }
iterator operator -=(const difference_type& n) {
difference_type k{ n }; if (k > 0) while (k--)--* this; else while (k++)++* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return iter < other.iter; }
bool operator <= (const iterator& other) const { return iter <= other.iter; }
bool operator > (const iterator& other) const { return iter > other.iter; }
bool operator >= (const iterator& other) const { return iter >= other.iter; }
// Difference. Also complicated, because no random access
difference_type operator-(const iterator& other) const {
difference_type result{};
Node* n{ iter };
while (n and n != other.iter) {
++result;
n = n->next;
}
return result;
}
};
// Begin and end function to initialize an iterator
iterator begin() const { return iterator(head, head); }
iterator end() const { return iterator(nullptr, head); }
// Functions typcical for forward lists ----------------------------------------------------------------------
// Easy, becuase we can operate form the current iterator and do not need the "previous" element
iterator insertAfter(iterator& pos, const T& i) {
iterator result(nullptr, head);
if (pos.iter and pos.iter->next) {
Node* n = new Node(i, pos.iter->next);
pos.iter->next = n;
result.iter = n;
}
return result;
}
iterator eraseAfter(iterator& pos) {
iterator result(nullptr, head);
if (pos.iter and pos.iter->next) {
Node* tmp = pos.iter->next->next;

Adding node in linked list to first pos in c++

I'm trying to make linked list and it already workes with one exception - adding new node to first position.
My node:
struct MyNode
{
string s;
int i;
MyNode* pointer;
}
Linked list:
private:
MyNode first;
int count;
public:
//methods
I had two ideas how to add new node to first position but none of them worked.
The first one:
void Add(Node* node, int index)
{
if (index == 1)
{
node->pointer = &first;
first = *node;
}
}
The node pointer points to itself and all other nodes are lost.
The second idea:
void Add(Node* node, int index)
{
if (index == 1)
{
Node n2 = first;
first = *node;
first.pointer = &n2;
}
}
which works fine at first but as soon as the program leaves the if, the node that was supposed to be second loses its string data (integer not for some reason).
Is it possible to write method to add node to first position without having to remake the structure of my list (it would break all other methods I wrote)?
Edit: Minimal reproducable example:
#include <string>
using namespace std;
struct Person
{
string forename{};
string surname{};
int age{};
Person* pointer{};
};
class linked_list
{
private:
Person first;
int count = 0;
Person* GetPointer(int index)
{
Person* current = &first;
Person* next = first.pointer;
if (index == 1) return &first;
for (int i = 1; (i < index) && (next->pointer != NULL); i++)
{
current = next;
next = next->pointer;
}
return current;
}
public:
linked_list()
{
first.forename = "dummy";
first.surname = "dummy";
first.age = 0;
}
void Add(Person* p, int index)
{
if ((index < 1) || (index > count + 1))
{
throw 0;
}
else if (index == 1)
{
Person p2 = first;
first = *p;
first.pointer = &p2;
/*p->pointer = &first;
first = *p;*/
}
else if (index == count + 1)
{
p->pointer = NULL;
Person* p2 = GetPointer(index);
p2->pointer->pointer = p;
}
else
{
p->pointer = GetPointer(index);
Person* p2 = GetPointer(index - 1);
p2->pointer = p;
}
count++;
}
};
int main()
{
linked_list l;
Person p;
p.age = 35;
p.forename = "John";
p.surname = "Smith";
l.Add(&p, 1);
}
There are some things that need to be done.
All variables must be initiliazed. That is utmost important. You can do this also dirctely in the class definition. Example:
struct MyNode {
string s{};
int i{};
MyNode* pointer{};
};
The uniform value initialization with {} is availabe since 10 years. It will initilize the string to an empty string, "i" to 0 and "pointer" to nullptr.
In the context of a singly linked list often the variable name "next" is used instead of pointer.
Then, what you did correctly, Nodes are parts of a linked list. In object oriented terms you would say a linked list "has a" node. We call it a "has a"-relation.
But also here, you would use a different name.
"MyNode first;" would become "MyNode *head;" because, the signly linked list only needs a pointer to the first node in the list.
If you want to add values to a linked list, then you would create dynamically a new node, assign the value to the node and then add the node to the linked list.
We need to differentiate between adding the first node or adding a node to a list that already contains other nodes.
And empty linked list is easy to identify. The "head" pointer will be a nullptr and then you can simply assign the new node's pointer to "head".
In case that there are already element in the singly linked list, then you must find the last element in the chain of nodes, by starting at head and then following all "next" pointer until this is "nullptr". Then you add the new node to this next pointer.
In order for you to get a better understanding, you may study the attached code (maybe a little bit advanced, but anyway):
#include <iterator>
#include <algorithm>
#include <iostream>
#include <initializer_list>
// Very simple implementation of a forward list
template <class T>
class SinglyLinkedList {
// The node
struct Node {
T data{}; // Data. Would normally be a templated argument
Node* next{}; // And the pointer to the next node
Node(const T& i, Node* n = nullptr) : data(i), next(n) {}; // Simple constructor to set a value and next pointer
};
Node* head{}; // This is the start of the list
// It would be advisable to have a tail pointer. We use the more inefficient approach here
Node* getLast() const { Node* n{ head }; while (n and n->next) n = n->next; return n; }
public:
// Constructor / Destructor --------------------------------------------------------------------------------------------------------
~SinglyLinkedList() { clear(); }
// Default constuctor
SinglyLinkedList() {} // Default
// From an initialization list
SinglyLinkedList(const std::initializer_list<T>& il) { clear(); for (const T& i : il) push_back(i); } // From initializer list
// Copy constructor
SinglyLinkedList(const SinglyLinkedList& other) { clear(); for (const T& i : other) push_back(i); }
// Move constructor. Will steal the elements from the other
SinglyLinkedList(SinglyLinkedList&& other) noexcept { head = other.head; other.head = nullptr; }
// Assignment operator
SinglyLinkedList& operator = (const SinglyLinkedList& other) { clear(); for (const T& i : other) push_back(i); }
// Move assignment operator
SinglyLinkedList& operator = (SinglyLinkedList&& other) { head = other.head; other.head = nullptr; }
// Housekeeping --------------------------------------------------------------------------------------------------------------
void clear() { Node* tmp{ head }; while (tmp) { Node* toDelete{ tmp }; tmp = tmp->next; delete toDelete; } head = nullptr; }
int empty() const { return head == nullptr; }
int size() const { int k{}; Node* n{ head }; while (n) { ++k; n = n->next; } return k; }
// Modify content --------------------------------------------------------------------------------------------------------------
void push_back(const T& i) { Node* n = new Node(i); Node* l = getLast(); if (l) l->next = n; else head = n; }
void push_front(const T& i) { Node* n = new Node(i); n->next = head; head = n; };
void pop_back() { // This is a little bit more difficult in a singly linked list
if (head) {
Node* n{ head }, * previous{};
while (n and n->next) {
previous = n;
n = n->next;
}
delete n;
if (previous)
previous->next = nullptr;
else
head->next = nullptr;
}
}
void pop_front() { if (head) { Node* tmp = head->next; delete head; head = tmp; } }
// Access elements --------------------------------------------------------------------------------
T back() const { Node* n = getLast(); return n ? n->data : 0; }
T front() const { return head ? head->data : 0; };
// Add iterator properties to class ---------------------------------------------------------------
struct iterator { // Local class for iterator
Node* iter{}; // Iterator is basically a pointer to the node
Node* head{};
// Define alias names necessary for the iterator functionality
using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
// Constructor
iterator() {}
iterator(Node* n, Node* h) : iter(n), head(h) {}
// Dereferencing
reference operator *() const { return iter->data; }
pointer operator ->() const { return &iter->data; }
// Aithmetic operations
iterator& operator ++() { if (iter) iter = iter->next; return *this; }
iterator& operator --() { Node* tmp = head; while (tmp and tmp->next != this->iter) tmp = tmp->next; iter = tmp; return *this; }
iterator operator ++(int) { iterator temp{ *this }; ++* this; return temp; }
iterator operator --(int) { iterator temp{ *this }; --* this; return temp; }
iterator operator +(const difference_type& n) const {
iterator temp{ *this }; difference_type k{ n }; if (k > 0) while (k--)++temp; else while (k++)--temp; return temp; }
iterator operator +=(const difference_type& n) {
difference_type k{ n }; if (k > 0) while (k--)++* this; else while (k++)--* this; return *this; };
iterator operator -(const difference_type& n) const {
iterator temp{ *this }; difference_type k{ n }; if (k > 0) while (k--)--temp; else while (k++)++temp; return temp; }
iterator operator -=(const difference_type& n) {
difference_type k{ n }; if (k > 0) while (k--)--* this; else while (k++)++* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return iter < other.iter; }
bool operator <= (const iterator& other) const { return iter <= other.iter; }
bool operator > (const iterator& other) const { return iter > other.iter; }
bool operator >= (const iterator& other) const { return iter >= other.iter; }
// Difference. Also complicated, because no random access
difference_type operator-(const iterator& other) const {
difference_type result{};
Node* n{ iter };
while (n and n != other.iter) {
++result;
n = n->next;
}
return result;
}
};
// Begin and end function to initialize an iterator
iterator begin() const { return iterator(head, head); }
iterator end() const { return iterator(nullptr, head); }
// Functions typcical for forward lists ----------------------------------------------------------------------
// Easy, becuase we can operate form the current iterator and do not need the "previous" element
iterator insertAfter(iterator& pos, const T& i) {
iterator result(nullptr, head);
if (pos.iter and pos.iter->next) {
Node* n = new Node(i, pos.iter->next);
pos.iter->next = n;
result.iter = n;
}
return result;
}
iterator eraseAfter(iterator& pos) {
iterator result(nullptr, head);
if (pos.iter and pos.iter->next) {
Node* tmp = pos.iter->next->next;
delete pos.iter->next;
pos.iter->next = tmp;
result.iter = pos.iter->next;
}
return result;
}
};
// Test/Driver Code
int main() {
// Example for initilizer list
SinglyLinkedList<int> sllbase{ 5,6,7,8,9,10,11,12,13,14,15 };
// Show move constructor
SinglyLinkedList<int> sll(std::move(sllbase));
// Add some values in the front
sll.push_front(4);
sll.push_front(3);
sll.push_front(2);
sll.push_front(1);
// Delete 1st element (Number 1)
sll.pop_front();
// Delete last element
sll.pop_back();
// Use a std::algorithm on our custom linked list. Works because we have an interator
SinglyLinkedList<int>::iterator iter = std::find(sll.begin(), sll.end(), 8);
++iter;
--iter;
// Now add an element after 8
iter = sll.insertAfter(iter, 88);
// And delete the 9
iter = sll.eraseAfter(iter);
// Use range based for loop. Works because, we have iterators
for (int i : sll)
std::cout << i << ' ';
// Reverse Output
std::cout << "\n\n";
std::reverse_iterator<SinglyLinkedList<int>::iterator> riter = std::make_reverse_iterator(sll.end());
std::reverse_iterator<SinglyLinkedList<int>::iterator> riterEnd = std::make_reverse_iterator(sll.begin());
for (; riter != riterEnd; ++riter)
std::cout << *riter << ' ';
std::cout << "\n\n";
return 0;
}

can anyone help me with my linked list error please?

There is an issue with my code. I need to write a program that creates a linked list and performs insertion, deleting from the beginning, deleting from the end, and printing. Everything in the program works fine, but the delete the first node function. It throws an error in the printing function (posted a picture of the error below). Does anyone know what seems to be the problem? The function that deletes the last node works and prints perfectly.
LINKED LIST PROGRAM:
struct Node {
int data;
Node* next;
};
void insert(Node** head,int n) //insertion method
{
Node* newNode = new Node;
newNode->data = n;
newNode->next = (*head);
(*head) = newNode;
}
Node* deleteFront(struct Node* head)//deleting first node in the list
{
if (head == NULL)
return NULL;
else
{
Node* t = head;
head = head->next;
free(t);
t = NULL;
}
return head;
}
Node* deleteEnd(struct Node* head)//deleting last node in the list
{
if (head == NULL)
return NULL;
else if (head->next == NULL) {
free(head);
head = NULL;
}
else {
Node* prev = head;
Node* prev2 = head;
while (prev->next != NULL)
{
prev2 = prev;
prev = prev->next;
}
prev2->next = NULL;
free(prev);
prev = NULL;
}
return head;
}
void printLL(Node* h)
{
while (h != NULL)
{
cout << h->data << " ";
h = h->next;
}
cout << endl;
}
int main()
{
cout << "Linked list question 2: " << endl;
//linked list question 2
Node* n = NULL;
insert(&n, 60);
insert(&n, 40);
insert(&n, 20);
printLL(n);
deleteFront(n);
cout << "after deleting first node: ";
printLL(n);
deleteEnd(n);
cout << "after deleting last element: ";
printLL(n);
}
A picture of the error:
error
output
Take it easy. I read your code and there are no errors in logic. However, there are some mistakes in the selection of parameters. It is not necessary to use ** in the insert. Using * can meet the requirements, and use & to achieve assignment to the linked list. The same is true for deleteFront and deleteEnd. I modified your code and now the program can run normally, hope it helps.
#include<iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
void insert(Node*& head, int n) //insertion method
{
Node* newNode = new Node;
newNode->data = n;
newNode->next = head;
head = newNode;
}
Node* deleteFront(struct Node*& head)//deleting first node in the list
{
if (head == NULL)
return NULL;
else
{
Node* t = head;
head = head->next;
free(t);
t = NULL;
}
return head;
}
Node* deleteEnd(struct Node*& head)//deleting last node in the list
{
if (head == NULL)
return NULL;
else if (head->next == NULL) {
free(head);
head = NULL;
}
else {
Node* prev = head;
Node* prev2 = head;
while (prev->next != NULL)
{
prev2 = prev;
prev = prev->next;
}
prev2->next = NULL;
free(prev);
prev = NULL;
}
return head;
}
void printLL(Node* h)
{
while (h != NULL)
{
cout << h->data << " ";
h = h->next;
}
cout << endl;
}
int main()
{
cout << "Linked list question 2: " << endl;
//linked list question 2
Node* n = NULL;
insert(n, 60);
insert(n, 40);
insert(n, 20);
printLL(n);
deleteFront(n);
cout << "after deleting first node: ";
printLL(n);
deleteEnd(n);
cout << "after deleting last element: ";
printLL(n);
}
Since you're returning head in deleteFront(n) and deleteLast(n), however you're not updating head in main(). That's why its n is pointing to some garbage memory. Update your main() by storing head in n variable.
int main()
{
cout << "Linked list question 2: " << endl;
//linked list question 2
Node* n = NULL;
insert(&n, 60);
insert(&n, 40);
insert(&n, 20);
printLL(n);
n = deleteFront(n);
cout << "after deleting first node: ";
printLL(n);
n = deleteEnd(n);
cout << "after deleting last element: ";
printLL(n);
}
The bugs in your code have been mentioned in other answers and there were proposals to fix.
I would like to add an additional observation regarding your design of the Linked List. In standard implementations, Node is not visible to the outside world. The Node is not the LinkedList. The linked list contains Nodes. So, you would create a class List and it would contain the definition of a Node and a head pointer to the first node instance.
Then you would add all you functions as methods to the outer class List. These methods would work with the internal Node-chain. According to object oriented model you would encapsulate the interna of the methods and expose only what is needed to the outside world.
What you should also note is that your list is a forward list only. It has only one link to the next element. This makes some operations difficult, because you may need to always go from the beginning the list through the element what you what operate on. See your function delete_end. Here you even need to remember the previous element.
In double linked list, you could simply access also the previous element.
Therefore, if you check the CPP reference for a std::forward_list, you will find some maybe strange sounding functions like insert_after or erase_after or an iterator before_begin. This is all the result of having just forward references. A function like delete_last which would be pop_back in CPP language, is even not existing.
Therefore you maybe need to confirm, if you should implement a singly linked list or maybe a double linked list.
To make this more visible for you, I created some complete example code for a singly linked list for you.
Here I added also simple iterator functionality, which allows to use the class in a convenient way, e.g. with range based for loops or std::algorithms.
You may take this code to get some ideas for your own implementation.
#include <iostream>
#include <iterator>
#include <initializer_list>
#include <algorithm>
// Very simple implementation of a forward list
class SinglyLinkedList {
// The node
struct Node {
int data{}; // Data. Would normally be a templated argument
Node* next{}; // And the pointer to the next node
Node(int i, Node* n=nullptr) : data(i), next(n) {}; // Simple constructor to set a value and next pointer
};
Node* head{}; // This is the start of the list
// It would be advisable to have a tail pointer. We use the more inefficient approach here
Node* getLast() { Node* n{ head }; while (n and n->next) n = n->next; return n; }
public:
// Constructor / Destructor --------------------------------------------------------------------------------------------------------
~SinglyLinkedList() { clear(); }
// Default constuctor
SinglyLinkedList() {} // Default
// From an initialization list
SinglyLinkedList(const std::initializer_list<int>& il) { clear(); for (const int i : il) push_back(i); } // From initializer list
// Copy constructor
SinglyLinkedList(const SinglyLinkedList& other) { clear(); for (const int i : other) push_back(i); }
// Move constructor. Will steal the elements from the other
SinglyLinkedList(SinglyLinkedList&& other) noexcept { head = other.head; other.head = nullptr; }
// Assignment operator
SinglyLinkedList& operator = (const SinglyLinkedList& other) { clear(); for (const int i : other) push_back(i); }
// Move assignment operator
SinglyLinkedList& operator = (SinglyLinkedList&& other) { head = other.head; other.head = nullptr; }
// Housekeeping --------------------------------------------------------------------------------------------------------------
void clear() { Node* tmp{ head }; while (tmp) { Node* toDelete{ tmp }; tmp = tmp->next; delete toDelete; } head = nullptr; }
int empty() { return head == nullptr; }
int size() { int k{}; Node* n{ head }; while (n) { ++k; n = n->next; } return k; }
// Modify content --------------------------------------------------------------------------------------------------------------
void push_front(int i) { Node* n = new Node(i); n->next = head; head = n; };
void push_back(int i) { Node* n = new Node(i); Node* l = getLast();if (l) l->next = n; else head = n; }
void pop_front() { if (head) { Node* tmp = head->next; delete head; head = tmp; } }
void pop_back() { // This is a little bit more difficult in a singly linked list
if (head) {
Node* n{ head }, *previous{};
while (n and n->next) {
previous = n;
n = n->next;
}
delete n;
if (previous)
previous->next = nullptr;
else
head->next = nullptr;
}
}
// Access elements --------------------------------------------------------------------------------
int front() { return head ? head->data : 0; };
int back() { Node* n = getLast(); return n ? n->data: 0; }
// Add iterator properties to class ---------------------------------------------------------------
struct iterator { // Local class for iterator
Node* iter{}; // Iterator is basically a pointer to the node
// Define alias names necessary for the iterator functionality
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = int;
using pointer = int*;
using reference = int&;
// Constructor
iterator() {}
iterator(Node* n) : iter(n) {}
// Dereferencing
reference operator *() const { return iter->data; }
pointer operator ->() const { return &iter->data; }
// Aithmetic operations
iterator& operator ++() { if (iter) iter = iter->next; return *this; }
iterator operator ++(int) { iterator temp{ *this }; ++* this; return temp; }
iterator operator +(const difference_type& n) const { iterator temp{ *this }; difference_type k{ n }; while (k--)++temp; return temp; }
iterator& operator +=(const difference_type& n) { difference_type k{ n }; while (k--)++* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return iter < other.iter; }
bool operator > (const iterator& other) const { return iter > other.iter; }
bool operator <= (const iterator& other) const { return iter <= other.iter; }
bool operator >= (const iterator& other) const { return iter >= other.iter; }
// Difference. Also complicated, because no random access
difference_type operator-(const iterator& other) const {
difference_type result{};
Node* n{ iter };
while (n and n != other.iter) {
++result;
n = n->next;
}
return result;
}
};
// Begin and end function to initialize an iterator
iterator begin() const { return iterator(head); }
iterator end() const { return iterator(); }
// Functions typcical for forward lists ----------------------------------------------------------------------
// Easy, becuase we can operate form the current iterator and do not need the "previous" element
iterator insertAfter(iterator& pos, const int i) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* n = new Node(i, pos.iter->next);
pos.iter->next = n;
result = n;
}
return result;
}
iterator eraseAfter(iterator& pos) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* tmp = pos.iter->next->next;
delete pos.iter->next;
pos.iter->next = tmp;
result = pos.iter->next;
}
return result;
}
};
// Test/Driver Code
int main() {
// Example for initilizer list
SinglyLinkedList sllbase{5,6,7,8,9,10,11,12,13,14,15};
// Show move constructor
SinglyLinkedList sll(std::move(sllbase));
// Add some values in the front
sll.push_front(4);
sll.push_front(3);
sll.push_front(2);
sll.push_front(1);
// Delete 1st element (Number 1)
sll.pop_front();
// Delete last element
sll.pop_back();
// Use a std::algorithm on our custom linked list. Works because we have an interator
SinglyLinkedList::iterator iter = std::find(sll.begin(), sll.end(), 8);
// Now add an element after 8
iter = sll.insertAfter(iter,88);
// End delete the 9
iter = sll.eraseAfter(iter);
// Use range based for loop. Works because, we have iterators
for (int i : sll)
std::cout << i << ' ';
}

How to Implement a Iterator class in a LinkedList class

New to c++ and I'm having trouble implementing an Iterator class in my LinkedList. I have a Iterator class defined in the private section of my LinkedList class as follows:
cs_linked_list.h
#ifndef LINKED_LIST_H_
#define LINKED_LIST_H_
#include <initializer_list>
#include <iostream>
namespace cs {
template <typename T>
class LinkedList {
struct Node; // forward declaration for our private Node type
public:
/**Constructs an empty list.**/
LinkedList(){
head_ = nullptr;
}
/**
* #brief Constructs a list from a range.
*
*/
template <class InputIterator>
LinkedList(InputIterator first, InputIterator last) {
for (; first != last; ++first) this->push_back(*first);
}
/** Constructs a list with a copy of each of the elements in `init_list`, in the same order. */
LinkedList(std::initializer_list<T> init_list) {
this->operator=(init_list); // call initializer list assignment
}
/**Constructs a container with a copy of each of the elements in another, in the same order**/
LinkedList(const LinkedList<T>& another){
//TODO
this->operator=(another);
}
/** Destroys each of the contained elements, and deallocates all memory allocated by this list. */
~LinkedList() {
while (this->head_) {
Node* old_head = this->head_;
this->head_ = old_head->next;
delete old_head;
}
}
/**Returns the number of elements in this list.Node *head**/
size_t size() const{ //DONE
//TODO
Node *temp = head_;
size_t len = 0;
while (temp != nullptr){
len++;
temp = temp->next;
}
return len;
}
/**Returns whether the list container is empty (that is, whether its size is 0). **/
bool empty() const{ //DONE
if(size_ == 0){
return true;
} else{
return false;
}
}
/** Appends a copy of `val` to this list. */
void push_back(const T& val) {
Node* new_node = new Node{val};
if (this->size_ == 0) {
this->head_ = this->tail_ = new_node;
} else {
this->tail_->next = new_node;
new_node->prev = this->tail_;
this->tail_ = new_node;
}
++this->size_;
}
/** Prepends a copy of `val` to this list. */
void push_front(const T& val) {
Node* new_node = new Node{val};
if (this->size_ == 0) {
this->head_ = this->tail_ = new_node;
} else {
new_node->next = this->head_;
this->head_->prev = new_node;
this->head_ = new_node;
}
++this->size_;
}
/**Returns a reference to the value in the first element in this list.**/
T& front() const{
return head_->data;
}
/**Returns a reference to the value in the last element in this list. **/
T& back() const{
return tail_->data;
}
/**Deletes the first value in this list. **/
void pop_front(){
Node *temp = head_;
if(empty()){
return;
}
if(temp == tail_){
return;
}
head_ = head_->next;
if (head_ != nullptr) {
head_->prev = nullptr;
} else {
tail_ = nullptr;
}
delete temp;
}
/**Deletes the last value in this list**/
void pop_back(){
if(empty()){
return;
}
if(head_ == tail_){
return;
}
Node *temp = head_;
while(temp->next->next != nullptr){
temp = temp->next;
}
tail_ = temp;
delete tail_->next;
tail_->next = nullptr;
size_--;
}
/**resizes the list so that it contains n elements.**/
void resize(std::size_t n){
//TODO
for (size_t i = 0; i < n; i++){
push_back('\0');
}
}
/**resizes the list so that it contains n elements**/
void resize(std::size_t n, const T &fill_value){
//TODO
for (size_t i = 0; i < n; i++) {
push_back(fill_value);
}
}
/**Removes from the container all the elements that compare equal to val. **/
void remove(const T &val){
//TODO
Node *p1 = head_;
Node *p2 = nullptr;
if(p1 != nullptr && p1->data == val){
head_ = p1->next;
delete p1;
} else {
while (p1 != nullptr && p1->data != val){
p2 = p1;
p1 = p1->next;
}
if (p1 == nullptr) {
return;
}
p2->next = p1->next;
delete p1;
}
}
/**Removes duplicate values from this list**/
void unique(){
//TODO
Node *temp = head_;
while (temp != nullptr && temp->next != nullptr) {
Node *temp2 = temp;
while (temp2->next != nullptr) {
if (temp->data == temp2->next->data) {
Node *temp3 = temp2->next;
temp2->next = temp2->next->next;
delete temp3;
} else {
temp2 = temp2->next;
}
}
temp = temp->next;
}
}
/**Deletes all values in this list.**/
void clear(){
//TODO
while (head_ != nullptr){
Node *temp = head_;
head_ = head_->next;
delete temp;
}
tail_ = nullptr;
size_ = 0;
}
/**Reverses the order of the elements in this list.**/
void reverse(){
//TODO
Node *p1 = head_;
Node *p2 = nullptr;
while (p1 != nullptr) {
Node *temp = p1->next;
p1->next = p2;
p2 = p1;
p1 = temp;
}
head_ = p2;
}
/** Replaces the contents of this list with a copy of each element in `init_list`. */
LinkedList& operator=(std::initializer_list<T> init_list) {
this->size_ = 0;
for (auto&& val : init_list)
this->push_back(val);
return *this;
}
/**Replaces the contents of this list with a copy of each element in another, in the same order.**/
LinkedList& operator=(const LinkedList& another){
//TODO
if (this != &another) {
this->clear();
Node *temp = another.head_;
this->size_ = 0;
while (temp) {
this->push_back(temp->data);
temp = temp->next;
}
}
return *this;
}
/**Compares this list with another for equality.**/
bool operator==(const LinkedList &another){ //DONE
//TODO
auto comp = head_;
auto comp2 = another.head_;
while(comp != nullptr){
if(comp != comp2){
return false;
}
comp = comp->next;
comp2 = comp2->next;
}
return true;
}
/**Compares this list with another for inequality. **/
bool operator!=(const LinkedList &another){ //DONE
//TODO
auto comp = head_;
auto comp2 = another.head_;
while(comp != nullptr){
if(comp != comp2){
return true;
}
comp = comp->next;
comp2 = comp2->next;
}
return false;
}
/** Inserts this list into an ostream, with the format `[element1, element2, element3, ...]` */
friend std::ostream& operator<<(std::ostream& out, const LinkedList& list) {
out << '[';
for (Node* cur = list.head_; cur; cur = cur->next) {
out << cur->data;
if (cur->next)
out << ", ";
}
out << ']';
return out;
}private:
struct Node {
T data;
Node* next = nullptr;
Node* prev = nullptr;
};
Node* head_ = nullptr;
Node* tail_ = nullptr;
std::size_t size_ = 0;
class Iterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
using difference_type = int;
using pointer = T*;
using reference = T&;
// Default constructor
Iterator() {
//TODO
n = nullptr;
}
// Copy constructor
Iterator(const Iterator& other) {
//TODO
this->operator=(other);
}
//Destructor if needed
~Iterator() {
//TODO
while (this->list.head_){
Node *old_head = this->list.head_;
this->list.head_ = old_head->next;
delete old_head;
}
}
// Copy assign
Iterator& operator=(const Iterator& that) {
//TODO
if(this != &that){
this->list.clear();
Node *temp = that.list.head_;
this->list.size_ = 0;
while (temp){
this->list.push_back(temp->data);
temp = temp->next;
}
}
return *this;
}
// Prefix increment
Iterator& operator++() {
//TODO
this->n = this->n->next;
return *this;
}
// Postfix increment
Iterator operator++(int) {
Iterator tmp(*this);
this->operator++();
return tmp;
}
// Prefix decrement
Iterator& operator--() {
//TODO
this->n = this->n->prev;
return *this;
}
// Postfix decrement
Iterator operator--(int) {
Iterator tmp(*this);
this->operator--();
return tmp;
}
// Inequality
bool operator!=(Iterator that) const {
return !(this->operator==(that));
}
// Equality
bool operator==(Iterator that) const {
//TODO
auto temp = list.head_;
auto temp2 = that.list.head_;
while(temp != nullptr){
if(*temp != *temp2){
return false;
}
temp = temp->next;
temp2 = temp2->next;
}
return true;
}
// lvalue dereference
T& operator*() const {
//TODO
return this->n->data;
}
// referring
Iterator* operator->() const {
return this;
}
Iterator begin(){
//TODO
return Iterator(list.head_->next);
}
Iterator end(){
//TODO
return Iterator(list.tail_);
}
private:
Node *n;
LinkedList<T> list;
};
};
} // namespace cs
#endif // LINKED_LIST_H_
Main:
#include "cs_linked_list.h"
#include <iostream>
int main() {
/***TESTING***/
cs::LinkedList<int> list;
// Add few items to the end of LinkedList
list.push_back(1);
list.push_back(2);
list.push_back(3);
std::cout << "Traversing LinkedList through Iterator" << std::endl;
for ( cs::LinkedList<int>::Iterator iter = list.begin();iter != list.end(); iter++) {
std::cout << *iter << " ";
}
std::cout << std::endl;
return 0;
}
Since my Iterator class is private I can't seem to implement my Begin() and End() functions. Should I Make it public or am I missing one crucial step. Instructions say to define a Iterator class in the private section of my LinkedList class.

Dereferencing a member Pointer

I am implementing a doubly linked list and I am getting a segfault when I try to access a member veritable of an object pointed at by a member pointer. My linked list is composed of Nodes, which have a value and a next and previous pointer
String (This is the bare bones implementation from a previous project):
class String{
public:
int len;
char *str;
String()
:len(0), str(nullptr){}
String(char const* S)
:len(strlen(S)), str(new char[len +1]){
assert(S != 0);
strcpy(str, S);
}
~String(){
delete[]str;
}
};
Node (I know this doesn't implement 'the big three', I would rather keep this class to a minimum):
#include <initializer_list>
template<typename T>
struct Node{
T value;
Node* next;
Node* prev;
Node() = default;
Node(T t, Node* n, Node* p)
:value(t), next(n), prev(p){}
Node & operator=(const Node & N){
value = N.value;
next = N.next;
prev = N.prev;
return *this;
}
};
Doubly linked list:
template<typename T>
struct List
{
List(std::initializer_list<T>);
Node<T>* head;
Node<T>* tail;
List()
:head(nullptr), tail(nullptr){}
//copy constructor
List(const List<T> & l){
Node<T>* p = l.head;
head = p;
Node<T>* past;
while(p){
Node<T>* q = new Node<T>;
*q = *p;
if(head == p){
head = q;
}else{
past->next = q;
q->prev = past;
}
past = q;
p = q->next;
}
tail = past;
}
//copy assignment
List & operator=(const List & L){
List temp = L;
swap (*this, temp);
return *this;
}
Node<T>* getHead()const{
return head;
}
Node<T>* getTail()const{
return tail;
}
void swap(List a, List b){
Node<T>* temp1 = a.getHead();
Node<T>* temp2 = a.getTail();
a.head = b.getHead();
a.tail = b.tail;
b.head = temp1;
b.tail = temp2;
}
void push_back(T t){
Node<T>* p = new Node<T>(t, nullptr, tail);
if(tail){
tail->next = p; //Segfault occurs here
}else{
head = p;
}
tail = p;
}
int compare(const List<T> & b)const{
Node<T>* temp1 = this->head;
Node<T>* temp2 = b.head;
while (temp1 != this->tail && temp2 != b.tail) {
if (temp1->value < temp2->value)
return -1;
if (temp2->value < temp1->value)
return 1;
}
if (temp1 == this->tail) {
if (temp2 != this->tail)
return -1; // [first1, last1) is a prefix of [first2, last2)
else
return 0; // [first1, last1) and [first2, last2) are equivalent
}
else {
return 1; // [first2, last1) is a prefix of [first1, last1)
}
}
size_t size()const{
size_t n = 0;
Node<T> *p = head;
while (p){
++n;
p = p->next;
}
return n;
}
void clear(){
Node<T> *p = head;
while(p){
Node<T>* q = p-> next;
delete[] p;
p = q;
}
head = tail = nullptr;
}
~List<T>(){
clear();
}
};
template<typename T>
List<T>::List(std::initializer_list<T> list)
{
for (T const& elem : list)
push_back(elem);
}
Main:
int main()
{
List<String> v1 = {"a", "b", "c"}; //segfault occurs on second pass of initialization loop
return 0;
}
Any help is appreciated!
Node (I know this doesn't implement 'the big three', I would rather keep this class to a minimum):
You should note that the copy/move constructors and assignment operators are still provided as compiler generated default versions.
To avoid that in cases you won't want to implement the big three (or five) you'll need to explicitly delete them:
class String{
public:
int len;
char *str;
String()
:len(0), str(nullptr){}
String(char const* S)
:len(strlen(S)), str(new char[len +1]){
assert(S != 0);
strcpy(str, S);
}
// Add these:
String(const String&) = delete;
String(String&&) = delete;
String& operator=(const String&) = delete;
String& operator=(String&&) = delete;
~String(){
delete[]str;
}
};