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.
Related
"dlist_test.cc:16: error: 'testList' was not declared in this scope.
dlist_test.cc:16: error: 'Dlist' was not declared in this scope."
I have been looking at other threads on circular dependences or namespace but I only have one header file, and I'm not using a namespace for dlist.h or dlist.cc. Where am I not declaring this correctly? Is it a Makefile problem? Any help would be appreciated, thank you for your time.
dlist.h:
#ifndef DLIST_H
#define DLIST_H
struct ListNode
{
/* define your list node type */
int val;
ListNode* next;
ListNode* prev;
};
class DList
{
public:
DList();
/* implement copy constructor, assignment, destructor if needed */
void add_to_front(int value);
void add_to_back(int value);
int first();
int last();
void remove(ListNode* node);
ListNode* previous(ListNode* node);
ListNode* next(ListNode* node);
ListNode* search_value(int value);
private:
/* declare your data */
ListNode* head;
ListNode* tail;
};
#endif
dlist.cc
#include "dlist.h"
#include <cstddef>
#include <stdlib.h>
class Dlist{
public:
Dlist(){
head = NULL;
tail = NULL;
}
void add_to_front(int value){
struct ListNode* newhead = (struct ListNode*) malloc(sizeof(struct ListNode));
newhead->val = value;
newhead->prev = NULL;
newhead->next = head;
if(head != NULL)
head->prev = newhead ;
head = newhead;
}
void add_to_back(int value){
if (tail == NULL){
struct ListNode* firstValue = (struct ListNode*)malloc(sizeof(ListNode));
firstValue->val = value;
firstValue->prev = NULL;
firstValue->next = NULL;
tail = firstValue;
}else{
struct ListNode* newtail = (struct ListNode*)malloc(sizeof(ListNode));
newtail->val = value;
newtail->next = NULL;
newtail->prev = tail;
tail->next = newtail;
tail = newtail;
}
}
int first(){
return head->val;
}
int last(){
return tail->val;
}
void remove(ListNode* node){
if (head == NULL || node == NULL){
return;
}
if(head == node){
head = node->next;
}
if (node->next != NULL){
node->next->prev = node->prev;
}
if (node->prev != NULL){
node->prev->next = node->next;
}
free(node);
}
ListNode* previous(ListNode* node){
if(node->prev != NULL){
return node->prev;
}
}
ListNode* next(ListNode* node){
if(node->next != NULL){
return node->next;
}
}
ListNode* search_value(int value){
while(head->next != NULL){
if(head->next->val == value){
return head;
}else{
head = head->next;
}
}
}
private:
ListNode* head;
ListNode* tail;
};
dlist_test.cc
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "dlist.h"
#include <bits/stdc++.h>
using namespace std;
int main (int argc, char* argv[])
{
int N = -1;
if (argc == 2) {
N = atoi (argv[1]);
assert (N > 0);
}
testList = Dlist();
int i = 0;
while(i<N){
testList.add_to_back(i+1);
i++;
}
int randn = rand() % N + 1;// randn in the range 1 to N
//
time_t start, end;
time(&start);
ios_base::sync_with_stdio(false);
struct ListNode* loc = testList.search_value(randn);
testList.remove(loc);
time(&end);
double time_taken = double(end - start);
cout << "Time taken by program is : " << fixed
<< time_taken << setprecision(5);
cout << " sec " << endl;
//
testList.add_to_front(N);
return 0;
}
Makefile:
default:
#echo "=================================================="
#echo "To build your sorting code, use:"
#echo "make dlist_test or make queue_test"
#echo "=================================================="
# Queue driver
queue_test: queue.o
# Doubly linked list driver
dlist_test: dlist.o dlist_test.o
g++ -o dlist_test dlist.o dlist_test.o
dlist.o: dlist.cc dlist.h
g++ -c dlist.cc
dlist_test.o: dlist_test.cc
g++ -c dlist_test.cc
clean:
rm -f core *.o *~ queue_test dlist_test
# eof
These are two different problems:
1) C++ distinguishes uppercase letters from lowercase ones. You declared the class as DList so you need write this name exactly this way. Dlist (with lower case "L") is considered an entirely different name.
2) You've never created variable testList so C++ is right to tell that it doesn't exist. It happens to the best ;)
Just change the line
testList = Dlist();
to
Dlist testList = Dlist();
or
Dlist testList;
The both variants are equivalent. C++ will use a constructor without parameters by default.
I want to read a text file and store new words in linked list. From this linked list I want to write a dictionary file with new words. I don't know why my code don't run. Can anyone help me?
p/s: when i run debug it found this when store vector element to new_node->word
Error
This is my code
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <cstring>
using namespace std;
typedef struct dictionary
{ string word;
int line;
int page;
struct dictionary* next;
} node;
int main()
{
node* Head = NULL;
ifstream file("filetest.txt");
if(file.fail())
cout << "Loi mo file! "<<endl;
string temp;
int cpage = 1,cline = 1;
while(getline(file,temp))
{
stringstream spliter;
spliter << temp;
vector<string> result;
while(!spliter.eof())
{
string str;
spliter >> str;
result.push_back(str);
}
for(size_t i = 0;i != result.size();i++)
{
if(Find(Head,result[i])==0)
{
Append(&Head,result[i],cline,cpage);
}
}
cline++;
if(cline == 25)
cpage++;
}
file.close();
;
ofstream outfile("test.txt");
node* p = Head;
while(p != NULL)
{
outfile << p->word <<","<<p->page<<"-"<<p->line<<endl;
p=p->next;
}
}
Append( add member to linked list)
void Append(node** First,string &newstr,int newl,int newp)
{
node* new_node = (node*)malloc(sizeof(node));
node* last = *First;
new_node->word=newstr;
new_node->line=newl;
new_node->page=newp;
new_node->next = 0;
if(*First == 0)
{
*First = new_node;
return;
}
while(last->next != 0)
{
last = last->next;
}
last->next = new_node;
return;
}
Find( check if a word is new or not)
int Find(node* head,string &tumoi)
{
node* current = head;
while(current != 0)
{
if(current->word == tumoi)
return 1;
current = current->next;
}
return 0;
}
You should not use malloc with C++ types. It does not properly initialize them.
Your node struct contains a std::string which needs to have its constructor called to be properly initialized.
When you do this
node* new_node = (node*)malloc(sizeof(node));
new_node->word=newstr;
The new_node->word is not initialized and can contain pointers to nowhere.
You should do
node* new_node = new node();
new_node->word=newstr;
instead.
It looks like in "SortedInsert", the head is always zero and then the code segfaults anyway... really frustrating. Any idea why the head is always zero even though I set it to something, and then why the code segfaults in general?
Thanks
#include <iostream>
#include <cassert>
#include <string>
#include <stdlib.h>
#include <sstream>
using namespace std;
struct Node {
Node* next = 0;
int data;
~Node(){
if (next != 0){
delete next;
}
}
};
void SortedInsert(Node* head, int value){
if(head == 0){
Node* header = new Node;
header->data = value;
head = header;
return;
}
cout << "TEST" << endl;
Node* temp = head;
while(temp != 0){
if(value > temp->data){
Node* insert = temp->next;
Node* otherTemp = new Node;
otherTemp->data = value;
temp->next= otherTemp;
temp->next->next = insert;
}
temp=temp->next;
}
return;
}
int main() {
srand(32);
Node* sortedList = 0;
for (int i = 0; i < 10; i++){
SortedInsert(sortedList, rand() % 100);
}
Node* temp = sortedList;
for (int i=0; i < 9; i++){
assert(temp->data <= temp->next->data);
temp = temp->next;
}
delete sortedList;
}
SortedInsert has its own copy of the head pointer. When you change head inside the function it doesn't affect the value in main. The solution is to pass head by reference or by passing the address.
void SortedInsert(Node** head, int value) {
//Use *head to refer to the head of the list
}
int main() {
...
Node* sortedList = 0;
SortedInsert(&sortedList, ...);
...
}
Or
void SortedInsert(Node*& head, int value) {
//Use head to refer to the head of the list
}
int main() {
...
Node* sortedList = 0;
SortedInsert(sortedList, ...);
...
}
Try the following
void SortedInsert( Node* &head, int value )
{
if ( head == nullptr || value < head->data )
{
head = new Node { head, value };
}
else
{
Node *current = head;
while ( current->next != nullptr && !( value < current->next->data ) )
{
current = current->next;
}
Node *tmp = new Node { current->next, value };
current->next = tmp;
}
}
As for your funcion implementation then the function deals with a copy of the head. Any changes of the copy do not influence on the argument itself. You should pass the head by reference or return the head from the function.
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.
This is my first go at building a graph and i've decide to use a LL to connect my vectors (or nodes or elements, whatever they're called) and each one of my nodes has a vector that holds pointers to nodes. I've created a "addEdge" function in my graph class but it seems to be breaking my program. My addElement class seems to be working fine, as it will add and print them out perfectly. But when I try to add an edge, it breaks. I went through the debugger and it breaks at
while(curr->next != NULL || curr->val != n)
Any ideas why?
#include "element.h"
#include "vector"
#include "iostream"
#include "functional"
using namespace std;
class Graph
{
public:
element *head;
Graph(int V)
{
head = NULL;
vector <element*> nodes;
}
void addElement(int val)
{
if (head == NULL)
{
element *newelement = new element(NULL, NULL, val);
head = newelement;
return ;
}
element *newelement = new element(NULL,NULL, val);
element *curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = newelement;
newelement->prev = curr;
return;
}
void addEdge(int n, int edge)
{
element *e = head;
element *curr = head;
if(curr = NULL)
{
cout<<"There are no elements in your graph to connect";
return;
}
while(e->next != NULL || e->val != edge)
{
cout<<"Looking";
e = e->next;
}
if(e->val != edge)
{
cout<<"Your edge node doesn't exist";
return;
}
while(curr->next != NULL || curr->val != n)
{
cout<<"Looking for main node";
curr = curr->next;
}
if(curr->val != n)
{
cout<<"Could not find the main node";
return;
}
curr->edges.push_back(e);
cout<<"Edge connected";
return;
}
node class
#include "vector"
#include "iostream"
#include "functional"
using namespace std;
class element {
public:
element(element* n = NULL, element *p = NULL, int num = NULL)
{
val = num;
next = n;
prev = p;
}
int val;
element *prev;
element *next;
vector<element*> edges;
};