I have a fully functioning hashMap class and everything seems to be working very well EXCEPT a rehash function designed to create a hashmap when the load factor of the previous hashmap reaches 0.8.
void HashMap::reHash()
{
logins = 0;
numberOfPairs = 0;
Node** newBucket = new Node* [(2 * lengthOfMap) + 1];
for(int i = 0; i < lengthOfMap; i++)
{
Node* oldHead = bucketList[i];
for(Node* temp = oldHead; temp != nullptr; temp = temp-> next)
{
std::string key = oldHead->key;
std::string value = oldHead->value;
unsigned int index = hash(key) % lengthOfMap;
if(newBucket[index] == nullptr)
{
std::cout << "HIT" << std::endl;
newBucket[i] = new Node;
newBucket[i]->key = key;
newBucket[i]->value = value;
newBucket[i]->next = nullptr;
numberOfPairs[index]++;
logins++;
}
else if (bucketList[index] != nullptr)
{
Node* temp = bucketList[index];
while(temp->next != nullptr)
{
temp = temp->next;
}
Node* n = new Node;
n->key = key;
n->value = value;
temp->next = n;
n->next = nullptr;
std::cout << "FAIL at index: " << index << std::endl;
//numberOfPairs[index]++;
logins++;
}
}
}
for(int i = 0; i < lengthOfMap; ++i)
{
if( bucketList[i] )
{
Node* first = bucketList[i];
while( first )
{
Node* temp = first->next;
delete first;
first = temp;
}
}
}
delete bucketList;
bucketList = newBucket;
lengthOfMap = (2 * lengthOfMap) + 1;
}
bucketList[] is my previous array full of Node* which each begin the first link in a linked list. I have added a couple std::cout for my own benefit, and I seem to be stuck in a permanent loop reading FAIL at index:0 over and over again. I will admit I am new to the for loop iterating through the linked list, which I think is the source of my problem, but I'm looking for any helpful input.
Thanks again.
Related
I am writing a program that modifies a linked list. The problem I am having is when inserting nodes into the linked list. The first few nodes are inserted and moved properly, but when reaching the end of the linked list some nodes are either removed or not displayed.
Function for inserting
void LinkedList::insert(int num, int pos)
{
Node *temp1 = new Node;
temp1->data = num;
temp1->next = NULL;
if(pos == 0)
{
temp1->next = head;
head = temp1;
return;
}
Node *temp2 = head;
for(int i = 0; i < pos-1; i++)
{
temp2 = temp2->next;
}
temp1->next = temp2->next;
temp2->next = temp1;
}
Node structure
struct Node
{
int data;
Node *next;
};
int size;
Node *head, *tail;
Driver code
nums.insert(1, 0); // 1 in location 0
nums.insert(5, 4); // 5 in location 4
nums.insert(3, 7); // 3 in location 7
List before insert
8 6 7 8 0 9
List after insert
1 8 6 7 5 8
Expected after insert
1 8 6 7 5 8 0 9 3
Would the values excluded from being display needed to be stored and inserted afterwards? Or is the inserting itself not being coded properly/missing elements?
Thanks for your help.
Full code
#include "linkedlist.h"
LinkedList::LinkedList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LinkedList::~LinkedList()
{
if(head != nullptr)
{
Node *temp;
while(head != nullptr)
{
temp = head->next;
// deletes head
delete head;
// goes to next element
head = temp;
}
}
}
void LinkedList::display()
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
cout << temp->data << "\t";
temp = temp->next;
}
cout << endl;
}
void LinkedList::append(int num)
{
// list is empty
if(head == nullptr)
{
head = new Node;
head->data = num;
head->next = nullptr;
// sets tail to head
tail = head;
}
else
{
// creates new node
Node *temp = new Node;
// sets new node data
temp->data = num;
temp->next = nullptr;
// sets previous tail link to new node
tail->next = temp;
// sets this node to new tail
tail = temp;
}
// increments size
size++;
}
void LinkedList::pop()
{
if(size > 1)
{
Node *temp = head;
// loops to node before tail
while(temp->next->next != nullptr)
{
temp = temp->next;
}
// deletes tail
delete tail;
// sets new tail
tail = temp;
tail->next = nullptr;
}
// if there's only one item
else if(size == 1)
{
Node *temp = tail;
// head and tail are now null
head = nullptr;
tail = nullptr;
// deletes node
delete temp;
}
size--;
}
int LinkedList::min()
{
int min = head->data;
struct Node *temp = head;
while(temp != nullptr)
{
if(min > temp->data)
{
min = temp->data;
}
temp = temp->next;
}
return min;
}
int LinkedList::max()
{
int max = head->data;
struct Node *temp = head;
while(temp != nullptr)
{
if(max < temp->data)
{
max = temp->data;
}
temp = temp->next;
}
return max;
}
int LinkedList::mean()
{
int sum = 0;
int average = 0;
struct Node *temp = head;
while(temp != nullptr)
{
sum += temp->data;
temp = temp->next;
}
average = sum / size;
return average;
}
void LinkedList::sort()
{
Node *current1 = head;
Node *current2 = head;
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size - 1; j++)
{
if(current1->data < current2->data)
{
int temp = current1->data;
current1->data = current2->data;
current2->data = temp;
}
current2 = current2->next;
}
current2 = head;
current1 = head->next;
for(int p = 0; p < i; p++)
{
current1 = current1->next;
}
}
}
void LinkedList::reverse()
{
Node *current1 = head;
Node *current2 = head;
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size - 1; j++)
{
if(current1->data > current2->data)
{
int temp = current1->data;
current1->data = current2->data;
current2->data = temp;
}
current2 = current2->next;
}
current2 = head;
current1 = head->next;
for(int p = 0; p < i; p++)
{
current1 = current1->next;
}
}
}
int LinkedList::linearSearch(int key)
{
Node *search = nullptr;
Node *temp = head;
Node *current = head;
int count = 0;
while(current != NULL && current->data != key)
{
count++;
temp = current;
current = current->next;
}
if(current != NULL)
{
search = current;
current = current->next;
}
key = count;
return key;
}
void LinkedList::insert(int num, int pos)
{
Node *temp1 = new Node;
temp1->data = num;
temp1->next = NULL;
if(pos == 0)
{
temp1->next = head;
head = temp1;
return;
}
Node *temp2 = head;
for(int i = 0; i < pos-1; i++)
{
temp2 = temp2->next;
}
temp1->next = temp2->next;
temp2->next = temp1;
}
You have a size member that your display function uses, but you never increment it in insert. So while the element gets added, you don't increase the size of the list.
Reading your whole code and getting to the solution may consume lot of time but if you want i have a code ready which is properly working. If you wanted to use this. Please go for it and also, please feel free to ask my anything though this link
#include <iostream>
using namespace std;
struct node
{
int data;
node *next;
};
class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}
void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;
if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}
node* gethead()
{
return head;
}
static void display(node *head)
{
if(head == NULL)
{
cout << "NULL" << endl;
}
else
{
cout << head->data << endl;
display(head->next);
}
}
static void concatenate(node *a,node *b)
{
if( a != NULL && b!= NULL )
{
if (a->next == NULL)
a->next = b;
else
concatenate(a->next,b);
}
else
{
cout << "Either a or b is NULL\n";
}
}
};
int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
linked_list b;
b.add_node(3);
b.add_node(4);
linked_list::concatenate(a.gethead(),b.gethead());
linked_list::display(a.gethead());
return 0;
}
I am using linked lists to simulate a computer lab, and I am trying to print the linked lists. There's an issue with printing using cout, it produces garbage until the terminal just gives up and sends a segmentation fault 11.
#include <iostream>
#include <string>
using namespace std;
struct lab {
string current_ID;
int station_number;
lab *link;
};
typedef lab* lab_ptr;
void print_status(lab_ptr& head1, lab_ptr& head2, lab_ptr& head3, lab_ptr& head4);
int main()
{
lab_ptr head_lab_1;
head_lab_1 = new lab;
lab_ptr head_lab_2;
head_lab_2 = new lab;
lab_ptr head_lab_3;
head_lab_3 = new lab;
lab_ptr head_lab_4;
head_lab_4 = new lab;
set_up_linked_list_for_n_stations(head_lab_1, 5);
set_up_linked_list_for_n_stations(head_lab_2, 6);
set_up_linked_list_for_n_stations(head_lab_3, 4);
set_up_linked_list_for_n_stations(head_lab_4, 3);
return 0;
}
void set_up_linked_list_for_n_stations(lab_ptr& head, int n)
{
lab_ptr curr;
curr = new lab;
for(int j = 0; j < n; j++)
{
lab_ptr temp = new lab;
temp->link = NULL;
temp->station_number = n+1;
temp->current_ID = 'empty';
cout << temp->station_number << " " << temp->current_ID << endl;
if(head != NULL)
{
curr = head;
while(curr->link != NULL)
{
curr = curr->link;
}
curr->link = temp;
} else
{
head = temp;
}
}
}
This is literally my first time using linked lists, so the error can be something incredibly obvious that i just missed. Sorry for advanced if it's a dumb mistake.
For the string member current_ID you need to pass the value using double quotes:
temp->current_ID = 'empty';
becomes
temp->current_ID = "empty";
Also you need to move the function void set_up_linked_list_for_n_stations(lab_ptr& head, int n) before the main()
You are making extra allocations, other place the list is not properly initialized. Initialize head_lab_1 to nullptr (or just NULL)
In the function set_up_linked_list_for_n_stations remove curr = new lab
void set_up_linked_list_for_n_stations(lab_ptr& head, int n)
{
for(int j = 0; j < n; j++)
{
lab_ptr temp = new lab;
temp->link = NULL;
temp->station_number = n + 1;
temp->current_ID = "empty";
cout << temp->station_number << " " << temp->current_ID << endl;
if(head != NULL)
{
lab_ptr curr = head;
while(curr->link != NULL)
{
curr = curr->link;
}
curr->link = temp;
}
else
{
head = temp;
}
}
}
int main()
{
lab_ptr head_lab_1 = nullptr;
lab_ptr head_lab_2 = nullptr;
lab_ptr head_lab_3 = nullptr;
lab_ptr head_lab_4 = nullptr;
set_up_linked_list_for_n_stations(head_lab_1, 5);
set_up_linked_list_for_n_stations(head_lab_2, 6);
set_up_linked_list_for_n_stations(head_lab_3, 4);
set_up_linked_list_for_n_stations(head_lab_4, 3);
return 0;
}
I've been struggling with this last function (list_copy_front). The function is for a linked list, it is supposed to return the value of the head pointer for a new list that contains copies of the first n nodes that the source pointer points to. Also if there is less than n nodes in the source then just copy all. Currently, when I run it as is I get a nasty Segmentation Fault SIGSEGV error. The debugger says the error happens at "Node *cursor = source_ptr-> link; Any help would be greatly appreciated, thank you.
Here is some relevant info,
struct Node
{
typedef int Item;
Item data;
Node *link;
};
void list_tail_attach(Node*& head_ptr, const Node::Item& entry);
Node* list_copy_front(Node* source_ptr, size_t n);
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node;
last->data = entry;
last->link = NULL;
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = new Node;
temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
Node *new_head_ptr = new Node;
Node *cursor = source_ptr->link;
size_t i = 0;
for(i = 0; i < n; i++)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
}
return new_head_ptr;
}
Here's the Main test for the function
int test4()
{
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
if(copy != NULL)
{
cout << "list_copy_front function doesn't work for copying empty list\n";
return 0;
}
for(int i = 1; i <= 4; i++)
list_tail_attach(list, i);
// list contains 1, 2, 3, 4
copy = list_copy_front(list, 3);
if(list_length(copy) != 3 || copy->data != 1 || copy->link->data != 2 || copy->link->link->data != 3 )
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
copy->link->data = 100;
if(list->link->data == 100)
{
cout << "list_copy_front function doesn't work.\n";
return 0;
}
list_clear(copy);
copy = list_copy_front(list, 6);
if(list_length(copy) != 4)
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
cout << "list_copy_front passes the test\n";
list_clear(list);
for(int i = 1; i <= 3; i++)
list_head_insert(list, i);
// list contains 3, 2, 1
list_copy(list, copy);
if(list_length(copy) != 3 || copy->data != 3 || copy->link->data != 2 || copy->link->link->data != 1 )
{
cout << "list_copy function doesn't work\n";
return 0;
}
cout << "list_copy function passes the test\n";
return 2;
}
Edit 3
So far here's what I'm working with I appreciate the comments so far it's just not quite working out. Which is probably my fault for not explaining better.
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node; // Creates new Node
last->data = entry; // Points last to data
last->link = NULL;
if(last == NULL)
{
return;
}
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL)
{
return NULL;
}
Node *new_head_ptr = new Node;
Node *cursor = source_ptr;
size_t i = 0;
while(cursor!= NULL && i < n)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
I am not allowed to change the way the function takes it's input so, that's why I left Node *last.
I left list_tail_attach(new_head_ptr, cursor->data) because without it I get an invalid conversion error. However when I run the above code I still receive an SIGSEGV error for while(temp->link != NULL) in list_tail_attach and on list_tail_attach(new_head_ptr, cursor->data); in list_copy_front.
Thank you if you are able to comment further
The first test case
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
gives Node* source_ptr == NULL and expects your function to handle it gracefully.
The function code soon tries to dereference NULL
Node *cursor = source_ptr->link;
The result is a segfault.
First is list_tail_attach, this function I assumed to be attaching an existing Node into a linked list. If the linked list is null then the Node become the head
void list_tail_attach(Node *& head_ptr, Node *& entry)
{
if (entry == NULL) {
return;
}
if (head_ptr == NULL)
{
head_ptr = entry;
}
else
{
Node *temp = head_ptr;
while (temp->link != NULL)
{
temp = temp->link;
}
temp->link = entry;
}
}
I changed the entry into a reference to a pointer to made it easier.
Ok, now move on to the list_copy_front
Node * list_copy_front(Node* source_ptr, size_t n)
{
if (source_ptr == NULL) {
return NULL;
}
Node * new_head_ptr = new Node;
Node * cursor = source_ptr;
size_t i = 0;
while(cursor != NULL && i < n){
list_tail_attach(new_head_ptr, cursor);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
You have to guard the source_ptr in case it is null.
To attach a new Node
for (int x = 0; x < 5; x++) {
Node * tmp = new Node();
tmp->data = x;
tmp->link = NULL;
list_tail_attach(list, tmp);
}
My professor helped me out with the correct solution. For anyone who views this in the future...
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL) // Takes care of NULL case
{
return NULL;
}
Node *new_head_ptr = NULL; // Creates new head and ensures NULL
Node *cursor = source_ptr; // Sets temp Node = to source
size_t i = 0; // Initializes temp variable
while(cursor!= NULL && i < n) // Loop that continues while n is bigger than i and it is not NULL
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link; // Attaches to new list
i++; // Increases count
}
return new_head_ptr;
}
The line that needed to be changed was
Node * new_head_ptr = new Node;
to
Node * new_head_ptr = NULL;
I have the following struct:
class List{
public: //Functions go here
typedef struct node{
string data;
node* prev;
node* next;
}* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
nodePtr tail;
List();
//~List();
void addToEnd(string addData);
void addToBeg(string addData);
void DeleteList();
//More functions not included//
};
with constructor:
List::List(){
head = NULL;
curr = NULL;
temp = NULL;
tail = NULL;
}
and to delete nodes:
void List::DeleteList(){
temp = head;
curr = head;
while(curr != NULL){
temp = curr->next;
delete curr;
curr = temp;
}
}
The rest of the code takes in numbers and performs addition and multiplication on them by partitioning the numbers into nodes. I call DeleteList() at the end of each function for each List. When I run the code with Valgrind, my output completes with the correct answers even though it says "Conditional jump or move depends on uninitialised value(s)" on a few of the function calls.
When I execute the program along using gcc, I get a "pointer being freed was not allocated". What is the difference between the two execution methods? And why is gcc saying that the pointer wasn't allocated?
Adding a node looks like:
void List::addToEnd(string addData){ //adds to end of linked list
//nodePtr n = (nodePtr)malloc(sizeof(node));
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if(head != NULL){
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = n;
n->prev = curr;
tail = n;
}
else{
n->prev = NULL;
head = n;
tail = n;
}
}
edit: Complete code for reference:
//structure for assembling doubly linked list.
#include <cstdlib>
#include <iostream>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <math.h>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
using namespace std;
class List{
public: //Functions go here
typedef struct node{
string data;
node* prev;
node* next;
}* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
nodePtr tail;
List();
~List();
void addToEnd(string addData);
void addToBeg(string addData);
List::nodePtr returnHead();
List::nodePtr returnNext(List::nodePtr n);
List::nodePtr returnPrev(List::nodePtr n);
List::nodePtr returnTail();
void DeleteList();
void PrintList();
void ConvertHead();
void DeleteNode(string delData);
string ListValue();
string returnValue(List::nodePtr n);
};
//Functions
List addLists(List a, List b, long long nodeLength);
List multLists(List a, List b, long long nodeLength);
string doArithmetic(string num1, string num2, string op, long long nodSiz);
string removeSpaces(string input);
int main(int argc, char** argv){
string sentence, sent2, operation, arg1, arg2;
long long digitCount;
int op;
//Takes in the first argument and finds the first double quote
//Uses what is in the quotes as the filename
string str (argv[1]);
size_t firstEqual = 6;
size_t semicolon = str.find_first_of(";");
size_t secondEqual = semicolon + 17;
std::string file = str.substr(firstEqual, semicolon - firstEqual);
digitCount = stoll(str.substr(secondEqual, str.length()));
//Opens the file designated in the argument
ifstream inputFile (file.c_str());
while(getline(inputFile, sentence)){
sent2 = removeSpaces(sentence);
op = sent2.find_first_of("+*");
arg1 = sent2.substr(0,op);
arg2 = sent2.substr(op+1,string::npos);
//cout << "arg1: " << arg1 << " arg2: " << arg2 << " Operation: " << sent2.substr(op,1) << endl;
cout << sent2 << "=";
cout << doArithmetic(arg1, arg2, sent2.substr(op,1), digitCount) << endl;
}
return 0;
}
string doArithmetic(string num1, string num2, string op, long long nodSiz){
long long nodeSize = nodSiz;
string numberOne = num1; //14
string numberTwo = num2;
string answer;
List value1, value2, result;
//cout << numberOne << endl;
//assigns values as strings to value1
if(strlen(numberOne.c_str())%nodeSize != 0){
value1.addToEnd(numberOne.substr(0,strlen(numberOne.c_str())%nodeSize));
for(int i=0; i < strlen(numberOne.c_str())/nodeSize; i++){
value1.addToEnd(numberOne.substr(strlen(numberOne.c_str())%nodeSize + i*nodeSize,nodeSize));
}
}
else{
for(int i=0; i < strlen(numberOne.c_str())/nodeSize; i++){
value1.addToEnd(numberOne.substr(strlen(numberOne.c_str())%nodeSize + i*nodeSize,nodeSize));
}
}
//value1.PrintList();
//cout <<numberTwo<<endl;
//assigns values as strings to value2
if(strlen(numberTwo.c_str())%nodeSize != 0){
value2.addToEnd(numberTwo.substr(0,strlen(numberTwo.c_str())%nodeSize));
for(int i=0; i < strlen(numberTwo.c_str())/nodeSize; i++){
value2.addToEnd(numberTwo.substr(strlen(numberTwo.c_str())%nodeSize + i*nodeSize,nodeSize));
}
}
else{
for(int i=0; i < strlen(numberTwo.c_str())/nodeSize; i++){
value2.addToEnd(numberTwo.substr(strlen(numberTwo.c_str())%nodeSize + i*nodeSize,nodeSize));
}
}
//value2.PrintList();
if(op == "+"){
result = addLists(value1, value2, nodeSize);
}
else{
result = multLists(value1, value2, nodeSize);
}
result.ConvertHead();
answer = result.ListValue();
value1.DeleteList();
value2.DeleteList();
result.DeleteList();
return answer;
}
List multLists(List a, List b, long long nodeLength){
List n;
List::nodePtr aPoint, bPoint;
long long valueA, valueB, product;
long long leftover = 0;
string filler;
long long lengthDiff;
int counterA = 0;
int counterB = 0;
for(int i=0; i < nodeLength;i++) filler = "0" + filler;
bPoint = b.returnTail();
while(bPoint != NULL){
//cout << "B Point" << endl;
valueB = stoll(b.returnValue(bPoint));
leftover = 0;
aPoint = a.returnTail();
counterA = 0;
while(aPoint != NULL){
//cout << "A Point" << endl;
List temp;
valueA = stoll(a.returnValue(aPoint));
product = valueA * valueB + leftover;
lengthDiff = to_string(product).length() - nodeLength;
if(to_string(product).length() > nodeLength){
temp.addToBeg(to_string(product).substr(to_string(product).length()-nodeLength,nodeLength));
leftover = stoll(to_string(product).substr(0,lengthDiff));
}
else{
temp.addToBeg(to_string(product));
leftover = 0;
}
for(int i = 0; i < counterA + counterB; i++){
temp.addToEnd(filler);
}
n = addLists(n,temp,nodeLength);
temp.DeleteList();
aPoint = a.returnPrev(aPoint);
counterA = counterA + 1;
}
bPoint = b.returnPrev(bPoint);
counterB = counterB + 1;
}
if(leftover != 0) n.addToBeg(to_string(leftover));
return n;
}
List addLists(List a, List b, long long nodeLength){
List n;
List::nodePtr aPoint, bPoint;
long long valueA, valueB, sum;
long long leftover = 0;
long long lengthDiff;
string input;
aPoint = a.returnTail();
bPoint = b.returnTail();
while(aPoint != NULL || bPoint != NULL){
if(aPoint != NULL) valueA = stoll(a.returnValue(aPoint));
else valueA = 0;
if(bPoint != NULL) valueB = stoll(b.returnValue(bPoint));
else valueB = 0;
sum = valueA + valueB + leftover;
if(to_string(sum).length() > nodeLength){
input = to_string(sum).substr(to_string(sum).length()-nodeLength,nodeLength);
}
else {
input = to_string(sum);
}
lengthDiff = nodeLength-to_string(sum).length();
if(nodeLength > to_string(sum).length()){
for(int i=0; i < nodeLength-to_string(sum).length();i++){
// cout << "sumLength: " << to_string(sum).length() << endl;
input = "0" + input;
}
}
n.addToBeg(input);
if(to_string(sum).length() > nodeLength){
leftover = stoll(to_string(sum).substr(0,to_string(sum).length() - nodeLength));
}
else leftover = 0;
if(aPoint != NULL) aPoint = a.returnPrev(aPoint);
if(bPoint != NULL) bPoint = b.returnPrev(bPoint);
// cout << "sum: " << sum << " sum.length(): " << to_string(sum).length() << " leftover: " << leftover << endl;
// cout << "lengthDiff: " << to_string(sum).substr(0,to_string(sum).length() - nodeLength) << endl;
}
if(leftover != 0) n.addToBeg(to_string(leftover));
return n;
}
List::List(){
head = NULL;
curr = NULL;
temp = NULL;
tail = NULL;
}
List::~List(){
temp = head;
curr = head;
while(curr != NULL){
temp = curr->next;
delete curr;
//free(curr);
curr = temp;
}
head = curr = temp = tail = NULL;
}
void List::addToEnd(string addData){ //adds to end of linked list
//nodePtr n = (nodePtr)malloc(sizeof(node));
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if(head != NULL){
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = n;
n->prev = curr;
tail = n;
}
else{
n->prev = NULL;
head = n;
tail = n;
}
}
void List::addToBeg(string addData){ //adds to beginning of linked list
//nodePtr n = (nodePtr)malloc(sizeof(node));
nodePtr n = new node;
n->prev = NULL;
n->data = addData;
if(head != NULL){
curr = head;
while(curr->prev!= NULL){
curr = curr->prev;
}
curr->prev = n;
n->next = curr;
head = n;
}
else{
n->prev = NULL;
head = n;
tail = n;
}
}
List::nodePtr List::returnHead(){
return head;
}
List::nodePtr List::returnNext(List::nodePtr n){
return n->next;
}
List::nodePtr List::returnPrev(List::nodePtr n){
return n->prev;
}
List::nodePtr List::returnTail(){
return tail;
}
string List::returnValue(List::nodePtr n){
return n->data;
}
void List::DeleteList(){
temp = head;
curr = head;
while(curr != NULL){
temp = curr->next;
delete curr;
//free(curr);
curr = temp;
}
head = curr = tail = temp = NULL;
}
void List::ConvertHead(){
long long convert;
curr = head;
convert = stoll(curr->data);
curr->data = to_string(convert);
}
void List::PrintList(){
curr = head;
while(curr != NULL){
cout << curr->data << endl;
curr = curr->next;
}
}
string List::ListValue(){
string value;
curr = head;
while(curr != NULL){
value = value + curr->data;
curr = curr->next;
}
return value;
}
string removeSpaces(string input){ //found on cplusplus.com
int length = input.length();
for (int i = 0; i < length; i++) {
if(input[i] == ' ') input.erase(i, 1);
}
return input;
}
Example command line prompt:
./a.out "input=test0.txt; digitsPerNode =3"
with example input file named test0.txt:
0*0
0+1
2*3
2*2000000000000000
2*3
1+10
10000000000000000+1
12345667890123456789 + 8765432109876543210
999999999999999999999 + 1
Copy constructor and assignment operator are required for such class, since it holds pointers.
The default copy constructor only makes a copy of class members.
So, if a local class instance is returned from a function the result contains pointers to invalid nodes that are deleted during destruction of the local object:
List multLists(List a, List b, long long nodeLength)
{
List n;
//... construct nodes of n
return n;
}
// result holds only body of returned n; nodes are already deleted
result = multLists(value1, value2, nodeSize);
Copy constructor and assignment operator with deep object copy resolve that issue:
// copy constructor
List::List(const List& l) :
head(nullptr), curr(nullptr), temp(nullptr), tail(nullptr)
{
for (nodePtr i = l.head; i; i = i->next)
addToEnd(i->data);
}
// C++11 move constructor
List::List(List&& l) :
head(l.head), curr(l.curr), temp(l.temp), tail(l.tail)
{
// keep original object in consistent state
l.head = nullptr;
l.curr = nullptr;
l.temp = nullptr;
l.tail = nullptr;
}
// assignment operator
List& List::operator=(const List& l)
{
if (this == &l)
return *this;
// for exception safety at first copy to temporary
List tmp(l);
// move temporary to this
*this = move(tmp);
return *this;
}
// C++11 move assignment operator
List& List::operator=(List&& l)
{
if (this == &l)
return *this;
// free current list
DeleteList();
// move to this
head = l.head;
curr = l.curr;
temp = l.temp;
tail = l.tail;
// keep original object in consistent state
l.head = nullptr;
l.curr = nullptr;
l.temp = nullptr;
l.tail = nullptr;
return *this;
}
The adding to begin also should be fixed:
void List::addToBeg(string addData){ //adds to beginning of linked list
nodePtr n = new node;
n->prev = NULL;
n->data = addData;
if(head != NULL){
n->next = head;
head->prev = n;
head = n;
}
else{
n->next = NULL;
head = n;
tail = n;
}
}
Other remarks
Since the project compilation requires C++11 there is nullptr instead of NULL.
It looks that addToEnd() may be optimized. The while loop is not needed to find the last list item, since there is tail pointer.
It makes sense to avoid deep object copies during function calls. It is better to pass constant references:
List multLists(const List& a, const List& b, long long nodeLength)
Of course here the code should be adjusted to proper usage of const qualifiers.
I am trying to do a linked list of int values. I add 3 int values to list, and I print them but my problem after print the 3 values, the program goes back in to print function to print a 4th one because (tempNode != NULL) gives true but it should be NULL after printing 3 values, so it gives me access violation reading error in the print method at cout << "index " << size-- << ", value: "<< tempNode->num << endl;
It is going beyond my list nodes, but I have no idea where am doing wrong.
Please help, 2 days am trying to figure this out.
code below.
IntList::IntList()
{
first = NULL;
last = NULL;
size = 0;
}
IntList::Node::Node(const int& info, Node* next = NULL)
{
num = info;
next = next;
}
IntList::~IntList()
{
Node* tempNode = first;
while ( tempNode != NULL )
//for(int i = 0; i < size; i++)
{
Node* nextNode = tempNode->next;
delete tempNode;
tempNode = nextNode;
}
first = last = NULL;
size = 0;
}
IntList::IntList(const IntList& wl)
{
cout << "here word list copy conts " << endl;
first = last = NULL;
size = wl.size;
if(wl.first != NULL){
Node* tempNode = wl.first;
for(int i = 0; i < wl.size; i++)
{
addLast(tempNode->num);
tempNode = tempNode->next;
}
}
}
IntList& IntList::operator = (const IntList& wl)
{
cout << "here word list =" << endl;
if(this == &wl)
return *this;
Node* tempNode = first;
while ( tempNode != NULL )
{
Node* nextNode = tempNode->next;
delete tempNode;
tempNode = nextNode;
}
first = NULL;
last = NULL;
if(wl.first != NULL)
{
for(int i = 0; i < wl.size; i++)
{
addLast(tempNode->num);
tempNode = tempNode->next;
size++;
}
}
return *this;
}
void IntList::addFirst(int& winfo)
{
Node* firstNode = new Node(winfo);
//Node firstNode(winfo);
if(first == NULL)
{
first = last = firstNode;
}
else
{
firstNode->next = first;
first = firstNode;
}
//increment list size
size++;
}
void IntList::print(ostream& out)
{
Node* tempNode = first;
while ( tempNode != NULL )
{
out << "\t";
cout << "index " << size-- << ", value: "<< tempNode->num << endl;
tempNode = tempNode->next;
}
}
The next parameter of the Node constructor shadows its next member, so next = next is assigning to the parameter.
Rename one of them.
Also, don't modify size while you're printing.