So far I have created a simple linked list project that I will build on in the future. All files compile correctly but when I try to build my project it comes up with a link error. I used an empty project to start. The main.cpp is used to demo that my linked list actually works. I'm really stuck and don't know how to solve this issue.
Main.cpp
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include "LinkedList.cpp"
#include "LinkedList.h"
using namespace SDI;
template <class T>
int LinkedList<T>::main()
{
LinkedList<T> menu;
menu.insert(1);
menu.insert(4);
menu.insert(7);
menu.insert(2);
menu.insert(8);
menu.display();
Std::cout << "-----" << endl;
menu.remove(2);
menu.remove(1);
menu.remove(10);
menu.display();
return 0;
};
header file LinkedList.h
#ifndef SDI_LL
#define SDI_LL
namespace SDI
{
template < class T >
class LinkedList
{
class Node
{
int number;
Node* next;
};
private:
T head;
T current;
T temp;
public:
LinkedList();
~LinkedList();
int main();
void insert(int add);
void remove(int remove);
void display();
};
}
#endif
LinkedList.cpp
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include "LinkedList.h"
using namespace SDI;
template <class T>
LinkedList<T>::LinkedList()
{
head = NULL;
current = NULL;
temp = NULL;
};
template <class T>
void LinkedList<T>::insert(int add)
{
newnode = new Node;
newnode->next = NULL;
newnode->number = add;
if (head != NULL)
{
current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
else
{
head = newnode;
}
};
template <class T>
void LinkedList<T>::remove(int remove)
{
remove1 = NULL;
temp = head;
current = head;
while (current != NULL && current->add != remove)
{
temp = current;
current = current->next;
}
if (current == NULL)
{
std::cout << "N/A\n";
delete remove1;
}
else
{
remove1 = current;
current = current->next;
temp->next = current;
if (remove1 == head)
{
head = head->next;
temp = NULL;
}
delete remove1;
}
};
template <class T>
void LinkedList<T>::display()
{
current = head;
while (current != NULL)
{
std::cout << current->number;
current = current->next;
}
};
You need a global main() function in your program, not the static version from LinkedList. The main function is called the entry point, and a quick lookup of the error message tells you this.
http://en.cppreference.com/w/cpp/language/main_function
Something along the lines of this might work:
int main()
{
LinkedList<int> menu;
menu.insert(1);
menu.insert(4);
menu.insert(7);
menu.insert(2);
menu.insert(8);
menu.display();
Std::cout << "-----" << endl;
menu.remove(2);
menu.remove(1);
menu.remove(10);
menu.display();
return 0;
};
Currently, you define a completely unrelated "main" function inside your class. This is just a plain normal function of your class and in no way related to the previously mentioned int main() entry point function.
Related
I can't specify what the problem is nor do I get any errors. This is my code:
Node.h:
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
template <typename T>
class LinkedList;
template <typename T>
class Node {
public:
Node(T data) : data(data),previousNode(nullptr),nextNode(nullptr) {}
Node<T>* GetNextNode() const {
return nextNode;
}
void SetNextNode(Node<T>* nextNode) {
this->nextNode = nextNode;
}
Node<T>* GetPreviousNode() const {
return previousNode;
}
void SetPreviousNode(Node<T>* previousNode) {
this->previousNode = previousNode;
}
T GetData() const {
return data;
}
void SetData(T data) {
this->data = data;
}
private:
T data;
Node<T>* previousNode;
Node<T>* nextNode;
};
#endif /* NODE_H */
linkedList.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "node.h"
#include <stdexcept>
#include <iostream>
#include <booking.h>
using namespace std;
template<typename T>
class LinkedList {
public:
LinkedList() {
root = nullptr;
end = nullptr;
cursor = end;
}
void insertNode(T data) {
Node<T>* node = new Node<T>(data);
cerr << "entered insert node" << endl;
if (root == nullptr) {
root = node;
node->SetNextNode(end);
end->SetPreviousNode(node);
}else{
node->SetNextNode(cursor);
node->SetPreviousNode(cursor->GetPreviousNode());
if (cursor->GetPreviousNode())
cursor->GetPreviousNode()->SetNextNode(node);
cursor->SetPreviousNode(node);
}
cursor = node;
if (!cursor->GetPreviousNode())
root = cursor;
}
bool isAtEnd() {
return (cursor == end);
};
void step_back() {
if (cursor && cursor->GetPreviousNode()) {
cursor = cursor->GetPreviousNode();
}
}
void advance() {
if (cursor && cursor->GetNextNode()) {
cursor = cursor->GetNextNode(); }
};
T getNode() {
return cursor->GetData();
};
void reset() {
cursor = root;
};
void deleteNode() {
Node<T>* tmpPrevious;
Node<T>* tmpNext;
if (root == nullptr) {
throw underflow_error("empty list...");
} else {
if (cursor->GetPreviousNode() == nullptr) {
if (cursor->GetNextNode() == end) {
delete cursor;
root = nullptr;
end->SetPreviousNode(nullptr);
cursor = end;
} else {
cursor = cursor->GetNextNode();
delete (root);
cursor->SetPreviousNode(nullptr);
root = cursor;
}
} else {
if (cursor->GetNextNode() == end) {
tmpPrevious = cursor->GetPreviousNode();
delete cursor;
cursor = end;
end->SetPreviousNode(tmpPrevious);
tmpPrevious->SetNextNode(end);
} else {
tmpPrevious = cursor->GetPreviousNode();
tmpNext = cursor->GetNextNode();
delete cursor;
tmpPrevious->SetNextNode(tmpNext);
tmpNext->SetPreviousNode(tmpPrevious);
cursor = tmpNext;
}
}
}
return;
};
protected:
Node<T>* root;
Node<T>* cursor;
Node<T>* end;
};
#endif /* LINKEDLIST_H */
Booking.h
#ifndef BOOKING_H
#define BOOKING_H
class Booking{
private:
long bookingID;
public:
Booking(long bookingID);
long getBookingID();
};
#endif // BOOKING_H
Booking.ccp:
#include "booking.h"
Booking::Booking(long bookingID):bookingID(bookingID){}
long Booking::getBookingID(){
return bookingID;
}
main.cpp:
#include <QCoreApplication>
#include <cstdlib>
#include <linkedList.h>
#include <iostream>
#include <string>
#include <booking.h>
using namespace std;
int main(int argc, char *argv[]){
QCoreApplication a(argc, argv);
LinkedList<Booking*> allBookings;
Booking* booking1 = new Booking(12);
allBookings.insertNode(booking1);
long test = allBookings.getNode()->getBookingID();
cout << "test: " << test << endl; //doesn't print anything
return a.exec();
}
I didn't get any errors. cout << "test: " << test << endl; in the main.cpp doesn't execute, because I was expecting it to print something. What am I doing wrong here? I did some debugging and I think in my Node.h implementation the function SetPreviousNode doesn't execute when I'm trying to insert a node in the main.cpp.
This code in insertNode
if (root == nullptr) {
root = node;
node->SetNextNode(end);
end->SetPreviousNode(node);
}else{
end has a value of nullptr at when you reach end->SetPreviousNode(node); which is likely crashing your program. (You should be able to confirm that in your debugger).
I'd like to suggest a fix but it's not clear to me what you are trying to do. The code seems a little complex. Plus I don't like the design decision to include a cursor in the list. I would drop that if you are able to.
I created at doubly link list and want to test out my count function within list class.
the count function is given with a pointer to an abitrary node and count how many nodes in the list.
the problem I have right now is to set up an variable/object that I can put it in count function parameter in main(). For example, the pointer can be pointing the middle node in the list. basically any random node that user might be pointing such as head->next-next or tail->prev->prev in the list.
#include "pch.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <cmath>
#include <string>
using namespace std;
template <class T>
class node {
public:
T data;
node<T> *next;
node<T> *prev;
//node() {};
node(T newdata):data(newdata){ next = nullptr; prev = nullptr; }
};
template <class T>
class list {
node<T> *head;
node<T> *tail;
public:
list() { head = nullptr; tail = nullptr; }
void insert_head(int newval) {
node<T> *curr = new node<T>(newval);
if (head == nullptr) {
head = tail = curr;
return;
}
tail->next = curr;
curr->prev = tail;
tail = curr;
return;
}
void print() {
node<T>*curr = head;
while (curr != nullptr) {
cout << curr->data << endl;
curr = curr->next;
}
}
int count(node<T>* rannode) {
int count = 0;
node<T> *tohead = rannode;
node<T> *totail = rannode;
while (totail->next != nullptr) {
count++;
totail = totail->next;
}
while (tohead != nullptr) {
count++;
tohead = tohead->prev;
}
return count;
}
};
int main() {
list<int> test;
test.insert_head(1);
test.insert_head(2);
test.insert_head(3);
test.insert_head(4);
test.insert_head(5);
test.print();
test.count(??)
return 0;
}
``` ``` ``` ``` ``` ``` ``` ``` ``` ``` ``` ```
I am trying to make a linked list and test it in c++ using nodes. I create six nodes and then I print them forward and backwards like this:
main.cpp
#include "LinkedList.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void TestAddHead();
int main()
{
TestAddHead();
system("pause");
return 0;
}
void TestAddHead()
{
cout << "Testing AddHead()" << endl;
LinkedList<int> data;
for (int i = 0; i < 12; i += 2)
data.AddHead(i);
cout << "Node count: " << data.NodeCount() << endl;
cout << "Print list forward:" << endl;
data.PrintForward();
cout << "Print list in reverse:" << endl;
data.PrintReverse();
}
LinkedList.h
#pragma once
#include <iostream>
#include <vector>
#include <array>
#include <stdexcept>
#include <string>
using namespace std;
template<typename T>
class LinkedList
{
public:
struct Node
{
T data_;
Node* next;
Node* previous;
};
void PrintForward() const;
void PrintReverse() const;
unsigned int NodeCount() const;
void AddHead(const T &data);
LinkedList();
LinkedList(const LinkedList<T> &list);
~LinkedList();
private:
Node* head = new Node;
Node* tail = new Node;
unsigned int count = 0;
};
template<typename T>
LinkedList<T>::LinkedList()
{
}
template<typename T>
LinkedList<T>::LinkedList(const LinkedList<T> &list)
{
}
template<typename T>
LinkedList<T>::~LinkedList()
{
}
template<typename T>
void LinkedList<T>::AddHead(const T &data)
{
Node* newNode = new Node;
newNode->data_ = data;
if (count == 0)
{
head = newNode;
tail = newNode;
head->next = nullptr;
head->previous = nullptr;
}
else
{
newNode->next = head;
head->previous = newNode;
head = newNode;
}
count = count + 1;
}
template<typename T>
void LinkedList<T>::PrintForward() const
{
Node* currentNode = head;
while (currentNode != nullptr)
{
cout << currentNode->data_ << endl;
currentNode = currentNode->next;
}
}
template<typename T>
void LinkedList<T>::PrintReverse() const
{
Node* currentNode2 = tail;
while (currentNode2 != nullptr)
{
cout << currentNode2->data_ << endl;
currentNode2 = currentNode2->previous;
}
}
template<typename T>
unsigned int LinkedList<T>::NodeCount() const
{
return count;
}
this should be the output of the program:
Testing AddHead()
Node count: 6
Print list forward:
10
8
6
4
2
0
Print list in reverse:
0
2
4
6
8
10
The program works and gives me the correct output but the problem is that it just crashes when it reaches the "10" at the bottom of the program and I don't know why, can anyone tell me why is this happening and a possible way to fix it? thank you
Your immediate problem, you never set the new node previous pointer to nullptr ( a problem that honestly should be rectified by a better constructed loop and/or a proper constructor for Node). Regardless, here...
template<typename T>
void LinkedList<T>::AddHead(const T &data)
{
Node* newNode = new Node;
newNode->data_ = data;
if (count == 0)
{
head = newNode;
tail = newNode;
head->next = nullptr;
head->previous = nullptr;
}
else
{
newNode->next = head;
newNode->previous = nullptr; // ADD THIS
head->previous = newNode;
head = newNode;
}
count = count + 1;
}
There are still several things wrong in this: memory leaks, empty copy-ctor and destructor, etc, but the above is the root of the current evil. That line could also be:
newNode->previous = head->previous;
but frankly that just confuses what you're doing. You're always landing your new nodes at the head of the list, so the previous member of said-same will always be nullptr (at least until you start studying circular lists).
I'm trying to make a unidirectional list with nodes containing a value and a pointer to the next node (the pointer in the final node is supposed to be a nullptr).
Howerver, things are not going as planed. It's compiling without any problems, but when I try to run it i get this fatal error condition:
SIGSEGV - Segmentation violation signal.
It think it's trying to reach memory which it doesn't have permission to use, or something? Another common cause is an accidental "=" instead of "==", but that doesn't seem to be the problem here.
It seems that the error occurs when I try to construct a Sorted_List without any nodes in my test file, like this:
Sorted_List empty_list{};
Here is the code I imagine can be relevant to the error:
Sorted_List.cc
#include "Sorted_list.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
Sorted_List::Sorted_List() : head{nullptr} {}
Sorted_List::Sorted_List(initializer_list<int> i)
:Sorted_List()
{
for (auto ii : i)
{
add_val(ii);
}
}
Sorted_List::~Sorted_List()
{
if (!check_empty())
{
Node* del = head;
while(del != nullptr)
{
Node* next = del->next;
delete del;
del = next;
}
}
}
bool Sorted_List::check_empty() const
{
return (head->value == 0 && head->next == nullptr);
}
void Sorted_List::del_val(int num)
{
Node* del = head;
if (num == 1)
{
head = del->next;
delete del;
}
for (int i = 1; i < num - 1; i++)
{
del = del->next;
}
}
void Sorted_List::add_val(int num)
{
Node* temp = new Node;
temp->value = num;
if (head == nullptr || head->value >= temp->value)
{
temp->next = head;
head = temp;
}
else
{
Node* current = head;
while(current->next != nullptr && current->next->value <temp->value)
{
current = current->next;
}
temp->next = current->next;
current->next = temp;
}
}
string Sorted_List::print( Sorted_List& list)
{
Sorted_List::Node* temp;
stringstream list_stream;
for(temp = list.head; temp != nullptr; temp = temp->next)
{
list_stream << temp->value;
if(temp->next != nullptr)
list_stream << ", ";
}
return list_stream.str();
}
Sorted_List.h
#ifndef SORTED_LIST_H
#define SORTED_LIST_H
#include <string>
#include <iostream>
#include <initializer_list>
#include <string>
class Sorted_List
{
private:
class Node
{
public:
int value{};
Node* next{};
};
Node* head{};
public:
Sorted_List();
Sorted_List(std::initializer_list<int>);
~Sorted_List();
std::string print(Sorted_List&);
void add_val(int num);
bool check_empty() const;
void del_val(int num);
};
#endif
Sorted_List_test.cc
#define CATCH_CONFIG_MAIN
#include "Sorted_list.h"
#include "catch.hpp"
#include <iostream>
#include <string>
using namespace std;
TEST_CASE(" EMPTY ")
{
Sorted_List empty_list{}; // this is where the error occurs
//REQUIRE(empty_list.check_empty() == true);
//REQUIRE(empty_list.print(empty_list) == "");
}
Any clues?
If you use a debugger you will see that the crash happens when the empty_list object is destructed. More precisely in the check_empty function called from the destructor.
This is because the default constructor sets head to a null pointer, and then in the check_empty you dereference this null pointer.
Your check_empty function should check if head is a null pointer.
I've been trying to rewrite some basic data structures using C++ to refresh my memory on some of the basics of OOP, but I've run into a silly problem already.
I'm trying to build a singly linked list, append the strings "Hello" and "World" to the list, and then view all of the contents within the list. This is a very easy task, but I'm getting a segmentation fault when I run the following code:
driver.cc
#include <iostream>
#include <string>
#include "SinglyLinkedList.h"
int main()
{
SLL<std::string> List;
List.Append("Hello");
List.Append("World");
List.visitAll(std::cout);
return 0;
}
Node.h
#ifndef NODE_H
#define NODE_H
template <class T>
class Node {
public:
Node<T>() {}
Node<T>(T init) { data = init; next = nullptr; }
void setData(T newData) { data = newData; }
void setNext(Node<T> *nextNode) { next = nextNode; }
const T getData() { return data; }
Node<T> *getNext() { return next; }
private:
T data;
Node<T> *next;
};
#endif
SinglyLinkedList.h
#ifndef SINGLY_LINKEDLIST_H
#define SINGLY_LINKEDLIST_H
#include "Node.h"
#include <iostream>
template <class T>
class SLL {
public:
SLL<T>() { head = nullptr; size = 0; }
~SLL<T>() {}
void Append(T added);
void Delete(T deleted);
void visitAll(std::ostream &outs);
private:
Node<T> *head;
long size;
};
template <class T>
void SLL<T>::Append(T added)
{
Node<T> *newNode = new Node<T>(added);
Node<T> *temp = head;
if(temp != nullptr) {
while(temp != nullptr) {
temp = temp->getNext();
}
temp->setNext(newNode); // seg fault here
}
else {
head = newNode;
}
}
template <class T>
void SLL<T>::visitAll(std::ostream &outs)
{
Node<T> *temp = head;
while(temp)
{
outs << temp->getData() << std::endl;
temp=temp->getNext();
}
}
#endif
Just debugging by hand, I create a new node with data = "Hello" and next = nullptr. This gets appended by the else in the void SLL<T>::Append method because temp == nullptr. However, on the second Append, the while loop runs once, then crashes when calling the setter of the Node class. I cannot figure out why this is the case.
I'm expecting to see
Hello
World
Am I being too tunnel-visioned? This is pretty silly. Sorry if it's too basic for SO...
Thanks,
erip
while(temp != nullptr) {
temp = temp->getNext();
}
temp->setNext(newNode); // seg fault here
That's because you are breaking out of the while loop when temp == nullptr.
Use:
while(temp->getNext() != nullptr) {
temp = temp->getNext();
}
temp->setNext(newNode);
Your while loop in Append ends with temp being a null pointer, therefore no temp->setNext()