I've been given a class declaration (create a list with nodes) in C++ that I need to define and I'm having trouble with one of the member functions: void print() const;
Question: How can I go about traversing and printing out the first->value's without removing const in the function declaration i.e. altering first? The function below yields an error: expression must be a modifiable lvalue.
Class declaration (only details of relevance)
class List {
public:
.
.
.
void print() const;
int size();
void add(int d);
private:
int sz = 0;
struct Node {
int value;
Node* next;
Node(int v, Node* n) : value(v), next(n) {}
};
Node* first; // pointer to the first node
};
Class definition (only details of relevance)
void List::print() const {
while (first != NULL) {
cout << first->value << endl;
first = first->next;
}
}
int List::size() const {
return sz;
}
void List::add(int d) {
if (size == 0)
first = new Node(d, NULL), sz++;
else {
Node* newnode = new Node(first->value, first->next);
first = new Node(d, newnode);
sz++;
}
}
Thanks for your time
The trick is to make a copy of first and only modify the copy: (not tested)
Node* firstCopy = first;
while (firstCopy != NULL) {
cout << firstCopy->value << endl;
firstCopy = firstCopy->next;
}
Related
I'm Trying to do a doubly linked list class that calls a Node class in C++
The Code for the Node class works just fine and I have the code for my class that works only when trying to print the values from least to greatest but if I try to print from greatest to least it only prints some values.
I also need guide on how to make a remove function that works similar to insert
Code of Node class:
Node.h
class Node {
public:
explicit Node(int data = 0, Node *nextPtr = nullptr, Node *beforePtr = nullptr);
int getData() const;
void setData(int data);
Node *getNextPtr() const;
void setNextPtr(Node *nextPtr);
Node *getBeforePtr() const;
void setBeforePtr(Node *beforePtr);
void print() const;
private:
int data;
Node *nextPtr;
Node *beforePtr;
};
Node.cpp
Node::Node(int data, Node *nextPtr, Node *beforePtr) : data(data), nextPtr(nextPtr), beforePtr(beforePtr) {}
int Node::getData() const {
return data;
}
void Node::setData(int data) {
Node::data = data;
}
Node *Node::getNextPtr() const {
return nextPtr;
}
void Node::setNextPtr(Node *nextPtr) {
Node::nextPtr = nextPtr;
}
Node *Node::getBeforePtr() const {
return beforePtr;
}
void Node::setBeforePtr(Node *beforePtr) {
Node::beforePtr = beforePtr;
}
void Node::print() const {
cout << getData() << endl;
}
MyList.h
class MyList {
public:
MyList(Node *currentPrt = nullptr);
void insert(int value);
void print() const;
private:
Node *currentPrt;
};
MyList.cpp
MyList::MyList(Node *currentPrt) {}
void MyList::insert(int value) {
if(currentPrt == nullptr){
currentPrt = new Node;
currentPrt->setData(value);
currentPrt->setNextPtr(nullptr);
currentPrt->setBeforePtr(nullptr);
}
else{
if(value > currentPrt->getData()){
while (currentPrt->getNextPtr() != nullptr && currentPrt->getNextPtr()->getData() < value){
currentPrt = currentPrt->getNextPtr();
}
Node *newPtr = new Node(value);
newPtr->setNextPtr(currentPrt->getNextPtr());
currentPrt->setNextPtr(newPtr);
newPtr->setBeforePtr(currentPrt);
}
else{
while (currentPrt->getBeforePtr() != nullptr && currentPrt->getBeforePtr()->getData() > value){
currentPrt = currentPrt->getBeforePtr();
}
Node *newPtr = new Node(value);
if (currentPrt->getBeforePtr() != nullptr){
currentPrt = currentPrt->getBeforePtr();
newPtr->setNextPtr(currentPrt->getNextPtr());
currentPrt->setNextPtr(newPtr);
newPtr->setBeforePtr(currentPrt);
}
else{
currentPrt->setBeforePtr(newPtr);
newPtr->setNextPtr(currentPrt);
}
}
}
}
void MyList::print() const {
Node *ptr;
ptr = currentPrt;
while(ptr->getNextPtr() != nullptr){
ptr = ptr->getNextPtr();
}
for (ptr; ptr != nullptr; ptr = ptr->getBeforePtr()){
cout << ptr->getData() << endl;
}
}
MyList test;
test.insert(5);
test.insert(3);
test.insert(2);
test.insert(1);
test.insert(2);
test.insert(7);
test.insert(8);
test.insert(6);
test.print();
Output:
8
7
5
3
2
1
and when the print function is this:
void MyList::print() const {
Node *ptr;
ptr = currentPrt;
while(ptr->getBeforePtr() != nullptr){
ptr = ptr->getBeforePtr();
}
for (ptr; ptr != nullptr; ptr = ptr->getNextPtr()){
cout << ptr->getData() << endl;
}
}
Output is: 1
2
2
3
5
6
7
8
as expected
Thank you for all the help
First of all, your code has undefined behaviour because of this constructor:
MyList::MyList(Node *currentPrt) {}
This leaves the currentPrt member uninitialised. It should be:
MyList::MyList(Node *currentPrt) : currentPrt(currentPrt) {}
The problem you have with the list order is caused by the insert method. There are two code blocks there where two next pointers are set, but only one before pointer, so in total three pointers are set. But there should be four of them in the general case.
This issue occurs in the second if block:
Node *newPtr = new Node(value);
newPtr->setNextPtr(currentPrt->getNextPtr());
currentPrt->setNextPtr(newPtr);
newPtr->setBeforePtr(currentPrt);
where newPtr->setNextPtr(currentPrt->getNextPtr()); is not mirrored by a link in the opposite direction. The correction is:
Node *newPtr = new Node(value);
newPtr->setNextPtr(currentPrt->getNextPtr());
if (currentPrt->getNextPtr() != nullptr) // <---
currentPrt->getNextPtr()->setBeforePtr(newPtr); // <---
currentPrt->setNextPtr(newPtr);
newPtr->setBeforePtr(currentPrt);
The same is going wrong in the deeper if block, where the if protection is not needed:
if (currentPrt->getBeforePtr() != nullptr){
currentPrt = currentPrt->getBeforePtr();
newPtr->setNextPtr(currentPrt->getNextPtr());
currentPrt->setNextPtr(newPtr);
newPtr->setBeforePtr(currentPrt);
}
The same statement is missing, and the correction can be:
if (currentPrt->getBeforePtr() != nullptr){
currentPrt = currentPrt->getBeforePtr();
newPtr->setNextPtr(currentPrt->getNextPtr());
currentPrt->getNextPtr()->setBeforePtr(newPtr); // <---
currentPrt->setNextPtr(newPtr);
newPtr->setBeforePtr(currentPrt);
}
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.
class Node
{
protected:
int decimal_value;
char letter;
public:
Node(int decimal, char lett) : decimal_value(decimal), letter(lett)
{}
Node() :decimal_value(0), letter(NULL)
{}
int get_decimal() const
{
return decimal_value;
}
char get_letter() const
{
return letter;
}
void set_decimal(int n)
{
decimal_value = n;
}
void set_letter(char l)
{
letter = l;
}
friend bool operator<( const Node& p1, const Node& p2)
{
return p1.decimal_value > p2.decimal_value;
}
virtual ~Node() {};
};
class Leaf :public Node
{
using Node::Node;
};
class Branch :public Node
{
Node* left;
Node* right;
public:
Branch(Node* l, Node* r) :left(l), right(r)
{
decimal_value = l->get_decimal() + r->get_decimal();
}
};
void tree_builder(priority_queue<Node*>& Q)
{
Node* qleft=new Leaf;
Node* qright= new Leaf;
while (Q.size() > 1)
{
*qleft = *Q.top();
Q.pop();
*qright = *Q.top();
Q.pop();
Node* b1 = new Branch(qleft, qright);
Q.push(b1);
cout << Q.top()->get_decimal();
tree_builder(Q);
}
}
int main()
{
bitset<8> A (string("1001"));
Node* n1= new Leaf (A.to_ulong(), 'A');
priority_queue<Node*> my_q;
my_q.push(n1);
tree_builder(my_q);
}
}
On the very last line of main when I try to perform tree builder on my_q. I get the error " cannot convert argument 1 from piriority_queue Node* to Priority_queue Node however I dont understand what is node as everything is Node* I have simplified my code to only include 1 Node* object for easier viewing.
Your error message suggests that the tree_builder function argument is a reference to a priority_queue<Node>, instead of priority_queue<Node*>, that your code shows.
Said that, I can compile your code just fine with clang, given the right includes.
I'm trying to implement a templated singly linked list and I'm fairly new to C++
#include <iostream>
#include <string>
#define NEWL "\n"
#define PRINT(s) std::cout << s
#define PRINTL(s) std::cout << s << NEWL
#define PRINTERR(e) std::cerr << e << NEWL
////// Class for a Node
template<class Data> class Node {
Node<Data>* next_ptr;
Data data;
public:
Node(Node<Data>* nxt_ptr) :next_ptr(nxt_ptr) {};
Node(Data d, Node<Data>* nxt_ptr) :data(d), next_ptr(nxt_ptr) {};
Node<Data>* get_next() { return next_ptr; }
Data& get_data() { return data; }
friend std::ostream& operator<<(std::ostream& out, const Node<Data>& node) {
out << node.data;
return out;
};
};
////// Class for a SinglyLinkedList
template<class Data> class SLinkedList {
Node<Data>* head_ptr;
int max_size;
public:
SLinkedList() : head_ptr(nullptr) {};
bool is_empty() {
return head_ptr == nullptr;
};
bool is_full() {
return get_size() == max_size;
};
int get_size() {
if (is_empty()) {
return 0;
}
int count = 0;
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
count++;
}
return count;
};
void add(Data d) {
if (is_full()) {
throw std::exception("List is full!");
}
Node<Data> new_node(d, head_ptr);
head_ptr = &new_node;
};
void print_content() {
int count = 1;
PRINTL("This list contains:");
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
PRINTL("\t["<< count << "]" << " at " << it_ptr << " : " << *it_ptr);
count++;
}
}
};
////// Main function
int main()
{
SLinkedList<int> sll;
sll.add(42);
sll.print_content();
}
I can't get this to work. Somehow iterating the list with for-loops does not work. It always results in an Reading Access Violation Exception about a pointer to 0xCCCCCCD0 and I have no idea how to fix this.
Your add function is incorrect
Node<Data> new_node(d, head_ptr);
creates a new function local Node in add. You then set head to the address of that local variable. When the function ends all local variables are destroyed so now head points to an object that no longer exists.
To fix that you need to use the new keyword to create a dynamic object that will live on after the function ends.
Node<Data>* new_node = new Node(d, head_ptr);
head_ptr = new_node;
The down side with this is you need to remember to call delete on all of the nodes you created in the list destructor.
You also have some other bugs in your code. You never set max_size in your constructor so using it at all except to give it a value is undefined behavior as we have no idea what the value of it is going to be. You also never increase the size of the list when you add nodes into the list.
This is a general programming question, and I hope the answers will offer an alternative approach to the problem rather than a quick fix or hack. I have two objects, each of which has some pointers to allocated memory. I want to copy some internal information from one object to the other. Since the information is significantly large, I just want to copy the pointer. The problem is that when the destructor of the two objects are called, they each call the destructor on the internal information (which is now in both objects). This leads to the destructor being called twice on the same pointer.
Since this is quite a complex scenario, and it wouldn't be practical to show you the whole code. I have devised a simple example to illustrate the root of the problem. The code attaches two pre-existing lists without copying any data. As the output shows, the destructor gets called on the last two nodes multiple times. (Once as K is destroyed and again as L is destroyed, since both lists have a pointer to those nodes).
#include <iostream>
struct Node {
int data;
Node * next;
};
class List {
public:
List(const int);
~List();
void append(const int);
void append(const List&);
void print()const;
private:
Node * head;
Node * tail;
};
List::List(const int x)
{
Node * q = new Node;
q->data = x;
q->next = 0;
head = q;
tail = q;
}
List::~List()
{
while (head != 0){
Node * temp = head->next;
std::cout << "Deleting " << head->data << std::endl;
delete head;
head = temp;
}
}
void List::append(const int x)
{
Node * q = new Node;
q->data = x;
q->next = 0;
tail->next = q;
tail = q;
}
void List::append(const List& L2)
{
this->tail->next = L2.head;
this->tail = L2.tail;
}
void List::print()const
{
for (Node * iter = head; iter; iter=iter->next){
std::cout << iter->data << " ";
}
std::cout << std::endl;
}
int main()
{
List L = List(1);
L.append(3);
std::cout << "List L:\n";
L.print();
List K = List(5);
K.append(10);
std::cout << "List K:\n";
K.print();
L.append(K);
std::cout << "List L:\n";
L.print();
}
The output is:
List L:
1 3
List K:
5 10
List L:
1 3 5 10
Deleting 5
Deleting 10
Deleting 1
Deleting 3
Deleting 0
Deleting 39125056
Instead of using a raw pointer to your nodes, use std::shared_ptr<Node> and remove the explicit delete from your destructor. A shared pointer will keep the Node in memory as long as there is a shared_ptr instance pointing to it in scope. When there are no longer any shared_ptr instances pointing to a Node, the Node will be automatically deleted.
In the main function, you declared two local variable L, K, they will be deconstructed before program exists.
In your code, you're append the list K to list L, when deconstructing, K is deconstructed first, as the K still holds the pointer the Nodes 1,3, which means this nodes will be free. But the Node 3 in L still holds the pointer to K's head, that's how the error happens.
Put breakpoints in the deconstructors, you'll find out how it occurs.
Using std::shared_ptr instead of raw pointers will solve your problem.
Here's your code converted to use std::shared_ptr.
#include <iostream>
#include <memory>
struct Node {
int data;
std::shared_ptr<Node> next;
Node(int d) : data(d), next(nullptr) {}
};
class List {
public:
List(const int);
~List();
void append(const int);
void append(const List&);
void print()const;
private:
std::shared_ptr<Node> head;
std::shared_ptr<Node> tail;
};
List::List(const int x)
{
Node * q = new Node(x);
head.reset(q);
tail = head;
}
List::~List()
{
}
void List::append(const int x)
{
Node * q = new Node(x);
tail->next.reset(q);
tail = tail->next;
}
void List::append(const List& L2)
{
this->tail->next = L2.head;
this->tail = L2.tail;
}
void List::print()const
{
for (std::shared_ptr<Node> iter = head; iter.get() != nullptr; iter=iter->next){
std::cout << iter->data << " ";
}
std::cout << std::endl;
}
int main()
{
List L = List(1);
L.append(3);
std::cout << "List L:\n";
L.print();
List K = List(5);
K.append(10);
std::cout << "List K:\n";
K.print();
L.append(K);
std::cout << "List L:\n";
L.print();
}
The output:
List L:
1 3
List K:
5 10
List L:
1 3 5 10
Update
A bare bones implementation of the std::share_ptr functionality:
template <typename T>
struct SharedPtr
{
SharedPtr() : dataPtr(new Data(nullptr)) {}
SharedPtr(T* n): dataPtr(new Data(n)) {}
SharedPtr(SharedPtr const& copy) : dataPtr(copy.dataPtr)
{
dataPtr->useCount++;
}
~SharedPtr()
{
dataPtr->useCount--;
if ( dataPtr->useCount == 0 )
{
delete dataPtr;
}
}
void reset(T* n)
{
dataPtr->useCount--;
if ( dataPtr->useCount == 0 )
{
delete dataPtr;
}
dataPtr = new Data(n);
}
T* get() const
{
return dataPtr->n;
}
T* operator->() const
{
return get();
}
SharedPtr& operator=(SharedPtr const& rhs)
{
if ( this != & rhs )
{
dataPtr->useCount--;
if ( dataPtr->useCount == 0 )
{
delete dataPtr;
}
dataPtr = rhs.dataPtr;
dataPtr->useCount++;
}
return *this;
}
struct Data
{
Data(T* in) : n(in), useCount(1) {}
~Data() { if ( n != nullptr ) delete n; }
T* n;
size_t useCount;
};
Data* dataPtr;
};