I get the "Debug assertion failed" error when my program ends. I've been trying to fix it for a long time and just can't find the cause. Even my prof in uni said he sees nothing wrong. So you are my last hope, stackoverllow. Please help.
The program finds the intersection of two lists and then checks if the third list is a subset of the intersection.
The screenshot of the error:
The code:
list.h:
#ifndef __LIST_H_INCLUDED__
#define __LIST_H_INCLUDED__
#include <string>
#include <iostream>
#include <fstream>
struct node
{
int value;
node *next;
};
class list
{
node* head;
public:
list();
~list();
void AddNodes(std::istream &input);
void PrintList(std::ostream &output = std::cout);
void AddOneNode(int AddVal);
node* RetHead();
list* Intersection(list* list2);
bool IsPresent(int val);
bool Subset(list subset);
};
#endif
list.cpp:
#include "stdafx.h"
#include "list.h"
#include <iostream>
#include <fstream>
list::list()
{
head=NULL;
}
list::~list()
{
node* current = head;
while( current != 0 )
{
node* next = current->next;
delete current;
current = next;
}
head = 0;
}
void list::AddNodes(std::istream &input)
{
int InVal;
while(input>>InVal)
AddOneNode(InVal);
}
void list::AddOneNode(int AddVal)
{
node *NewNode= new node;
NewNode->value=AddVal;
NewNode->next=NULL;
if(!head)
head=NewNode;
else
{
node *temp=head;
while(temp->next)
temp=temp->next;
temp->next=NewNode;
}
}
void list::PrintList(std::ostream &output)
{
node *temp=head;
while(temp)
{
output<<temp->value<<std::endl;
temp=temp->next;
}
}
list* list::Intersection(list *list2)
{
list* result=new list;
node* temp1=head;
while(temp1)
{
if(list2->IsPresent(temp1->value))
result->AddOneNode(temp1->value);
temp1=temp1->next;
}
return result;
}
bool list::IsPresent(int val)
{
node *temp=head;
while(temp)
{
if(temp->value==val)
return true;
temp=temp->next;
}
return false;
}
bool list::Subset(list subset) // head=set
{
bool flag;
node* tempset=head;
node* tempsub=subset.RetHead();
while(tempset)
{
if (tempsub->value==tempset->value)
{
flag=true;
break;
}
tempset=tempset->next;
}
if (!tempset)
return false;
while(tempsub)
{
tempsub=tempsub->next;
if(!tempsub)
return true;
while(tempsub->value!=tempset->value&&tempset)
tempset=tempset->next;
if(!tempset)
return false;
}
return flag;
}
node* list::RetHead()
{
return head;
}
main.cpp:
#include "stdafx.h"
#include "list.h"
#include <Windows.h>
#include <fstream>
list Cross (list list1, list list2);
bool Subset (list set, list subset);
int main()
{
setlocale (LC_ALL, "Russian");
list l1,l2,l3;
std::ifstream fl1 ("l1.txt");
std::ifstream fl2 ("l2.txt");
std::ifstream fl3 ("l3.txt");
l1.AddNodes(fl1);
std::cout<<"List 1:"<<std::endl;
l1.PrintList();
std::cout<<std::endl;
l2.AddNodes(fl2);
std::cout<<"List 2:"<<std::endl;
l2.PrintList();
std::cout<<std::endl;
l3.AddNodes(fl3);
std::cout<<"List 3:"<<std::endl;
l3.PrintList();
std::cout<<"Intersection of list 1 and list 2"<<std::endl;
list *intersec=l1.Intersection(&l2);
intersec->PrintList();
std::cout<<std::endl;
if(intersec->Subset(l3))
std::cout<<"Third set is a subset of the intersection"<<std::endl;
else
std::cout<<"Third set is not a subset of the intersection"<<std::endl;
system("pause");
return 0;
}
The problem is that the function list::Subset(list subset) takes its argument by value causing a copy of the list to be made. Since you did not follow the Rule of Three (as noted in Chris' comment) a shallow copy is made. This means that two instance of list "own" the pointers. When the Subset function returns the copy goes out of scope causing the nodes to be deleted. When the program exits the original copy of the list goes out of scope and it attempts to delete the same nodes again causing the assertion.
You can get around this by taking the argument by reference instead of by value. Change
class list
{
// ... snip ...
bool Subset(list subset);
// ... snip ...
};
to
class list
{
// ... snip ...
bool Subset(list& subset);
// ... snip ...
};
and
bool list::Subset(list subset)
{
// ... snip ...
}
to
bool list::Subset(list& subset)
{
// ... snip ...
}
Some other suggestions:
Either implement a proper copy constructor or declare one and make it private to prevent copies from being made
Learn const correctness. Since Subset does not modify the contents of the list passed to it you can declare it bool list::Subset(const list&) const instead. This will require list::RetHead() to be declared const as well.
bool flag in list::Subset is not initialized meaning that any value can be returned if your logic is not correct.
Related
So I understood how to print a single linked list in reverse order using recursion. I'm having trouble with doing it non member functions.
For example in int print_reverse(IntSLList & list)) function how do you print reverse in an iterative way?
************************ .h file **************************
class IntSLLNode {
public:
IntSLLNode() {
next = 0;
}
IntSLLNode(int el, IntSLLNode *ptr = 0) {
info = el; next = ptr;
}
int info;
IntSLLNode *next;
};
class IntSLList {
public:
IntSLList() {
head = 0;
}
~IntSLList();
int isEmpty() {
return head == 0;
}
void addToHead(int);
void addToTail(int);
int deleteFromHead(); // delete the head and return its info;
int deleteFromTail(); // delete the tail and return its info;
bool isInList(int) const;
void printAll() const;
private:
IntSLLNode *head;
};
and here is the main
************************ main **************************
#include <iostream>
using namespace std;
#include "intSLList.h"
int print_reverse(IntSLList & list){
if (head == NULL)
return;
printReverse(head->next);
cout << head->data << " ";
//How to compelete this in an iterative(or recursive if iterative is too much work)way ?
//like this?
}
int main() {
IntSLList list;
list.print_reverse(list);
}
Added the functions
The header gives literally no way to access the contents of the list, other than by destroying it. So ... that's what we're going to do.
int deleteFromTail(); // delete the tail and return its info;
Except we need to go the extra step and rebuild it, because nobody expects printing the container to destory its contents. See https://en.wikipedia.org/wiki/Principle_of_least_astonishment
#include <iostream>
#include <stack>
#include <list>
class IntSLList {
public:
int isEmpty() { return m_list.empty(); }
void addToHead(int i) { m_list.push_front(i); }
void addToTail(int i) { m_list.push_back(i); }
int deleteFromHead() {
int temp = m_list.front();
m_list.pop_front();
return temp;
}
int deleteFromTail() {
int temp = m_list.back();
m_list.pop_back();
return temp;
}
private:
// no implementation given so I'm using std::list internally.
std::list<int> m_list;
};
int print_reverse(IntSLList& mylist) {
// store the data we are destroying in temp
IntSLList temp;
// literally the only way we can access the contents of the container is destructive so ... guess we're going there
while (!mylist.isEmpty()) {
int back = mylist.deleteFromTail();
std::cout << back << std::endl;
temp.addToHead(back);
}
// now rebuild the original list. I told you this would be bad.
while (!temp.isEmpty()) {
mylist.addToHead(temp.deleteFromTail());
}
// maybe this was supposed to be length, but not documented so I can return whatever I want.
return -1;
}
int main() {
IntSLList mylist;
mylist.addToTail(1);
mylist.addToTail(2);
mylist.addToTail(3);
print_reverse(mylist);
}
3
2
1
I am tasked with implementing a new class function called bool List::largest_value(int &largest) within a given class List. The instruction is:
If the list is not empty, put the largest value in the largest
parameter and return true. If the list is empty, return false.
My question is, how do I find the largest value within a parameter?
Here is what I have so far for bool List::largest_value(int &largest):
// Fill in the functions at the bottom of this file
//
#include <iostream>
#include <climits>
using namespace std;
#include "list.h"
// on some machines member variables are not automatically initialized to 0
List::List()
{
m_head = NULL;
}
// delete all Nodes in the list
// since they are dynamically allocated using new, they won't go away
// automatically when the list is deleted
// Rule of thumb: destructor deletes all memory created by member functions
List::~List()
{
while (m_head)
{
Node *tmp = m_head;
m_head = m_head->m_next;
delete tmp;
}
}
// always insert at the front of the list
// Note: this works even in the SPECIAL CASE that the list is empty
void List::insert(int value)
{
m_head = new Node(value, m_head);
}
// iterate through all the Nodes in the list and print each Node
void List::print()
{
for (Node *ptr = m_head; ptr; ptr = ptr->m_next)
{
cout << ptr->m_value << endl;
}
}
void List::compare(int target, int &less_than, int &equal, int &greater_than)
{
Node *temp = m_head;
less_than = 0;
equal = 0;
greater_than = 0;
while(temp != NULL)
{
if(temp->m_value > target)
{
greater_than++;
}
else if(temp->m_value < target)
{
less_than++;
}
else if(temp->m_value == target)
{
equal++;
}
temp = temp-> m_next;
}
}
bool List::largest_value(int &largest)
{
Node *temp = m_head;
largest = INT_MIN;
if(temp == NULL)
{
return false;
}
while(temp != NULL)
{
if(temp->m_value > largest)
{
largest = temp->m_value;
}
temp = temp->m_next;
}
return true;
}
Here is the given class List:
class List
{
public:
List();
~List();
void insert(int value); // insert at beginning of list
void print(); // print all values in the list
void compare(int target, int &less_than, int &equal, int &greater_than);
bool largest_value(int &largest);
private:
class Node
{
public:
Node(int value, Node *next)
{m_value = value; m_next = next;}
int m_value;
Node *m_next;
};
Node *m_head;
};
Main.cpp:
#include <iostream>
using namespace std;
#include "list.h"
int main()
{
List list;
int value;
// read values and insert them into list
while (cin >> value)
{
list.insert(value);
}
int largest;
bool result = list.largest_value(largest);
if (result == false)
{
cout << "empty list" << endl;
return 1;
}
else
{
cout << "The largest value you entered is: " << largest << endl;
}
}
My code compiles and runs, however I keep receiving the output empty list. I honestly have no idea what I need to change in my bool List::largest_value(int &largest)function. I am still very new to linked lists. Any help would be appreciated
I'm writing a binary tree in object-oriented format. I've had experience with binary trees before, but it's been a while since I've touched on this. My problem is that I'm unable to assign a node to my root. Every time I check in debugging mode, the root remains NULL. While this is happening, the cur node contains all the information it's assigned.
I've tried making my root private and changing this->root = NULL; to root-> = NULL;. I've also tried making all of my functions public, but it didn't make a difference. I tried declaring root's children to NULL values and name to an empty string as well.
main.cpp
#include <iostream>
#include <string>
#include <fstream>
#include "Friends.h"
using namespace std;
int main() {
string line;
ifstream file;
file.open("friends.txt");
Friends f;
while (getline(file, line)) {
f.insert(f.root, line);
}
f.print(f.root);
system("pause");
return 0;
}
Friends.cpp
#include "Friends.h"
#include <iostream>
#include <string>
using namespace std;
Friends::Friends() {
this->root = NULL;
}
Friends::node* Friends::createNode(string& val) {
node* newNode = new node();
newNode->left = NULL;
newNode->right = NULL;
newNode->name = val;
return newNode;
}
Friends::node* Friends::insert(node* cur, string& val) {
if (!cur) {
cur = createNode(val);
}
else if (val < cur->name) {
insert(cur->left, val);
return cur;
}
else if (val > cur->name) {
insert(cur->right, val);
return cur;
}
return NULL;
}
void Friends::print(node* cur) {
if (!cur) {
return;
}
print(cur->left);
cout << cur->name << endl;
print(cur->right);
}
Friends.h
#ifndef FRIENDS_H
#define FRIENDS_H
#include <string>
using namespace std;
class Friends {
private:
struct node {
string name;
node* left;
node* right;
};
public:
node* root;
node* insert(node* cur, string&);
void print(node* cur);
Friends();
node* createNode(string&);
};
#endif
The root node should have a node, but has keeps showing up as a NULL value. It doesn't run with any errors either. It just remains as NULL.
change from:
node* insert(node* cur, string&);
to :
node* insert(node* &cur, string&);
should fix
Of course the implementation header should also be changed
For an assignment i have to build this. I just can't seem to see what i am doing wrong. When I am trying to run this code I keep seeing the pointer that my linked list stores it's starting location get pointed to garbage right in the middle. I don't know if Visual Studio is just hazing me or if I am miss assigning a pointer somewhere.
This is the main class i use to run my code
#include "stdafx.h"
#include "Iterator.h"
#include "Node.h"
#include "List.h"
#include <iostream>
int main()
{
int input = 0;
List<double> salaryList;
std::cin >> input;
Node<double> tim(7.0, nullptr);
Node<double> sim(input, nullptr);
Node<double> jim(7.5, nullptr);
salaryList.Add_back(&jim);
salaryList.Add_back(&tim);
salaryList.Insert_front(&sim);
Iterator<double> checkSalaries=salaryList.begin();
//std::cout << "printing all elements in Iterator" << std::endl;
while (checkSalaries.Is_item()){
double x = (*checkSalaries).value;
std::cout << x << std::endl;
checkSalaries++;
}
system("PAUSE");
return 0;
}
This is the code for the LinkedList, i just named it List :
#include "Iterator.h"
#include "Node.h"
template <class t>
class List
{
private:
Node<t>* start=nullptr;
Node<t>* end=nullptr;
int size = 0;
public:
List() {
start = nullptr;
end = nullptr;
}
~List() {
}
void Insert_front(Node<t> * input) {
if (start != nullptr)
{
input->setPoint(start);
start = input;
size++;
}
else {
start = input;
}
if (start->point != nullptr && end == nullptr) {
end = start->point;
size++;
}
}
void Add_back(Node<t> * input) {
if (end != nullptr) {
Node<t> temp = (*end);
temp.setPoint(input);
end = input;
}
else {
if (start != nullptr) {
start->point=input;
end = input;
}
else {
start = input;
}
size++;
}
}
Iterator<t> begin() const
{
Node<t> tempNode = *start;
Iterator<t> temp(&tempNode);
return temp;
}
void Remove_all()
{
List<Node<t>> temp;
start = temp.start;
end = temp.end;
size = 0;
}
int Size() const {
return size;
}
};
This is the Node code:
template <class T>
class Node {
public:
T value;
Node<T> * point;
Node(T first, Node<T> * second)
{
value = first;
point = second;
}
Node()
{
value = NULL;
point = nullptr;
}
void setPoint(Node<T> * input) {
point = input;
}
};
I am going to include here two images the first is what it looks like just before it goes bad, and the next is what happens right after, it seems to occur fairly at random but i have found that using cout always triggers it so i commented out that line, though that didn't resolve the issue.
Good StateBad State
On my first review, it seems the local variable in begin method is creating the issue. Please check my code below. I have commented out the temporary variable created in the begin method and instead made use of the pointer start. This should solve the issue.
Iterator<t> begin() const
{
// Node<t> tempNode = *start; <-- A local variable is used here
// Iterator<t> temp(&tempNode); <-- address of local variable passed to iterator.
Iterator<t> temp(start);
return temp;
}
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()