Linked List insertion using for loop in separate function - c++

I am learning how to program in C++, and have looked at linked lists. I have found many code snippets to get me started.
The code I am playing with is from studytonight. I understand how to insert nodes into a list. But what if I want to create a linked list and fill x-many nodes at once in a loop? The for loop in my main() works fine, but when I try turning it into a function, such as arrayToList(), I am running into problems.
The function would simply use the entries of an array and turn them into the data (like an index) and a second value stored in the node. Obviously, the function needs to return a list to continue any manipulation, like deleting or replacing, etc, but also needs to receive a list as a parameter as the created list inside won't exist outside this function. The call to traverse the list inside the for loop is just to highlight that inside the function that list isn't empty.
I am a little lost as to make the function work, and would appreciate any help regarding a method to iteratively add x-many at once nodes to a linked list. I hope I have explained my problem well enough.
#include <iostream>
#include <stdlib.h>
using namespace std;
struct node
{
int data; // Data
node *prev; // A reference to the previous node
node *next; // A reference to the next node
double x;
};
class Doubly_Linked_List
{
node *front; // points to first node of list
node *end; // points to first las of list
public:
Doubly_Linked_List()
{
front = NULL;
end = NULL;
}
void add_front(int, double );
void forward_traverse();
void arrayToList(int[], int);
};
void Doubly_Linked_List :: add_front(int d, double x)
{
// Creating new node
node *temp;
temp = new node();
temp->data = d;
temp->x = x;
temp->prev = NULL;
temp->next = front;
// List is empty
if(front == NULL)
end = temp;
else
front->prev = temp;
front = temp;
}
void Doubly_Linked_List :: forward_traverse()
{
node *trav;
trav = front;
while(trav != NULL)
{
cout<<trav->data<<" (" << trav->x << " )" << endl;
trav = trav->next;
}
}
void Doubly_Linked_List :: arrayToList(int arr[], int n)
{
Doubly_Linked_List list;
for(int i=n-1; i>=0;i--)
{
cout << i << endl;
list.add_front(arr[i], arr[i]);
list.forward_traverse();
}
}
int main()
{
Doubly_Linked_List list;
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
// for (int i= 1; i< 10; i++)
// {
// list.add_front(i, i*2);
// }
list.arrayToList(arr, n);
cout << "after filling arrayList " << endl;
list.forward_traverse();
}

For starters the function should be declared like
void arrayToList( const int[], size_t );
and the function can be defined the following way if to take into account this commented statement in main
// list.add_front(i, i*2);
void Doubly_Linked_List :: arrayToList( const int arr[], size_t n )
{
while ( front )
{
node *current = front;
front = front->next;
delete current;
}
end = nullptr;
for ( size_t i = n; i != 0; i-- )
{
add_front( arr[i-1], 2 * arr[i-1] );
}
}
Though it would be better to declare the function at least like
void arrayToList( const std::pair<int, double>[], size_t );

Your arrayToList() is creating and filling a local Doubly_Linked_List object named list, which is a separate object from the list in main(). Creating a local object is fine (it is good for exception safety), but arrayToList() is then discarding that local object and not assigning its data to the object that arrayToList() was actually called on. That is why your call to forward_traverse() in main() does not see anything changed.
Try this instead:
#include <utility>
void Doubly_Linked_List :: arrayToList(int arr[], int n)
{
Doubly_Linked_List list;
for(int i=n-1; i>=0;i--) {
list.add_front(i, arr[i]);
}
// add this
std::swap(front, list.front);
std::swap(end, list.end);
}
Otherwise, get rid of the local list and modify the data in this instead:
void Doubly_Linked_List :: arrayToList(int arr[], int n)
{
// optional: clear the called-on object first, if needed...
// clear(); // <-- add this method to Doubly_Linked_List...
for(int i=n-1; i>=0;i--) {
add_front(i, arr[i]);
}
}
Otherwise, change arrayToList() to be static, and then have it return a new Doubly_Linked_List object (just make sure you also implement a copy constructor, copy assignment operator, and destructor, per the Rule of 3/5/0):
class Doubly_Linked_List
{
...
// implement these!
~Doubly_Linked_List();
Doubly_Linked_List(const Doubly_Linked_List &);
Doubly_Linked_List& operator=(const Doubly_Linked_List &);
// and change this
static Doubly_Linked_List arrayToList(int[], int);
...
};
Doubly_Linked_List Doubly_Linked_List :: arrayToList(int arr[], int n)
{
Doubly_Linked_List list;
for(int i=n-1; i>=0;i--) {
list.add_front(i, arr[i]);
}
return list;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
Doubly_Linked_List list = Doubly_Linked_List::arrayToList(arr, n);
cout << "after filling arrayList " << endl;
list.forward_traverse();
}

Related

Breakpoint on Delete class pointer

I'm working on a class project and this piece of code won't let me delete an instance of a class without throwing a breakpoint error.
The class is Node, I'm trying to build a singly linked list for data structures and algorithms. I'll include the whole program, it isn't long, but the code in question that's causing the problem is in deleteMin(), the delete u.
#include <iostream>
using namespace std;
// we create a Node class.
class Node { // inside this class we hold two pieces of information.
int x; // the integer x, which is our data.
Node* next; // and the address of the next node.
public:
Node(int x0) : x(x0), next(NULL) { } // Here I've set up a constructor that sets x equal to the argument
// and defaults the next address to NULL.
bool add(int newValue); // Here follows our three required functions.
int deleteMin();
int size();
void printSSL(); // I also added a printSSL() function so that we can test and see what's going on.
};
//Originally I wanted to put these inside of the Node class, but then you'd end up with a unique head and tail for every Node.
//So instead I've left them outside. If you wanted to create multiple SSList's then you'd want to create an object out of these as well.
Node* head; // The first value in the our SLList.
Node* tail; // The last value in our SLList.
int n; // The number of elements in the list.
// I should mention here that head and tail are set equal to the first value in the SLList in the Main() function below.
// Here follows the actual implementation.
// I chose to try and simplify things by focusing on the add() function.
// If the add function organizes the information, and puts it into the SLList in order,
//then deleteMin() only has to pull the first value.
bool Node::add(int newValue) { // add() is a member function of Node and it takes in the newValue were adding to the list.
Node* u = new Node(newValue); // First thing we do is create a new Node using the argument value x. We pass this into a pointer, u.
if (newValue <= head->x) { // Next, we check to see if the new value is less than the head.
u->next = head; // if it is, then our job is done and we just make this new, smaller value, the new head.
head = u; // we do this by making the initial head equal to the next address in the new Node u.
n++; // Once we have the address saved, we make u into the new head and increment n.
return true; // There's no iteration in this case, so this if statement would be O(1).
}//O(1)
else { // If the new value is greater than the head, then we have to store it further back in the SLList.
Node* y = head; // This was the hardest part of the whole thing... I solved it by creating two Node pointers,
Node* z = head; // Both Node pointers are set equal to head, but this is mostly just to ensure that they aren't empty.
while ((newValue > y->x) && (y != tail)) { // Then I set a while loop that looks at whether the new value is less than the value in the head.
z = y; // The while loop continues, moving through the list of values, setting y equal to the next value,
y = y->next; // and using z to keep track of the former value.
} // The loop exits when we either a) hit the end of the SLList, y == tail, or when the new value is
if (y == tail) { // smaller than the next value, newValue < y->x. When the loop exits we have to deal with these two
y->next = u; // scenarios separately. If we reached the end of our list, then adding the new value is as simple as
tail = u; // setting y->next equal to u, then we make u into the new tail.
} // if we didn't reach the end of the list, then we have to set u inbetween z and y. This was really
else { // the only reason I needed z. I needed to be able to update the address of the previous Node, and
z->next = u; // I also needed to have the address of the next Node, this way I could slip u inbetween the two.
u->next = y; // Worst case scenario, this function runs through the entire SLList and then adds the value at the end.
} // I could have shaved off some time by asking if(newValue > tail->x) then run the z->next=u; and u->next=y; after
n++; // after that, but that throws an error becauset ail is a NULL pointer, which is bull#*#!
return true; // because I'm not dealing the tail->next, all I care about is tail->x which isn't NULL.
}//O(n) // But because this is an SSList and not a DLList I have no way of going to the n-2 element.
}//O(max(1, n)) // When that's done, we just increment n and leave the function.
// Considering that the worst case scenario, when x > tail->x, takes us through the whole SLList.
// I'm going to say that this add function is O(n).
int Node::deleteMin() { // The deleteMin() function starts by checking whether or not the
int x = head->x;
Node* u = head;
head = head->next;
delete u; // I have to figure out what the hells going on right here, why can't I delete this?
return x;
}
int Node::size() {
cout << n + 1 << endl;
return n + 1;
}
void Node::printSSL() {
Node* u = head;
cout << "Head:";
for (int i = 0; i <= n; i++) {
cout << i << ":(" << u->x << ", " << u->next << ") ";
u = u->next;
}
cout << " Tail" << endl;
}
int main()
{
Node one(1);
head = &one;
tail = &one;
one.printSSL();
one.deleteMin();
}
You declared an object of the type Node
Node one(1);
You may not apply the operator delete to a pointer to the object because the object was not allocated dynamically. It has automatic storage duration.
Pay attention to that it is a bad idea when functions depend on global variables. For example you will be unable to define two lists in your program.
What you need is to define a class named something like List the following way
class List
{
private:
Node *head = nullptr, *tail = nullptr;
public:
// special member functions and some other member functions;
void clear();
~List() { clear(); }
};
and to allocate nodes dynamically that will be inserted in the list.
The destructor and the function clear will delete all the allocated nodes in the list.
class Node also should be defined as a nested class of the class List.
For example the function clear can be defined the following way
#include <functional>
//...
void List::clear()
{
while ( head )
{
delete std::exchange( head, head->next );
}
tail = nullptr;
}
#include <iostream>
using namespace std;
class SLList { // SLList is the object that holds the entire list.
public: // The Node class lives inside the SLList class.
struct Node {
int data;
Node* next;
Node(int x0) : data(x0), next(NULL) {}
Node() : data(NULL), next(NULL) {}
};
Node* head;
Node* tail;
int n;
SLList() : n(0) {
Node* initial = new Node();
head = initial;
tail = initial;
cout << "You've created a new SSList" << endl;
}
bool add(int newValue);
int deleteMin();
int size();
void printSSL();
};
bool SLList::add(int newValue) { //
if (n == 0) {
head->data = newValue;
n++;
return true;
}
else {
Node* u = new Node(newValue);
if (newValue <= head->data) { //
u->next = head; //
head = u; //
n++; //
return true; //
}//O(1)
else { //
Node* y = head; //
Node* z = head; //
while ((newValue > y->data) && (y != tail)) { //
z = y; //
y = y->next; //
} //
if (y == tail && newValue > y->data) {
y->next = u; //
tail = u; //
} //
else { //
z->next = u; //
u->next = y; //
} //
n++; //
return true;
}
}//O(n) //
}//O(max(1, n)) //
int SLList::deleteMin() {
int x = head->data;
Node* u = head;
head = head->next;
delete u;
n--;
return x;
}//O(1)
int SLList::size() {
cout << n + 1 << endl;
return n + 1;
}//O(1)
void SLList::printSSL() {
Node* u = head;
cout << n << " Nodes|" << "Head:";
for (int i = 0; i < n; i++) {
cout << i << ":(" << u->data << ", " << u->next << ") ";
u = u->next;
}
cout << " Tail" << endl;
}//O(n)
int main() {
SLList* one = new SLList;
one->printSSL();
one->add(30);
one->printSSL();
one->add(20);
one->printSSL();
for (int i = 0; i < 7; i++) {
int x = rand() % 50;
one->add(x);
one->printSSL();
}
for (int i = 0; i < 9; i++) {
one->deleteMin();
one->printSSL();
}
}

Can't pass private member directly from main to function in C++

This my C++ code:
#include <iostream>
class Node
{
public:
int data;
Node* prev;
Node* next;
};
class Doublyll
{
private:
Node* head;
Node* tail;
public:
Doublyll();
Doublyll(int A[], int num);
~Doublyll();
friend std::ostream& operator<<(std::ostream& os, const Doublyll& src);
int Length(Node* p);
};
// Default Constructor will SET head and tail to NULL
Doublyll::Doublyll()
: head(NULL), tail(NULL)
{
}
// Explicit Construcor
Doublyll::Doublyll(int A[], int num)
: head(NULL), tail(NULL)
{
// std::cout << "Explicit Constructor called!\n";
Node** p = &head;
for (int i = 0; i < num; i++)
{
Node* t = new Node;
t->data = A[i];
if (head == NULL)
t->prev = NULL;
else
t->prev = tail;
t->next = NULL;
*p = t;
p = &(t->next);
tail = t;
}
}
// Destructor
Doublyll::~Doublyll()
{
// std::cout << "Desctructor called!\n";
Node* p = head;
Node* tmp;
while (p != NULL)
{
tmp = p;
p = p->next;
delete tmp;
}
}
// Display using Overloading << Operator
std::ostream& operator<<(std::ostream& os, const Doublyll& src)
{
Node* tmp;
for (tmp = src.head; tmp != NULL; tmp = tmp->next)
std::cout << tmp->data << " ";
std::cout << std::endl;
return os;
}
// Find Length how much Node in linked list
int Doublyll::Length(Node* p)
{
static int count = 0;
if (p != NULL)
{
count++;
Length(p = p->next);
}
return count;
}
int main()
{
int A[] = {2, 4, 6, 8, 10, 12, 14};
int size = sizeof(A) / sizeof(A[0]);
// Create object and linked list
Doublyll l1(A, size);
// Display linked list
std::cout << l1;
// Get length of linked list
int c = l1.Length(l1.head);
std::cout << c << std::endl;
return 0;
}
As you can see, I try to practice Doubly Linked List. Then, I want to count total Node in my linked list.
You can see in int Doublyll::Length(Node* p) I try to Count it using Recursion. Just because I want to practice it with Recursion. But, in my main() somewhow this code: int c = l1.Length(l1.head); said "Head is inaccessible"
I know that is because Head is Private in my Doublyll class. And I can simply change it to Public. OR I can write a function getHead() which will return Head pointer and then pass it as arguments.
So, Is there a way to dircetly pass it from my main() without change the member to public or write a getHead() function? or maybe there's another way to write a Recursion based on my problem, which in the future can also implement it to another recursion like display()? Because it seems like difficult to access if everything is inside class.
Maybe you can also review how I create a Doubly Linked List. Thank you!
Make int Doublyll::Length(Node *p) a private member function and add a public int Doublyll::Length() that takes no arguments and does:
int Doublyll::Length()
{
return Length(head);
}
(also you should probably make both of them const - int Doublyll::Length() const since they shouldn't modify anything)
Then just call l1.Length() in main.
Users of Doublyll shouldn't know about the internals of the class, and it doesn't make sense to ask a Doublyll object for the length from some node that it might not even own. Making Length(Node *p) private prevents nonsense things like l1.Length(l2.head).
As for your implementation of int Doublyll::Length(node *p) it's just wrong. As a comment mentions, you're using a static int count to track the length which will give you the wrong answer if you call the function multiple times. Plus your recursion is wrong since you aren't using the result of the recursive call. Do something like this instead:
int Doublyll::Length(Node *p) const
{
// Base case - no nodes
if (p == nullptr)
return 0;
// Recursive case
return 1 + Length(p->next);
}
Or a solution that allows for tail call optimization:
int Doublyll::Length(Node *p, int count) const
{
// Base case - no more nodes - return count
if (p == nullptr)
return count;
// Recursive case - increment count and go to the next node
return Length(p->next, count+1);
}
int Doublyll::Length() const
{
return Length(head, 0);
}
A common technique when implementing recursive functions is to have one public non-recursive function to start things off (say, Doublyll::Length()), and a second private helper function that actually performs the recursion (something like Doublyll::LengthRecursive()).
This could look something like:
int Doublyll::LengthRecursive(Node* p)
{
static int count = 0;
if (p != NULL)
{
count++;
Length(p = p->next);
}
return count;
}
int Doublyll::Length()
{
return LengthRecursive(head);
}
One way of handling a situation like this is to use two member functions: one that is the public interface and one that is private but has the signature you want for the recursive call.
For example:
class Doublyll
{
private:
Node* head;
Node* tail;
int LengthAux(Node* p); //private recursive implementation
public:
Doublyll();
Doublyll(int A[], int num);
~Doublyll();
friend std::ostream& operator<<(std::ostream& os, const Doublyll& src);
int Length(); // public interface
};
int Doublyll::Length() {
return LengthAux(head);
}
// Find Length how much Node in linked list
int Doublyll::LengthAux(Node* p)
{
static int count = 0;
if (p != NULL)
{
count++;
LengthAux(p->next);
}
return count;
}
...
This is a pretty common pattern used by implementations involving recursion. It is the nature of recursive calls that the signature of the recursive guts of the function is often different than the natural signature of calling the function externally.

How to fix Segmentation Fault in linked list

I'm getting a segmentation fault error that I don't know how to fix. List.cpp and List.hpp are bigger, but I added just what I'm using in main.cpp. Here is the code:
List.hpp
#ifndef LIST_H
#define LIST_H
#include <iostream>
#include <cstdlib>
struct Node{
int _value;
Node *_next;
};
struct List{
Node *_head;
int _size;
List();
void insert(int value);
void print();
};
#endif
List.cpp
#include "List.hpp"
List::List(){
_size = 0;
_head = nullptr;
}
void List::insert(int value){
Node* node;
node->_value = value;
node->_next = _head;
_head = node;
}
void List::print(){
Node* head = _head;
if (_size > 0){
while(head){
std::cout << head->_value << " ";
head = head->_next;
}
std::cout<<std::endl;
}
else{
std::cout<<std::endl;
return;
}
}
main.cpp
#include <iostream>
#include "List.hpp"
int main(){
List *L = new List();
int N=0;
std::cout << "type the N value"<< std::endl;
std::cin >> N;
for(int i=0; i<=N; i++){
L->insert(i);
}
L->print();
delete L;
return 0;
}
console
▶ g++ -std=c++14 -Wall main.cpp List.cpp -o main && ./main out
List.cpp: In member function ‘void List::insert(int)’:
List.cpp:10:15: warning: ‘node’ is used uninitialized in this function [-Wuninitialized]
10 | node->_value = value;
| ~~~~~~~~~~~~~^~~~~~~
type the N value
3
[1] 13247 segmentation fault (core dumped) ./main out
I actually don't know how to debug it either (I'm using VS Code), so I have no idea about what is happening with the variables that are being created on the stack and on the heap.
As the error(warning) message says, in the insert function you are doing:
Node* node;
But this simply declares a pointer that is not yet pointing to valid memory. Accessing members of the object such as _value pointed at by node will invoke undefined behavior. This can cause a segmentation fault. If you're unlucky, there won't be a segfault, and the program will break at some later point.
You need to allocate memory for a Node like this:
Node* node = new Node{};
In fact, the entire insert function could simply be:
void List::insert(int value) {
_head = new Node{value, _head}; // allocate Node, initialize to
// appropriate values, and link _head
}
Also, you should default initialize the members of Node like this:
struct Node{
int _value{};
Node *_next = nullptr;
};
Also, there seems to be no need to allocate memory for a List in main:
List *L = new List();
Instead, you can simply have a List object like this:
List L{};
Inside the member function insert you are using an uninitialized pointer node
void List::insert(int value){
Node* node;
^^^^^^^^^^^
node->_value = value;
node->_next = _head;
_head = node;
}
that has an indeterminate value and trying to access memory using this pointer that results in undefined behavior.
You have to allocate a node that will be pointed to by the pointer and inserted in the list.
Also you forgot to increase the size of the list.
But I would like to point to some drawbacks of the implementation.
For starters do not use identifiers that start from underscore because according to the C++ Standard
(3.2) — Each identifier that begins with an underscore is reserved to
the implementation for use as a name in the global namespace.
So such names will confuse readers of your code.
The structure Node should be a private or protected data member of the structure List. The user shall not have a direct access to the structure Node. It is an implementation detail.
There is no sense to allocate an object of the type List dynamically.
Here is a demonstrative program that shows how the list can be implemented.
#include <iostream>
#include <functional>
class List
{
protected:
struct Node
{
int value;
Node *next;
} *head = nullptr;
size_t n = 0;
public:
List() = default;
~List() { clear(); }
// These special member functions you can define yourself if you will want
List( const List & ) = delete;
List & operator =( const List & ) = delete;
void insert( int value );
size_t size() const { return n; }
void clear()
{
while ( head ) delete std::exchange( head, head->next );
n = 0;
}
friend std::ostream & operator <<( std::ostream &os, const List &list )
{
for ( Node *current = list.head; current != nullptr; current = current->next )
{
os << current->value << " -> ";
}
return os << "null";
}
};
void List::insert( int value )
{
head = new Node { value, head };
++n;
}
int main()
{
const int N = 10;
List list;
for ( int i = N; i != 0; i-- )
{
list.insert( i );
}
std::cout << list << '\n';
return 0;
}
The program output is
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null

C++ Copying elements into new list

I have a problem with copying some elements of list into the new one. It has to be done under one condition: elements that can be copied must be from entered range. The problem is that every single element is copied into newlist. Any suggestions? I want to note that my English is not perfect but I hope you gonna get it. Thank you :)
struct Node
{
Node* next;
int data;
};
struct List
{
Node* head;
Lista();
void push(int);
void addafter(int, int);
void delchosen(int);
void pop();
void print();
int count();
Node* find(int);
void pushback(int);
void popback();
void minmax(int&, int&);
List* range(int, int);
};
List::List()
{
head = NULL;
}
void List::push(int value)
{
Node *p = new Node;
p->data = value;
p->next = head;
head = p;
}
List* List::range(int x, int y)
{
Node* e = head;
List* newlist = new List;
while(e)
{
if(e->data > x && e->data <y)
{
newlist->push(e->data);
}
e = e->next;
}
return newlist;
}
int main()
{
List l;
srand(time(NULL));
const int size = 30;
int* arr = new int [size];
for(int i=0; i<size; i++)
{
arr[i]=rand()%20+1;
l.push(arr[i]);
}
l.range(3, 10);
return 0;
}
Didn't think it will be necessary, but I just have edited the code. Every single function works fine excepting this copying.
You never use the new list. That could probably mislead you. For example you could print or watch in the debugger the old list, which is still contain all the values. It happens sometimes with all the programmers, from freshmen to old long-bearded gurus.
Otherwise code should work:
auto newList = l.range(3, 10);
newList->print();
Bonus: General code review.
It would probably be easier to debug and test the code if you fill the list with deterministic values, rather than random content:
for (int i = 0; i < size; i++) {
l.push(i);
}
Most likely you don't need to allocate newlist on the heap. Use stack allocation:
List List::range(int x, int y) const {
...
List newlist;
...
newlist.push(...);
...
return newlist;
}
While it's nice and funny for self-education and various hacking, you should avoid using homebrew linked lists in the serious code. In C++ we tend to use Standard library facilities instead. Something like:
#include <iostream>
#include <iterator>
#include <list>
int main() {
// Construct original list from brace-initializer list
std::list<int> original{ 1, 2, 3, 4, 5, 6, 7 };
// Get the beginning of the new list by advancing
// beginning of the original list by 2 elements
auto begin = original.cbegin();
std::advance(begin, 2);
// Get the end of the new list by advancing
// beginning of the original list by 5 elements
auto end = original.cbegin();
std::advance(end, 5);
// Construct sublist from iterator range
std::list<int> sublist(begin, end);
// Print new list
for (auto&& e : sublist)
std::cout << e << ' '; // prints "3 4 5"
}

How to print the Data part of Linkedlist

Basically I want to print the data part of the Linked list which is basically an Integer pointer and I am assigning it an array at the time of creation, I want to print all the values of it how to do so ???
Thank you.
Here is my code
using namespace std;
struct Node{
Node *next;
int *data;
};
class DataLine{
private:
Node *first;
public:
DataLine(){
first=NULL;
}
void create_list(){
Node *temp=new Node;
int i=2;
int dat[5]={12,13,14,13,16};
temp->data=dat;
temp->next=NULL;
if(first==NULL){
//cout<<"hello 1"<<endl;
first=temp;
}
else{
Node *curr=first; //We are now doing trevercing so we are assigning the first to the node because we donot want to move the first bacuse link break if we move the first
while(curr->next!=NULL) //searching end of list
{
curr=curr->next; //Moving to the next node
}
curr->next=temp; //insert node
temp=NULL; //Making the temp enpty to use it for the new purpose
//delete temp;
}
}
void print_list()
{
Node *prnt=first; //We are now again want trevercing so we agin run the node by the new node
while(prnt!=NULL) //Checking the loop will run till it get the null in the node means its address part and data part both are nUll
{
for(int i=0;i<5;i++)
cout<<" ***** The "<<" node is "<<*(prnt->data+i)<<endl; //Printing the data
prnt=prnt->next; //Moving to the next node
}
}
};
int main(){
DataLine dl;
dl.create_list();
dl.print_list();
_getch();
return 0;
}
The idea of your void print_list(void) is correct but you can make it much cleaner, note however I changed your output to print a single node per line (change that back if you want). The structure of a for loop seems, to me, perfect for linked lists and keeps the linked list code our of the body of the loop.
void print_list(void) const
{
for (Node* p = first; p != NULL; p = p->next)
{
for (int i = 0; i < Node::unLength; ++i) std::cout << p->data[i] << ", ";
std::cout << std::endl;
}
}
However, as pointed out in some of the comments, there are other problems in your create list code. The way I would suggest to fix these (for this program) would be to redefine your structure to always hold a fixed number of integers.
struct Node
{
enum { unLength = 5 };
Node* next;
int data[unLength];
};
I have also added here a constant for the length of the array, since its bad practice to have magic numbers floating around your code, what happens if you mistype one of them?
Now in your void create_list() you can go:
void create_list()
{
Node* temp = new Node;
// Set the next node of temp
temp->next = NULL;
// Add some data to temp (we can't just assign the data pointer in C/C++)
int data[Node::unLength] = {0, 1, 2, 3, 4};
for (int i = 0; i < Node::unLength; ++i) temp->data[i] = data[i];
Node *p = first;
while (p != NULL) p = p->next;
p->next = temp;
}
There is no point setting temp to NULL since temp is deleted straight after the function returns. In your previous code you set the pointer in Node to data (temp->data=dat;, this doesn't work either since dat was deleted as soon as the function returned, you need to instead allocate memory and copy the values from dat which is what the for loop in the above code does.
For you class constructor (and destructor) I would suggest:
class DataLine
{
private:
Node* first;
public:
DataLine(void) : first(NULL) {}
~DataLine(void)
{
while (first != NULL)
{
Node *temp = first->next;
delete first;
first = temp;
}
}
You had the right idea, but there are a few subtle things about C/C++ that aren't obvious in higher level languages, such as copying arrays and the scope of variables.
If you are using C++ however, I would really suggest not worrying about linked lists, just create a std::vector, in C++ 11 something like the following might work (untested):
#include <vector>
#include <array>
int main(int argc, char** argv)
{
std::vector< std::array<int, 5> > myData;
myData.push_back({0, 1, 2, 3, 4});
myData.push_back({0, 1, 2, 3, 4});
myData.push_back({0, 1, 2, 3, 4});
for (const auto& i : myData)
{
for (int j : i) std::cout << j << ", ";
std::cout << std::endl;
}
return 0;
}