C++ linked list implementation - c++

i am working on an assignment where i am asked to implement a linked list in c++. so far everything is working great except for when i am creating a new list. in my method create_list(). after i assign content and an id number to my Field and try to call GetNext() i get an error saying: Request for member 'GetNext()' in 'Node' which is a non-class type '*Field'. I'm still new to the C++ syntax and object oriented programming. What am I doing wrong? I thought by using the line Field *Node = new Field(SIZE, EMPTY); that my variable Node would be of class type Field...?
#include <iostream>
#include <ctype.h>
using namespace std;
typedef enum { EMPTY, OCCUPIED } FIELDTYPE;
// Gameboard Size
int SIZE;
class Field {
private:
int _SquareNum;
FIELDTYPE _Content;
Field* _Next;
public:
// Constructor
Field() { }
// Overload Constructor
Field(int SquareNum, FIELDTYPE Entry) { _SquareNum = SquareNum; _Content = Entry; }
// Get the next node in the linked list
Field* GetNext() { return _Next; }
// Set the next node in the linked list
void SetNext(Field *Next) { _Next = Next; }
// Get the content within the linked list
FIELDTYPE GetContent() { return _Content; }
// Set the content in the linked list
void SetContent(FIELDTYPE Content) { _Content = Content; }
// Get square / location
int GetLocation() { return _SquareNum; }
// Print the content
void Print() {
switch (_Content) {
case OCCUPIED:
cout << "Field " << _SquareNum << ":\tOccupied\n";
break;
default:
cout << "Field " << _SquareNum << ":\tEmpty\n";
break;
}
}
}*Gameboard;
here is my create_list() method:
void create_list()
{
int Element;
cout << "Enter the size of the board: ";
cin >> SIZE;
for(Element = SIZE; Element > 0; Element--){
Field *Node = new Field(SIZE, EMPTY);
Node.GetNext() = Gameboard; // line where the error is
Gameboard = Node;
}
}

. is used for addressing members in objects and references to objects. Node, however, is a pointer to an object. So you need to turn it into a reference before you can use it with .. This means doing (*Node).GetNext(). Or you can use the shorthand: Node->GetNext() - these two are exactly equivalent.
A good mnemonic to use is that you use the pointy operator with pointers :)

No in the declaration
Field *Node = new Field(SIZE, EMPTY);
Node is of type pointer to Field.
The fix is simple if you have a pointer to a class and you want to access a member of that class use ->.
Node->GetNext() = Gameboard;
I think your code has other errors, and I don't think that even with this 'fix' it's going to work. Probably what you really want is
Node->SetNext(Gameboard);

You're calling Node.GetNext(), but Node is a pointer. You need to use the -> operator instead of the . operator, as in Node->GetNext().

The function must returns a reference value if you want to set as a l-value.
You code need some changes:
// Get the next node in the linked list
Field& GetNext() { return *_Next; }
then you can use the function as a l-value
Node->GetNext() = *Gameboard;

Related

Implement iterator of a circular list

I'm trying to implement a class of Circular List with a nested class of iterator and I wrote like this:
template <class T>
class CircularList {
struct Item {
T data;
Item* next;
};
Item* head;
int size;
public:
CircularList() {
head = new Item();
head->next = head;
}
int sizeList() { return size; }
void push(T data) {
Item* i = new Item();
i->data = data;
i->next = head->next;
head->next = i;
size++;
}
class CircularListIterator {
Item* p;
CircularListIterator() {
p = head->next;
}
bool hasNext() {
if(p->next != head) {
return true;
}
return false;
}
T next() {
T data_temp = p->data;
p = p->next;
return data_temp;
}
};
CircularListIterator* iterator() {
return new CircularListIterator();
}
};
int main() {
CircularList<string>* letters = new CircularList<string>;
letters->push("d");
letters->push("c");
letters->push("b");
letters->push("a");
Iterator<string>* it= new Iterator<string>;
it = letters->iterator();
while (it->hasNext()) {
cout<< it->next() << "," << endl;
}
return 0;
}
But the Iterator is not working when I try to create an iterator in the main function, It said that it wasn't declared in the scope and has no member of it.
Assuming by "in the main class" you mean in the main function, the problem is quite straightforward: you're trying to construct a ::Iterator<string>, but there is no class in the global namespace (or anywhere else, in this code sample) called Iterator! You could try constructing a CircularList<string>::CircularListIterator - that's at least a class that exists - but it wouldn't work because the iterator needs to be associated with a CircularList object for it to be able to access member variables like head.
The correct thing to do here is to promote the iterator function - the one that returns a CircularListIterator* - out of the CircularListIterator class and into the CircularList class. Then, in your main function, you can call letters->iterator() and it'll return a CircularListIterator* for the letters object.
Now, CircularListIterator doesn't inherit from any other iterator classes - neither the (nonexistent-in-this-code Iterator you've typed it as, nor the C++ std::iterator or any of its variants) - so you can't assign it to it or probably even compile the code that references Iterator. To make CircularListIterator a subclass of std::iterator, you'll need to extend std::iterator<Category, T> with the appropriate category. See https://www.cplusplus.com/reference/iterator/iterator/ for more information on the std::iterator class template, including an example of implementing it.

C++ How may I return an array class member of a nested class?

This is not a real question, since I've already solved the problem myself, but I still need some clarifications about the mechanism behind assigning an array's address to a pointer of the same type when the array is a class member of a nested class.
The following code is fully functioning, although it may lack some error_check. It is only meant to show how I made my (real) program work.
HEADER (linkedList)
class linkedList
{
public:
linkedList();
~linkedList();
int* getArray();
void forward();
private:
class listNode
{
public:
listNode();
~listNode();
friend class linkedList;
private:
int array[3];
listNode* next;
};
listNode *first;
listNode *current;
};
CPP (linkedList)
linkedList::linkedList()
{
first = new listNode;
current = first;
}
//~~~~~~~~~~~~
linkedList::~linkedList()
{
delete first;
first = 0;
current = 0;
}
//~~~~~~~~~~~~
int* linkedList::getArray()
{
if (current)
{
return &(current->array[0]);
}
}
//~~~~~~~~~~~~
void linkedList::forward()
{
if (current->next)
{
current = current->next;
}
}
//-------------------------
//-------------------------
//-------------------------
linkedList::listNode::listNode()
{
next = 0;
for (int i = 0; i < 3; i++){array[i]=((i+1)*3);}
}
//~~~~~~~~~~~~
linkedList::listNode::~listNode()
{
}
CPP (main)
#include <iostream>
#include "linked_list.h"
using namespace std;
int main()
{
linkedList list;
int *myArray;
myArray = list.getArray();
for (int i = 0; i < 3; i++){cout << myArray[i] << " ";}/**/cout << "\n\n";
return 0;
}
The real program is meant to move through a linked list made of nodes which contain 3 integer values in an array of int type, retrieve the three values and use them as parameters for some other functions.
Now, to do so I have to return the address to the first element of the array contained in the node through an accessor.
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
Why?
I've got to this solution through trial and error with very little knowlegde of the reasons that brought me to build this expression as it is.
Usually, when you want to assign the address of an array to a pointer, you just do so:
int main()
{
int array[3];
int* pArray;
pArray = array;
}
And that's it, because the name of the array itself is enough to retrieve the address of its first element.
The exact same result can be achieved by doing this (tested):
int main()
{
int array[3];
int* pArray;
pArray = &(array[0]);
}
Both methods are also valid when the accessor returns the address from a member variable of its own class.
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
What are the logic stages that make it the only viable method?
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
You aren't:
return current->array;
and
return &(current->array[0]);
Both do the same thing when the return type is int*. You aren't forced to use the second way.
Also, there's a bug in getArray. You don't return anything if current is null.
To be pedantic...
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
You're returning the address i.e. a pointer. Reference means something else.

How to find the end of a linked list

We are creating LinkedLists in our data structures class. The following is the declaration for the class.
template <class T>
class LinkedList
{
public:
T m_data; // Data to be stored
LinkedList<T>* m_next; // Pointer to the next element in the list
// ...
};
The teacher told us which functions to implement. I am currently trying to implement this:
// Purpose: accessor function for last element node
// Returns: pointer to the last element's node in the list;
// returns NULL if list is empty
LinkedList<T>* getLastPtr();
I am not sure what code you need to see, so here is a minified version of my code which demonstrates the problem:
template <class T>
class LinkedList
{
public:
T m_data;
LinkedList<T>* m_next;
LinkedList() : m_next(NULL) {}
void insert_front(const T& x);
LinkedList<T>* getLastPtr();
}
// INSERT FRONT
template<typename T>
void LinkedList<T>::insert_front(const T& x){
LinkedList<T> *tmp;
tmp = new LinkedList<T>;
tmp->m_data = m_data;
tmp->m_next = m_next;
this->m_next = tmp;
this->m_data = x;
}
// GET LAST POINTER
template<typename T>
LinkedList<T>* LinkedList<T>::getLastPtr(){
const LinkedList<T>* runner;
const LinkedList<T>* tmp; //one behind runner
runner = this;
while (runner->m_next != NULL){
tmp = runner;
runner = runner->m_next;
cout<<"tmp: "<<tmp->m_data<<endl; //FIX DIS
cout<<"runner: "<<runner->m_data<<endl; //FIX DIS
}
return tmp->m_next;
}
We are also given a tester but for sake of simplification I will only post the section I am having issues with:
LinkedList<int> A;
//TEST : Inserting 13 numbers to a
cout << endl << "TEST : Inserting 13 numbers into A" << endl;
for (int k=0; k<13; k++){
A.insert_front(k*2);
}
// TEST : Acessing last element
cout << endl << "TEST : Acessing last element" << endl;
LinkedList<int>* p = A.getLastPtr();
cout << "Last = " << p->m_data << endl;
My issue is that when I use the function getLastPtr() it returns a bunch of random numbers. I do not know what I am doing wrong since my getAtPtr() function works properly and I am using almost identical code.
I think it has something to do with pointing to the wrong thing OR my last element isn't pointing to NULL (which should be for checking purposes).
Here you can see a demo of the problem: http://ideone.com/mDXKsV
in getLastPtr() i was going to the last element in the list which pointed to NULL. I was originally grabbing data from THAT point and therefore it was gibberish. I learned that i had to grab the element behind the Null so i made a follower to the runner, but i also cleaned up a bunch of my code especially for insert_first.

How to properly use protected in singly linked list

I've successfully programmed a singly linked list by the following program:
The header file is:
#ifndef SLL_H_
#define SLL_H_
#include <iostream>
class node {
protected:
public:
int key;
node *next;
node();
~node();
};
class SLL : public node{
private:
node *Head = NULL;
int SLL_SIZE = 0;
public:
//Constructor
SLL();
//SLL(int n);
//Destructor
~SLL();
//Modifiers
void Push_Front(int a);
void Push_Back(SLL A,int b);
void Traverse();
//Access function
int SLL_size();
int Get(node* p);
//Iterator
node* Begin();
node* End();
//void Search(int a);
};
#endif
SLL.cpp
#include "SLL.h"
#include <iostream>
using namespace std;
node::node(){
cout << "Empty constructor of node is being called;" << endl;
}
node::~node(){
cout << "Empty destructor of node is being called;" << endl;
}
SLL::SLL():node(){
cout << "Empty constructor of SLL is being called;" << endl;
}
SLL::~SLL(){
cout << "Empty destructor of SLL is being called." << endl;
}
//Insert element at the front of the list
void SLL::Push_Front(int k){
node *temp = new node [1];
temp->key = k;
temp->next = Head;
Head = temp;
SLL_SIZE = SLL_SIZE + 1;
}
//Insert element at the end of the list
void SLL::Push_Back(SLL A, int m){
node *temp1 = A.End();
node *temp2 = new node [1];
temp2->key = m;
temp1->next = temp2;
temp2->next = NULL;
SLL_SIZE = SLL_SIZE + 1;
}
//Insert element at a given position
//Return the number of elements in the linked list
int SLL::SLL_size(){
return SLL_SIZE;
}
//Traverse the list (print the list)
void SLL::Traverse(){
node *temp;
temp = Head;
while(temp!=NULL){
cout << temp->key << " ";
temp = temp->next;
}
cout << endl;
}
//Get key given pionter
int SLL::Get(node* pt){
if(pt!=NULL){
node* temp = pt;
return temp->key;
}
else {
cout << "Null pointer points to nowhere!" << endl;
return 0;
}
}
//Return the pointer at the beginning of the list
node* SLL::Begin(){
return Head;
}
//Return the pointer at the end of the list
node* SLL::End(){
node* temp = Head;
while(temp->next!=NULL){
temp = temp->next;
}
return temp;
}
main.cpp
#include <iostream>
#include "SLL.h"
using namespace std;
int main()
{
SLL A;
A.Push_Front(1);
A.Push_Front(2);
A.Push_Front(5);
A.Push_Front(6);
A.Push_Back(A,3);
A.Traverse();
cout << A.SLL_size() << endl;
cout << A.Get(A.Begin()) << endl;
cout << A.Get(A.End()) << endl;
return 0;
}
One error is, for example :
SLL.h||In member function 'void SLL::Push_Front(int)':|
SLL.h|7|error: 'int node::key' is protected|
SLL.cpp|25|error: within this context|
SLL.h|8|error: 'node* node::next' is protected|
SLL.cpp|26|error: within this context|
SLL.h||In member function 'void SLL::Push_Back(SLL, int)':|
SLL.h|7|error: 'int node::key' is protected|
SLL.cpp|35|error: within this context|
SLL.h|8|error: 'node* node::next' is protected|
LL.cpp|36|error: within this context|
SLL.h|8|error: 'node* node::next' is protected|
SLL.cpp|37|error: within this context|
Similar error for the other member functions that employed key and next.
This program works very well now. However, after I moved the 2 lines in node class, int key; node *next; under protected, then it gives me error such as "node::key is protected".
First, please don't blame me for doing something stupid :P . I know if I struct for the node then life will be much easier. I am trying to practice inheritance and to understand protected. That's why.
By definition, protected members can be accessed by derived class, right? I don't know where I am doing it wrong.
Hope you can help me out. Thanks!
The protected keyword allows an inheriting class to see the protected members. That means instances of the inheriting class can see the protected members of themselves, as well as the protected members of other instances of that same inheriting class. It does not extend this access through pointers to the parent class type, because that access isn't safe.
Let's make that concrete. Consider the following example:
class A
{
protected:
int a_int;
};
class B : public A
{
public:
int good()
{
return a_int; // OK: Protected member of this instance
}
int bad( A *a_ptr )
{
return a_ptr->a_int; // BAD: Can't access the protected member
// through a pointer to the parent class type.
}
int also_good( B *b_ptr )
{
return b_ptr->a_int; // OK: Pointer to the same class type as this
// class is safe.
}
};
The errors in your code look like the second case. So why is the second case illegal, but third case OK?
The second case is illegal because the compiler doesn't know the actual type of object the A* points to. It could be any descendent of A, and may not even be convertible to B*. Therefore, the access extended by the protected clause isn't guaranteed to be safe or meaningful. For example, suppose you had
class C : public A { ... };
class D : public C { ... };
and you passed a C* or a D* into method bad() above. It doesn't seem reasonable that B should be able to see the protected members that were exposed to C, since C and B aren't directly related. The same holds true for D.
But, in the third case, the compiler knows for certain it has a pointer to a B or a class derived from B, so it knows that the access extended by the protected keyword is safe and meaningful. By that, I mean that the protected fields are managed in the way B expects them to be managed. In fact, without that access, you would have a hard time writing binary operators involving two instances of B
Make sense?
In case you're still not convinced: Suppose I made two parallel classes, both which inherit from node:
// plain singly linked list
class normal_sll : public node { };
// singly linked list that stores all of its elements negated
class negative_sll : public node { };
Sure, it's a contrived example, but bear with me. Because both classes derive from node, you could pass either class through a node *. So, you could pass an instance of negative_sll to normal_sll or vice versa.
C++'s access control prevents either class from looking at the protected fields through that node *, though. And that's good, because negative_sll manages them differently than normal_sll.
But, you can't pass an instance of negative_sll through a normal_sll* or vice versa. So, you know if you have a normal_sll* inside one of normal_sll's methods, you know it's safe to access the protected members.
Sure, it's a contrived example. I'm sure you could think of a better one. Make sense, though?
Now you could make B a friend of A and override this control. But, this would let B see the private members of A, totally bypassing the protected concept. A better solution would be to rewrite your SLL code so that you pass SLL*, not node* to its methods.
First of all, I don't see, why you want to derive SLL from Node at all, as a List is not a specialization of a Node. What you probably want to do instead is to make SLL a friend of Node:
class node {
protected:
int key;
node *next;
public:
friend SLL; //This allows SLL to access node's private and protected members
node();
~node();
};
As far as your question - why SLL can't access Node's protected members - is concerned:
--------- EDIT: My explanation was just wrong ------------

Mixing abstract classes and templates, a recipe for disaster?

I'm having problems with the following situation. I have three classes that are involved in this mixup. List, ListNode, City. I have a List<City *>, where the list will be made up of a set of ListNode<City *> (standard wrapper around the list nodes).
City is an abstract class, so there are several classes that inherit from it that could be placed in this list and accessed polymorphically. The List class has a getHead() method which returns a pointer to a ListNode that is the head.
Any city has a population, so to access the populations, I'd expect the following to work. It's not, thus my question. I broke it down into pieces to make it simpler along the way:
ListNode<City *> *head= country->city_list->getHead();
City *headnode = *head->getNode();
cout << "Test: " << headnode->getPopulation() << endl;
getPopulation() returns an integer. country is defined as List<City*> *city; Any help on how I could figure out my problem would be greatly appreciated.
edit adding more code for better idea of what I'm working with. First, ListNode:
template <class T>
class ListNode
{
public:
ListNode() {next = 0;node = 0;};
ListNode(T *t) {node = t; next = 0;};
ListNode(const ListNode &l)
{
//long copy constructor. snip.
};
T *getNode() const { return node; }
ListNode *getNext() const { return next; };
private:
T *node;
ListNode *next;
};
Now, here is what might relevant in the List class..
template <class T>
class List
{
public:
List()
{
head = 0;
size = 0;
};
List(ListNode<T> *t)
{
head = t;
size = 1;
};
List(T *t)
{
head = new ListNode<T>(t);
size = 1;
};
List(const List<T> &t)
{
// long copy constructor. snip.
};
//bunch of irrelevent methods.
ListNode<T> *getHead() const {return head;};
List &operator+=(T &t)
{
this->insert(&t);
size++;
return (*this);
};
private:
List &insert(T *t)
{
ListNode<T> *current = head;
if (current == 0)
{
head = new ListNode<T>(t);
}
else
{
while (current->getNext() != 0)
{
current = current->getNext();
}
current->setNext(new ListNode<T>(t));
}
return (*this);
};
ListNode<T> *head;
int size;
};
I have a hunch that the process of inserting might be the problem. I insert with the List class's += operator, shown in the List implementation above. It calls the private insert method shown above, as well. It looks like this:
City *somecity = new City(x,y,z); //some parameters. integers.
*city_list += somecity; // where city_list is a List.
I think you've got a variable scoping problem.
Your ListNode class contains a pointer to the node value. Your ListNode constructor takes in a pointer to the node value and saves it.
The problem is if that pointer is to a local variable that then goes out of scope. Your ListNode's node pointer is now pointing to an object that doesn't exist. e.g. in this example
addToList(List<int>& myList)
{
int x = 3;
myList += x; // pointer to x is in the list
}
// Out of scope; x no longer exists, but myList has a pointer to it.
// Accessing this node will result in an error.
There are a couple possible remedies:
Have your ListNode contain values rather than pointers. The drawback here is that you will be making copies of the values
Implement ListNode using a reference counted smart pointer which will manager the lifetime of the object.
Well, what you could do is:
ListNode<City *>* head = new ListNode<City*>(country->city_list->getHead());
City* headnode = head->getNode();
cout << "Test: " << headnode->getPopulation() << endl;
It will take the existing City (on the memory) and put it at the head of the List node, and so on.
and if you want to copy them, maybe you could just make this:
ListNode<City *>* head = new ListNode<City*>*(new City(country->city_list->getHead()));
City* headnode = new City(head->getNode());
cout << "Test: " << headnode->getPopulation() << endl;
Hope it will help you.