Singly Linked List assign issue (nullptr) - c++

what's wrong with this simple Linked List ?
// linked_lst1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class Node
{
int data;
Node* next;
friend class LinkedList;
};
class LinkedList
{
private:
Node* s;
public:
LinkedList() : s(NULL)
{};
void add(int x)
{
Node* s1 = new Node();
s1 = s;
if (!s1)
{
s->data = x;
return;
}
while (s1->next)
s1 = s1->next;
Node* temp = new Node;
temp->data = x;
s1->next = temp;
temp->next = NULL;
}
void showList()
{
Node* s1 = new Node;
s1 = s;
while (s1)
{
cout << s1->data << " ";
s1 = s1->next;
}
}
};
Here is main section :
int main()
{
LinkedList list;
list.add(3);
list.showList();
return 0;
}
I think there is an assign issue in s->data = x;, but I don't know how to solve it...
Notice that this is just an educational simple code and I don't want to use templates etc.
I think, I got what was wrong.

You make a new node and then immediately overwrite s1 to point to whatever s was pointing to -- you lose all access to the newly created node.

Related

Multiple constructors in a C++ LinkedList class: non-class type "ClassName"

I have a LinkedList constructor where I can pass in an array and it builds. Then I can add additional nodes to it by passing in integers.
However, I also want the option to construct the LinkedList, without any arguments. In my LinkedList.h file I've tried to create a constructor that sets the first and last pointers. My add method should construct a Node.
But in my main() function, when I try to use this constructor, I get an error:
request for member ‘add’ in ‘l’, which is of non-class type ‘LinkedList()’
Same error for the other methods called in the main.cpp.
Where am I going wrong in how I structure my two constructors?
main.cpp
#include <iostream>
#include <string>
#include "LinkedList.h"
using namespace std;
int main()
{
//int A[] {1, 2, 3, 4, 5};
//LinkedList l(A, 5);
LinkedList l();
l.add(8);
l.add(3);
cout << l.getCurrentSize()<<endl;
l.display();
return 0;
}
LinkedList.h
#ifndef LINKED_LIST_
#define LINKED_LIST_
#include "IList.h"
class LinkedList: public IList
{
protected:
struct Node
{
int data;
struct Node *next;
};
struct Node *first, *last;
public:
//constructor
LinkedList(){first=nullptr; last=nullptr;}
LinkedList(int A[], int n);
//destructor
virtual ~LinkedList();
//accessors
void display();
virtual int getCurrentSize() const;
virtual bool add(int newEntry);
};
#endif
LinkedList.cpp
#include <iostream>
#include <string>
#include "LinkedList.h"
using namespace std;
//constructor
LinkedList::LinkedList(int A[], int n)
{
Node *t;
int i = 0;
first = new Node;
first -> data = A[0];
first -> next = nullptr;
last = first;
for(i = 1; i < n; i++) {
t = new Node;
t -> data = A[i];
t -> next = nullptr;
last -> next = t;
last = t;
}
};
//destructor
LinkedList::~LinkedList()
{
Node *p = first;
while (first) {
first = first -> next;
delete p;
p = first;
}
}
void LinkedList::display()
{
Node *p = first;
while(p) {
cout << p -> data << " ";
p = p -> next;
}
cout <<endl;
}
int LinkedList::getCurrentSize() const
{
Node *p = first;
int len = 0;
while(p) {
len++;
p = p -> next;
}
return len;
}
bool LinkedList::add(int newEntry)
{
Node *temporary;
temporary = new Node;
temporary -> data = newEntry;
temporary -> next = nullptr;
if (first==nullptr) {
first = last = temporary;
}
else {
last -> next = temporary;
last = temporary;
}
return true;
}
The problem has nothing to do with your constructors themselves.
LinkedList l(); is a declaration of a function named l that takes no arguments, and returns a LinkedList. That is why the compiler is complaining about l being a non-class type.
To default-construct a variable named l of type LinkedList, drop the parenthesis:
LinkedList l;
Or, in C++11 and later, you can use curly-braces instead:
LinkedList l{};

How would you write a function to create a linked list?

I was wondering if it would be possible to create a function that would create a linked list, here is my attempt, I would appreciate if anyone could tell me if this is correct or not.
The logic is as follows:
Take in a starting node, the created linked list will be connected to this node
Create all the nodes that need to be created and store their memory addresses in a vector
Loop through the vector linking together all of the nodes
#include <iostream>
#include <vector>
using namespace std;
class node{
public:;
int value;
node *next;
node():value(0),next(NULL){};
};
void CreateList(node& starting_node, int number_of_nodes_to_create){
// Keep track of all the nodes addresses that need to be created
vector <node*> nodes = {};
// Create the nodes
for (int i = 0; i < number_of_nodes_to_create;i++){
node *temp = new node;
nodes.push_back(temp);
}
// Attach the first created node to the starting node
starting_node.next = nodes[0];
// We now have all the new nodes, now we just need to link them all up with pointers
for (int i = 0; i < nodes.size()-1;i++){
nodes[i] ->next = nodes[i+1];
}
}
I am very much a beginner, all criticism is welcome!
You don't need the vector at all. Your function can be simplified to something like this:
#include <iostream>
#include <vector>
using namespace std;
class node{
public:
int value;
node *next;
node() : value(0), next(NULL) {}
};
void CreateList(node* &starting_node, int number_of_nodes_to_create){
// if the list already exists, find the end of it...
node **n = &starting_node;
while (*n) {
n = &((*n)->next);
}
// Create the nodes
while (number_of_nodes_to_create > 0) {
*n = new node;
n = &((*n)->next);
--number_of_nodes_to_create;
}
}
void DestroyList(node *starting_node) {
while (starting_node) {
node *n = starting_node->next;
delete starting_node;
starting_node = n;
}
}
int main() {
node* head = NULL;
CreateList(head, 5);
...
DestroyList(head);
}
Online Demo
Though, it is not usual for a list creation to take an existing node as input. Usually the creation should create the list and then return the 1st (head) node, eg:
#include <iostream>
#include <vector>
using namespace std;
class node{
public:
int value;
node *next;
node() : value(0), next(NULL) {}
};
node* CreateList(int number_of_nodes_to_create){
node *head = NULL, **n = &head;
while (number_of_nodes_to_create > 0) {
*n = new node;
n = &((*n)->next);
--number_of_nodes_to_create;
}
return head;
}
void DestroyList(node *head) {
while (head) {
node *n = head->next;
delete head;
head = n;
}
}
int main() {
node* head = CreateList(5);
...
DestroyList(head);
}
Online Demo

How can I have a linked-list using class?

I'm trying to write a linked-list using class and I want it to have a specific format.
For example if I have three data called p1,p2 and p3 and a linked-list called list; I want to put them in order like blow.
list.insert(p1).insert(p2).insert(p3);
I tried to return the object, but didn't work.
Here's my code.
#include<iostream>
using namespace std;
class linked_list {
public:
int *head;
linked_list();
~linked_list();
linked_list insert(int data);
};
linked_list::linked_list()
{
head = NULL;
}
linked_list::~linked_list()
{
int *temp;
int *de;
for (temp = head;temp != NULL;) {
de = temp->next;
delete temp;
temp = de;
}
delete temp;
//delete de;
}
linked_list linked_list::insert(int data)
{
int *temp;
temp = new int;
*temp = data;
temp->next = NULL;
if (head == NULL) {
head = temp;
}
else {
int* node = head;
while (node->next != NULL) {
node = node->next;
}
node->next = temp;
// delete node;
}
//delete temp;
return *this;
}
int main(){
linked_list l1;
int p1,p2,p3;
l1.insert(p1).insert(p2).insert(p3);
return 0;}
#Jarod42 got your answer, despite all the buggy things around, what you want is something like this.
The function you want to chain must return a reference to your current object instance.
Here is a Foo class that change its _data member and chain multiple time.
#include <iostream>
class Foo
{
private:
int _data;
public:
Foo(int data) : _data(data) {}
~Foo()
{
}
// change the value of data then return a reference to the current Foo instance
Foo &changeData(int a)
{
_data = a;
return *this;
}
void printData()
{
std::cout << _data << std::endl;
}
};
int main()
{
Foo f(1);
f.changeData(2).changeData(3);
f.printData();
}
Note that I'm returning Foo& from the function I'm chaining, that's the little trick that is missing from yours.
Hope it helped you :)

Making template type LinkedList

i have recently started studying linkedlist in c++. Although i am finding it pretty confusing but i made some functions to insert and delete and element from the linkedlist.
The program worked fine with int data type. But i want to create a linkedlist of template type and i cannot understand how to do it.
I have tried to create a function to insert the node at the first position of link list but it gives me errors like access specifier needed before node etc ...
#include <iostream>
#include<conio.h>
using namespace std;
template<class T>
class node
{
public:
T data;
node *next;
};
template<class T>
class linklist
{
public:
node <int>*head;
linklist()
{
head = NULL;
}
bool Is_Empty(node <T>*ptr)
{
if(ptr==NULL)
{
return true;
}
return false;
}
void insert_at_head(T num)
{
if(Is_Empty(head))
{
node <T>*temp = new node; // error is on this line. it says access specifier needed before node.
temp->data = num;
head = temp;
temp->next = NULL;
}
else
{
node *temp = new node;
temp->data = num;
head = temp;
temp->next = head->next;
}
}
void show_list(node <T>*ptr)
{
cout<<"\nElements in the List are : ";
while(ptr!=NULL)
{
cout<<ptr->data<<" ";
ptr = ptr->next;
}
}
};
int main()
{
cout << "Hello world!" << endl;
getch()
}

I am getting the error "invalid null pointer"

I want to read in student names from a file and insert them into my linked-list, but I am having this problem with an error box. The error reads "Expression: Invalid Null Pointer."
I've googled with no such luck. I think I have an idea where I've went wrong, but I don't know how to fix it.
If you could help, that would be great!
Here is my code:
P.S I'm not nearly done so my code might be incomplete, I'm just trying to weed out all my errors now so I don't have triple my errors at the end.
LList.h
#include <iostream>
#include <iomanip>
#include <string>
#ifndef LLIST_H
#define LLIST_H
typedef int ElementType;
class LList
{
public:
LList();
~LList();
void insert(std::string new_data);
void display();
void remove(std::string delete_data);
private:
class Node
{
public:
std::string data;
Node *next;
Node(std::string data_value = NULL);
};
Node *head;
int mySize;
};
#endif LLIST_H
LList.cpp
#include <iomanip>
#include <iostream>
#include <string>
#include "LList.h"
using namespace std;
LList::Node::Node (string data_value)
{
this -> data = data_value;
this -> next = NULL;
}
LList::LList()
{
this -> head = new Node(0);
mySize = 0;
string data = "";
}
LList::~LList()
{
delete this -> head;
}
void LList::insert(string new_data)
{
Node *tempHolder;
tempHolder = this->head;
while (tempHolder->next != NULL)
tempHolder = tempHolder -> next;
Node *newNode = new Node(new_data);
tempHolder ->next = newNode;
this->mySize++;
}
void LList::display()
{
Node *temp;
temp = head->next;
while(temp -> next != NULL)
{
cout << temp -> data << endl;
temp = temp -> next ;
}
}
void LList::remove(string delete_data)
{
Node *tempHolder;
tempHolder = head;
while (tempHolder->next != NULL )
{
if (tempHolder->next->data == delete_data)
{
Node *delete_ptr = tempHolder->next;
tempHolder->next = tempHolder->next->next;
delete delete_ptr;
mySize-- ;
break;
} else
tempHolder = tempHolder->next;
}
}
Main.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include "LList.h"
#include <fstream>
using namespace std;
int main()
{
LList student;
ifstream infile;
char readLine[500];
infile.open ("names.txt");
if(infile.is_open())
{
while (!infile.eof())
{
infile.getline(readLine,sizeof(readLine)); // read a line from file
student.insert(readLine);
}
}
else
{
cout << "Can't open file!" << endl;
}
}
I found my problem.
In:
LList::LList()
{
this -> head = new Node(0);
mySize = 0;
string data = "";
}
Node(0);
is calling my
LList::Node::Node (string data_value)
{
this -> data = data_value;
this -> next = NULL;
}
which is initialized as a string.
I changed
Node(0);
to
Node("");
and it worked flawlessly.
I wonder could you give the reference where you read that you may to write?
Node(std::string data_value = NULL);
Class std::string has no constructor that converts NULL to an object of type std::string.
it would be much better to declare the constructor without a default argument
Node( std::string data_value );
There is no any sense to create a node without data.
In fact there is no any need to declare a constructor of Node. It could be used as an aggregate.
Also change the constructor of LList as
LList::LList() : head( 0 ), mySize( 0 ){}
Also the destructor is invalied
LList::~LList()
{
delete this -> head;
}
You have to delete not only head but all nodes in the LList.
Also nodes in a single linked list are inserted in the beginning of the list that is before the head.
I would write method insert the following way provided that the constructor of Node is removed bacause it is not needed.
void LList::insert( const std::string &new_data )
{
head = new Node { new_data, head };
}
If your compiler does not support the initializer list then you indeed need to define constructor in class Node.
Node( const std::string &data_value, next_node = NULL );
In this case method insert will look as
void LList::insert( const std::string &new_data )
{
head = new Node( new_data, head );
}