C++: Error In Creating Classes [duplicate] - c++

This question already has answers here:
What are forward declarations in C++?
(8 answers)
Forward Declaration of Class, Function
(6 answers)
Closed 5 years ago.
My assignment is to create a general tree, and I decided to do this using three classes: node (contains character data, a pointer to a list ADT which contains all its children, and a pointer to another node for its own sibling nodes), list (contains all the children of a node), and the tree itself. The list is a singly linked list of nodes. The node class is supposed to be used in both the list and tree ADTs. Whenever I try to test my code in main() and see whether the classes are being created properly, I keep getting the error message "error: unknown type name 'list'". Can anyone look at my code and help me figure out how to correctly set up my classes?
//Genghis Khan
#include <iostream>
using namespace std;
class node //will be used for both list and trie ADTs
{
char character;
list* child; //all the children of the node will be stored in the list
node* sibling; //within a list, provides access to all children, functions like a "next"
friend class list;
friend class trie;
};
class list
{
private:
node* head;
node* tail;
public:
list()
{
head = new node;
tail = new node;
head->character = '*'; //head is a sentinel
tail->character = '*';
tail->sibling = head;
}
void insert(char a) //insertion into the list at the tail
{
node* v= new node;
tail->sibling = v;
v->character = a;
v->child = NULL;
tail = v;
}
int size() //so that I can use an empty() boolean
{
int size = 0;
node* temp = head;
if(temp->character != '*')
{
size += 1;
temp = temp->sibling;
}
else
{
temp = temp->sibling;
}
return size;
}
bool empty() //empty condition
{
return(size() == 0);
}
void print()
{
node* temp = head;
while(temp->character != '*' and temp != tail)
{
cout << temp->character;
temp = temp->sibling;
}
}
friend class trie;
friend class node;
};
class trie
{
private:
node* root;
public:
trie()
{
root = new node;
root->character = '*'; //sentinel
root->child = NULL; //to be changed when we add children
root->sibling = NULL; //will never change
}
bool haschildren(node* v)
{
return(v->child != NULL);
}
};
int main()
{
list a;
a.insert('G');
a.insert('e');
a.insert('n');
a.insert('g');
a.insert('h');
a.insert('i');
a.insert('s');
a.print();
}
As a note, I tried making "node" a struct instead of a class, but that did not help.

Related

Can you help me debug this c++ program which is supposed to add a node at the end in circular single linked list and print the list?

Can you help me debug this c++ program which is supposed to add a node at the end in circular single linked list and print the list?
using namespace std;
class Node
{
public:
int data;
Node* next;
Node(int x)
{
data = x;
next = NULL;
}
};
class Lfun
{
public:
virtual void addLast(int x) = 0;
virtual void display() = 0;
virtual ~Lfun(){};
};
class List :public Lfun{
private:
Node* head;
Node* curr;
public:
List()
{
head = NULL;
curr = NULL;
}
void addLast(int x)
{
Node *tmp = new Node(x);
tmp->next = head;
if (head == NULL)
{
head = tmp;
}
else
{
curr = head;
while (curr->next != NULL)
{
curr = curr->next;
}
curr->next = tmp;
}
}
void display()
{
curr = head;
for (int i = 0; i < 5; i++)
{
cout << curr->data << " ";
}
}
};
int main()
{
List* ll = new List();
for (int i = 0; i < 5; i++)
{
cout << i;
ll->addLast(i);
ll->display();
}
}
I have created a class 'Node' to create a node for the linked list and another class 'Lfun' to redefine all the functions in the child class ,that is 'List'.
The program is not giving any output, can you explain why that is happening and how I can fix that problem?
Your main problem is this line in List:
tmp->next = head;
With that line, you ensure that the last Node's next will never be NULL, but point back at head, giving you a circular list.
In your while-loop you loop until you find a next member that is NULL, but due to the above problem, this will loop forever.
Your display function is also broken, as it prints the first element 5 times without advancing curr. Another thing is that curr should really not be a member variable, but rather a local variable in functions where it is used.
Also note that in c++, you should use nullptr, not NULL

Building a Linked-List with another Struct - Append Function runtime error

First whack at learning pointers, I'm trying to follow all of this and I thought I had it right but alas I am getting a runtime error when calling the append function. The CSV function appears to be working. I'm guessing I've messed up the Append flow. Any tips or advise is warmly welcomed.
struct Car {
string carId; // unique identifier
string title;
};
class LinkedList {
private:
struct node {
Car cars;
node *next; //is this storing the memory address of the struct?
};
// alias for node pointer (memory address of node)
typedef struct node* nodePtr;
// defining pointer variables for memory positions in the List
nodePtr head;
nodePtr curr;
nodePtr temp;
nodePtr tail; //is this needed
public:
LinkedList();
void Append(Car car);
};
//Default constructor
LinkedList::LinkedList() {
head = NULL;
curr = NULL;
temp = NULL;
tail = NULL;
}
void LinkedList::Append(Car car) {
nodePtr n = new node;
n->cars = car;
n->next = NULL;
if (head == NULL){
head = n;
tail =n;
}
else {
tail->next = n;
tail=n;
}
}
void loadCars(string csvPath, LinkedList *list) {
csv::Parser file = csv::Parser(csvPath);
try {
// loop to read rows of a CSV file
for ( unsigned int i = 0; i < file.rowCount(); i++) {
// initialize a bid using data from current row (i)
Car car ;
car.carId = file[i][1];
car.title = file[i][0];
// add this bid to the end
list->Append(car);
}
}
}
int main(int argc, char* argv[]) {
LinkedList carlist
csvPath = xyz;
loadCars(csvPath, &carlist);
}

Converting Single Liked List to a Doubly Linked List using class inheritance

I managed to create the single linked list using the following class named node:
class node
{
protected:
int info; //value
int lenght;
node *next;
node *head;
};
(In public I have the working funcitons). And the other class double_node:
class double_node : public node
{
protected : node *prev;
};
My issue here is using the add function in the double_node class, where I have two problems (modified it alteast 10 times but I'll post the one with all errors I got, because I'm not sure the other versions fixed any of them):
void add (int x){
double_node *p = new double_node(x); // constructor makes next = NULL & info = x
if (head == NULL)
{
p->prev = NULL;
head = p;
}
else
{
double_node* q = head; //#1st issue, no idea how to initialize a pointer with head
while (q->next!= NULL)
{
q = q->next; //#2nd issue
}
q->next= p;
p->prev= q;
}
}
Both errors are : invalid conversion from 'node*' to 'double_node*' [-fpermissive].
Any ideeas to fix this? Or maybe another way to create the doubly linked list?
Thanks in advance!
Note: posted it on code review but I was told it would fit better here.
Declaring a node* instead of a double_node* in add function should suffice.
You can always assign a pointer to a subclass to its ancestor, but the opposite is not valid.
Something like the following should suffice:
void add (int x){
node *p = new double_node(x);
if (head == NULL)
{
head = p;
}
else
{
node* q = head;
while (q->next!= NULL)
{
q = q->next; //#2nd issue
}
q->next= p;
static_cast<double_node*>(p)->prev= q;
}
}

Search and protecting singly linked list in C++

I have one questions regarding searching elements on a Singly Linked List of ints, in this case, using C++. I'm creating my own version of list for exercising. This is the code
Let's suppose I have two search functions. I know we need to traverse the entire list until find the element because we don't have direct access like arrays.
The two functions are:
bool search(int n); // Traverse the list till find n.
bool search(Node* node, int n); Traverse the list till find n only after *node (included)
1 case: My list has the following elements: [0, 1, 2, 3]
If I search for 3 I easily find at the end of the list. Nice.
QUESTIONS:
2 case: My list has the following elements: [0, 1, 2, 3, 3, 3, 4, 5, 6]
If I search for 3 with:
bool search(int n);
I'm going to get the first 3 element always, except if I have a reference to the second or third 3 element to pass to that function:
bool search(Node* node, int n);
My questions is if that is the correct search algorithm in a singly linked list. The two types of functions or if I should have other types.
Bellow is the code for my actual code (I didn't put the code for searching):
SingleLinkedList.h
struct Node {
int data;
Node* next;
Node(int d = 0)
: data {d}, next {nullptr}
{}
};
class SinglyLinkedList {
public:
SinglyLinkedList();
~SinglyLinkedList();
void display();
bool addFirst(const int); // Add a node to the beginning of the list.
bool addFirst(Node*); // Add a node to the beginning of the list.
bool addLast(const int); // Add a node to the end of the list.
bool addLast(Node*); // Add a node to the end of the list.
private:
Node* head;
Node* tail;
};
SinglyLinkedList.h
#include "SinglyLinkedList.h"
#include <iostream>
SinglyLinkedList::SinglyLinkedList()
: head {nullptr}, tail {nullptr}
{}
SinglyLinkedList::~SinglyLinkedList() {
Node* iterationNode = head;
Node* actualNode {nullptr};
while (iterationNode != nullptr) {
actualNode = iterationNode;
iterationNode = iterationNode->next;
delete actualNode;
}
}
void SinglyLinkedList::display() {
std::cout << "################### Displaying Linked List ###################" << std::endl;
if (head == nullptr) {
std::cout << "Linked List is empty!" << std::endl;
}
else {
Node* iterationNode = head;
std::cout << "[ ";
while (iterationNode != nullptr) {
std::cout << iterationNode->data << " ";
iterationNode = iterationNode->next;
}
iterationNode = nullptr;
std::cout << "]" << std::endl;
}
std::cout << "##############################################################" << std::endl;
}
bool SinglyLinkedList::addFirst(const int n) {
Node* element = new Node {n};
if (head == nullptr) {
head = element;
tail = element;
}
else {
element->next = head;
head = element;
}
return true;
}
bool SinglyLinkedList::addFirst(Node* element) {
if (head == nullptr) {
head = element;
tail = element;
}
else {
element->next = head;
head = element;
}
return true;
}
bool SinglyLinkedList::addLast(const int n) {
Node* element = new Node {n};
if (head == nullptr) {
head = element;
tail = element;
}
else {
tail->next = element;
tail = element;
}
return true;
}
bool SinglyLinkedList::addLast(Node* element) {
if (head == nullptr) {
head = element;
tail = element;
}
else {
tail->next = element;
tail = element;
}
return true;
}
Program.cpp
#include <iostream>
#include "SinglyLinkedList.h"
int main() {
{
SinglyLinkedList list;
list.display();
list.addFirst(5);
list.addFirst(4);
list.addFirst(3);
Node* secondNode = new Node {2};
list.addFirst(secondNode);
Node* firstNode = new Node {1};
list.addFirst(firstNode);
Node* zeroNode = new Node;
list.addFirst(zeroNode);
list.addLast(6);
list.display();
}
system("pause");
}
Another question is, how can I protect my struct in a way the user of the program can not mess up changing the links/references directly. For example, in the Program.cpp, any programmer could simply do this:
secondNode->next = zeroNode
The answer to your first question depends on what you need. If you are doing this as a learning project, implement whatever you see fit. What you have described is appropriate for search by value.
The best way to prevent users from directly accessing your Node members in cases like this is to completely abstract the Node type away. You can do this simply by declaring and defining Node in your source file and use forward declarations of Node* in your header. Users who include your header will then not have any notion of your Node type whatsoever.
// SinglyLinkedList.h
class SinglyLinkedList {
//...//
struct Node* head; // head node is forward declared
//...//
}
// SinglyLinkedList.cc
struct Node {
//...
};
// define ll methods
If you do want the user to know about the Node type, one solution is to make its members private, create a public value accessor method, and make the Node a friend of the SinglyLinkedList class.

C++ classes & linked list: adding & counting items

I need to make a linked list with classes. Each list will store two values: a URI and IP. After doing all the adding, I need to be able count the total number of items in the linked list. I have tried the following code but it doesn't compile. We are not allowed to use std::list. Any suggestions please?
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
class ip_uri_store {
protected:
string ip;
string uri;
ip_uri_store *next;
public:
ip_uri_store(string huri, string hip);
void additem(string auri, string aip);
void deleteitem(string duri);
void findbyuri(string furi);
void findbyip(string fip);
int totalitems();
};
ip_uri_store *head = NULL;
ip_uri_store *curr = NULL;
void ip_uri_store::additem(string auri, string aip)
{
curr = head;
while (curr->next != NULL) {
curr = curr->next;
}
curr->uri = auri;
curr->next = new ip_uri_store;
curr->ip = aip;
curr->next = new ip_uri_store;
curr = curr->next;
curr = head;
}
int ip_uri_store::totalitems()
{
int i = 0;
curr = head;
while (curr->next != NULL) {
i += 1;
curr = curr->next;
}
return i;
}
int main(int argc, char *argv[])
{
if (argc == 1) {
cout << "123456, 123456#student.rmit.edu.au, Gordon Brown" << endl;
return (0);
}
head = new ip_uri_store;
curr = head;
int i;
for (i = 1; i < argc; i++) {
if (argv[i][0] == 'A') //add item
{
ip_uri_store.additem(argv[i + 1], argv[i + 2]);
i += 2;
}
else if (argv[i][0] == 'N') //print total tiems
{
cout << ip_uri_store.totalitems() << endl;
}
else {
cout << "command error\n";
return 0;
}
}
return (0);
}
Your ip_uri_store::additem() is pretty messed up. In it you change the curr object before you assign a new value to it:
curr->uri = auri;
curr->next = new ip_uri_store;
In doing so you change the last item in the list instead of assigning auri to the new item added later. (Interestingly, you got the order right with ip.)
I like the idea of giving pieces of code names, so that you can read what they do. Functions are what this is done with. For example, I'd factor out the code that finds the last list node
ip_uri_store *find_last_node(ip_uri_store *curr)
{
while (curr->next != NULL) {
curr = curr->next;
}
return curr;
}
and call it from ip_uri_store::additem():
void ip_uri_store::additem(string auri, string aip)
{
ip_uri_store *curr = find_last_node(head);
// ...
Now create a new object and remember its address in curr->next
// ...
curr->next = new ip_uri_store(auri,aip);
}
Your ip_uri_store::totalitems() returns an int. Why? Do you ever expect the count of objects to be negative? Better return an unsigned type.
You should consider what happens when you delete a list node. If it still points to a next object, chances are the pointer isn't stored anywhere else, and so the object (and those it points to) is (are) leaking. One way to deal with that is to write a destructor for ip_uri_store which deletes next. (If you want to delete a node without having it delete its own tail, you could assign NULL to its next pointer first.)
Also, according to the Rule of Three, you need to think about copying of list nodes. That's not easy to get right in the first try, so you might just want to forbid it:
class ip_uri_store {
private:
ip_uri_store(const ip_uri_store&); // not implemented
ip_uri_store& operator=(const ip_uri_store&); // not implemented
// ...
Instead of using global variables, you put them into class. That way you could have more than one list. Rename ip_uri_store to ip_uri_store_impl and pout it into a new ip_uri_store class:
class ip_uri_store {
private:
class ip_uri_store_impl { /* ... */ };
ip_uri_store_impl* head;
};
Since this class manages dynamically allocated objects, you need to think about destruction and copying such objects.
The wrapper class should have public methods that invoke the methods of ip_uri_store_impl whenthey nedd to. Functions like totalitems(), which operate on the whole list (instead of a node), should probably be implemented in the wrapper class.
You need to provide the two arguments to the constructor of your ip_uri_store class:
// The constructor call needs two arguments
curr->next = new ip_uri_store(huri, hip);
You cannot call instance methods on the class itself:
// Invalid, totalitems() is valid only on instances of ip_uri_store.
cout << ip_uri_store.totalitems() << endl;
Why are the variables head and curr global? They really should be data members of a class.
Pull out the ip, uri and next members of ip_uri_store and put them in their own structure, say ip_uri_store_node. Then, ip_ur_store_node can define a constructor that initializes them. Then make ip_uri_store hold the head and curr pointers to ip_uri_store_node instances.
This is what I mean:
struct ip_uri_store_node
{
string ip;
string uri;
ip_uri_store_node* next;
ip_uri_store_node(const char* u, const char* i)
: ip(i), uri(u), next(0) {}
};
class ip_uri_store
{
private:
ip_uri_store_node* head;
ip_uri_store_node* curr;
public:
// Initializes head and curr
ip_uri_store();
// These functions woud act on head and curr.
void additem(string auri, string aip);
void deleteitem(string duri);
void findbyuri(string furi);
void findbyip(string fip);
int totalitems();
};
int main()
{
ip_uri_store list;
// Do things with the list...
return 0;
}
The function additem can create new instances of ip_uri_store_node like this:
curr->next = new ip_uri_store_node(auri, aip);
The rest is up to you.