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;
}
Related
I have implemented a basic linked list in order to prepare for a more difficult one as an assignment. I can't seem to be able to print the contents of a node without printing out random symbols.
I know this means I am accessing bad memory but I cannot identify where or how it is happening.
Can someone please help me fix this error?
built with g++ on linux
Header File
#ifndef LLIST_H
#define LLIST_H
#include <string>
using namespace std;
struct node
{
int age;
string name;
string hair;
int height;
node* next;
};
node loadNode(node a, string b);
class linkedlist
{
private:
node* head = NULL;
node* tail = NULL;
int size;
public:
linkedlist();
linkedlist(node* n[], int si);
int getSize();
void print();
void addNode(node add);
void del(string record);
node sort(node sortee);
void printList();
node * getHead();
};
#endif
Implementation
#include "list.h"
#include <iostream>
#include <sstream>
#include <string>
node loadNode(node a, string b)
{
int counter = 0;
string ag = "";
string nam = "";
string hai = "";
string hei = "";
for(int i = 0; i < b.length(); i++)
{
if(b[i] == ',')
{
counter++;
i++;
}
if(counter == 0)
ag = ag + b[i];
else if(counter == 1)
nam = nam + b[i];
else if(counter == 2)
hai = hai + b[i];
else
hei = hei + b[i];
}
stringstream s(hei);
stringstream o(ag);
int f,g;
s >> f;
o >> g;
a.hair = hai;
a.height = f;
a.age = g;
a.name = nam;
return a;
}
linkedlist::linkedlist()
{
head = NULL;
tail = NULL;
size = 0;
}
linkedlist::linkedlist(node a[],int si)
{
head = NULL;
tail = NULL;
size = 0;
for(int i = 0; i < si; i++)
{
addNode(a[i]);
}
}
void linkedlist::addNode(node added)
{
node * pointer = new node;
//if the first element
if(size == 0)
{
tail = pointer;
pointer->next = NULL;
}
pointer->next = head;
head = pointer;
//add data members
pointer-> age = added.age;
pointer-> hair = added.hair;
pointer-> name = added.name;
pointer-> height = added.height;
size++;
//time to exit!
pointer = NULL;
delete pointer;
}
node * linkedlist::getHead()
{
node * temp = head;
return temp;
}
void linkedlist::print()
{
node* iterator = (node*)malloc(sizeof(node));
iterator = head;
while(iterator != NULL)
{
printNode(iterator);
iterator = (iterator->next);
}
iterator = NULL;
delete iterator;
}
void printNode(node* printed)
{
cout << printed->name << endl;
cout << printed->age << endl;
cout << printed->height << endl;
cout << printed->hair<< endl;
}
main program
#include "list.h"
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
string k = "21,Ces Goose,brown,5";
string a = "25, SteveO, Brown, 6";
string b = "23, Jimmy , Brown, 5";
node d,f,c;
d = loadNode(d,k);
f = loadNode(f,a);
c = loadNode(c,b);
node lib[3] = {d,f,c};
linkedlist doublel = linkedlist(lib, 3);
doublel.print();
return 0;
}
The output I am getting is:
6304000
#g���
#C.M. please let me know if this fixes the issue
void linkedlist::addNode(node added)
{
node * temp = new node;
//add data members
temp-> age = added.age;
temp-> hair = added.hair;
temp-> name = added.name;
temp-> height = added.height;
//if the first element
if(size == 0)
{
head = temp;
tail = temp;
temp->next = NULL;
size++;
}
else
{
temp->next = head;
head = temp;
size++;
//time to exit!
temp = NULL;
delete pointer;
}
}
also changed linkedlist doublel = linkedlist(lib, 3); to
linkedlist * doublel = new linkedlist(lib,3);
doublel->print();
in main() file
I have no idea how to delete in a circular link list. For example the head was B, so the list will go from "B, C, D, E, A". The first node will always pick a number from 1-5 which I keep reducing using the counter, so for example if "B" picked 3, the count will start unto it's next node which is "C" so counting from "C", we will have to eliminate "E", once "E" was eliminated.
The new head aka the picker will start unto the next node after the eliminated node, so the next set of nodes will become "A,B,C,D", this function must repeat until there is only 1 last standing node.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include <string>
#include <ctime>
using namespace std;
/*
* Node Declaration
*/
struct node
{
string name;
struct node *next;
};
node *t, *head;
node *ex;
int paper;
int ctr = 5;
int num;
void create(string sname)
{
node *n = new node;
n->name = sname;
if (head == NULL)
{
head = n;
t = n;
}
else
{
t->next = n; // connects the nodes
t = t->next; // moves the connecter to the t= last
}
t->next = head;
}
/*
* Deletion of element from the list
*/
void delete_element(string value)
{
}
//Display Circular Link List
void display()
{
node *temp = new node;
temp = head;
if ((head == NULL) && (t == NULL))
{
}
for (int j = 1; j <= 5; j++)
{
cout << temp->name << "\n";
temp = temp->next;
}
}
void firstpic()
{
srand(time(NULL));
paper = rand() % 5 + 1;
int fctr = 5;
bool p1 = 0, p2 = 0, p3 = 0, p4 = 0, p5 = 0;
if (paper == 1)
{
create("A");//1
fctr--;
}
else if (paper == 2)
{
create("B");//2
p2 = 1;
}
else if (paper == 3)
{
create("C");//2
p3 = 1;
}
else if (paper == 4)
{
create("D");//2
p4 = 1;
}
else if (paper == 5)
{
create("E");//2
p5 = 1;
}
if (p1)
{
create("B");
create("C");
create("D");
create("E");
}
else if (p2)
{
create("C");
create("D");
create("E");
create("A");
}
else if (p3)
{
create("D");
create("E");
create("A");
create("B");
}
else if (p4)
{
create("E");
create("A");
create("B");
create("D");
}
else if (p5)
{
create("A");
create("B");
create("C");
create("D");
}
}
void drawn()
{
node *holder = head;
ex = holder->next;
cout << holder->name << " has drawn: " <<num <<endl;
}
int main()
{
head == NULL;
t == NULL;
srand(time(NULL));
firstpic();
display();
num = rand() % ctr + 1;
drawn();
system("pause>nul");
return 0;
}
Here is something that may suit your needs:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <ctime>
using namespace std;
/*
* Node Declaration
*/
struct node
{
string name;
struct node *next;
};
node *tail, *head;
void addNode(string sname)
{
node *n = new node;
n->name = sname;
if (head == NULL) {
head = n;
tail = n;
} else {
tail->next = n; // connects the nodes
tail = tail->next; // moves the connecter to the t= last
}
tail->next = head;
}
/*
* Deletion of element from the list
*/
void removeNode(string value)
{
// no elements
if (head == NULL) {
return;
}
node *n = head;
node *prev = tail;
// 1 element
if(n == prev) {
if(n->name == value) {
delete n;
head = tail = NULL;
}
return;
}
bool found = false;
// search
do {
if(n->name == value) {
found = true;
break;
}
prev = n;
n = n->next;
} while (n != head);
// no such element
if(!found) {
return;
}
prev->next = n->next;
if(n == head) {
head = n->next;
} else if(n == tail) {
tail = prev;
}
delete n;
}
void displayList()
{
if (head == NULL) {
cout << "empty!" << endl;
return;
}
node *n = head;
do {
cout << n->name << "\n";
n = n->next;
} while (n != head);
cout << endl;
}
void createList()
{
const int count = 5;
std::string names[count] = {"A", "B", "C", "D", "E"};
int nameIndex = rand() % count;
for(int i = 0; i<count; ++i) {
nameIndex += 1;
nameIndex %= count;
addNode(names[nameIndex]);
}
}
int main()
{
srand(time(NULL));
head = NULL;
tail = NULL;
createList();
displayList();
removeNode("A");
displayList();
removeNode("A");
displayList();
removeNode("E");
displayList();
removeNode("B");
displayList();
removeNode("C");
displayList();
removeNode("D");
displayList();
system("pause>nul");
return 0;
}
Note that during node deletion you should take care of such cases as:
No elements case
Last 1 element to be deleted
Head deletion
Tail deletion
Also, never do things like you did in your firstpic() function: it is a painfull way to do it. drawn() function seems not to do anything that makes sence, but it is out of question's scope.
So my assignment requires us to use doubly linked lists to add or multiply numbers together and print them out. I was able to get it to work for whole numbers, but I can't figure out what to change to make it work for decimal numbers as well. Here's what I've got so far. I know it's not the most efficient or cleanest code, but I can try to clarify stuff if it doesn't make sense to you
For example this program will work fine if I do 50382+9281 or 482891*29734,but I need to get it to work for something like 4.9171+49.2917 or 423.135*59
EDIT: Pretend the int values are doubles. I changed it on my actual code, but the result when I do the math is still giving me a whole number so I need to figure out how to insert the decimal at the right place
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
using namespace std;
// A recursive program to add two linked lists
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
// A linked List Node
struct node
{
int data;
node* next;
node *prev;
};
typedef struct node node;
class LinkedList{
// public member
public:
// constructor
LinkedList(){
int length = 0;
head = NULL; // set head to NULL
node *n = new node;
n->data = -1;
n->prev = NULL;
head = n;
tail = n;
}
// This prepends a new value at the beginning of the list
void addValue(int val){
node *n = new node(); // create new Node
n->data = val; // set value
n->prev = tail; // make the node point to the next node.
// head->next = n;
// head = n;
// tail->next = n; // If the list is empty, this is NULL, so the end of the list --> OK
tail = n; // last but not least, make the head point at the new node.
}
void PrintForward(){
node* temp = head;
while(temp->next != NULL){
cout << temp->data;
temp = temp->next;
}
cout << '\n';
}
void PrintReverse(){
node* temp = tail;
while(temp->prev != NULL){
cout << temp->data;
temp = temp->prev;
}
cout << '\n';
}
void PrintReverse(node* in){
node* temp = in;
if(temp->prev== NULL){
if(temp->data == -1)
cout << temp->data << '\n';
}
else{
cout << temp->data << '\n';
temp = temp->prev;
PrintReverse(temp);
}
}
// returns the first element in the list and deletes the Node.
// caution, no error-checking here!
int popValue(){
node *n = head;
int ret = n->data;
head = head->next;
delete n;
return ret;
}
void swapN(node** a, node**b){
node*t = *a;
*a = *b;
*b = t;
}
node *head;
node *tail;
// Node *n;
};
/* A utility function to insert a node at the beginning of linked list */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node = (struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* A utility function to print linked list */
void printList(struct node *node)
{
while (node != NULL)
{
printf("%d", node->data);
node = node->next;
}
// printf("\n");
}
// A utility function to swap two pointers
void swapPointer( node** a, node** b )
{
node* t = *a;
*a = *b;
*b = t;
}
/* A utility function to get size of linked list */
int getSize(struct node *node)
{
int size = 0;
while (node != NULL)
{
node = node->next;
size++;
}
return size;
}
// Adds two linked lists of same size represented by head1 and head2 and returns
// head of the resultant linked list. Carry is propagated while returning from
// the recursion
node* addSameSize(node* head1, node* head2, int* carry)
{
// Since the function assumes linked lists are of same size,
// check any of the two head pointers
if (head1 == NULL)
return NULL;
int sum;
// Allocate memory for sum node of current two nodes
node* result = (node *)malloc(sizeof(node));
// Recursively add remaining nodes and get the carry
result->next = addSameSize(head1->next, head2->next, carry);
// add digits of current nodes and propagated carry
sum = head1->data + head2->data + *carry;
*carry = sum / 10;
sum = sum % 10;
// Assigne the sum to current node of resultant list
result->data = sum;
return result;
}
// This function is called after the smaller list is added to the bigger
// lists's sublist of same size. Once the right sublist is added, the carry
// must be added toe left side of larger list to get the final result.
void addCarryToRemaining(node* head1, node* cur, int* carry, node** result)
{
int sum;
// If diff. number of nodes are not traversed, add carry
if (head1 != cur)
{
addCarryToRemaining(head1->next, cur, carry, result);
sum = head1->data + *carry;
*carry = sum/10;
sum %= 10;
// add this node to the front of the result
push(result, sum);
}
}
// The main function that adds two linked lists represented by head1 and head2.
// The sum of two lists is stored in a list referred by result
void addList(node* head1, node* head2, node** result)
{
node *cur;
// first list is empty
if (head1 == NULL)
{
*result = head2;
return;
}
// second list is empty
else if (head2 == NULL)
{
*result = head1;
return;
}
int size1 = getSize(head1);
int size2 = getSize(head2) ;
int carry = 0;
// Add same size lists
if (size1 == size2)
*result = addSameSize(head1, head2, &carry);
else
{
int diff = abs(size1 - size2);
// First list should always be larger than second list.
// If not, swap pointers
if (size1 < size2)
swapPointer(&head1, &head2);
// move diff. number of nodes in first list
for (cur = head1; diff--; cur = cur->next);
// get addition of same size lists
*result = addSameSize(cur, head2, &carry);
// get addition of remaining first list and carry
addCarryToRemaining(head1, cur, &carry, result);
}
// if some carry is still there, add a new node to the fron of
// the result list. e.g. 999 and 87
if (carry)
push(result, carry);
}
node* reverse_list(node *m)
{
node *next = NULL;
node *p = m;
node *prev;
while (p != NULL) {
prev = p->prev;
p->prev = next;
next = p;
p = prev;
}
return prev;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Multiply2(node* n1, node* n2);
int digitsPerNode = 2;
node* result;
node* resultp = result;
node* resultp2 = result;
void Multiply(node* n1, node* n2)
{
if (n2->prev != NULL)
{
Multiply(n1, n2->prev);
}
Multiply2(n1, n2);
resultp2 = resultp = resultp->prev;
}
void Multiply2(node* n1, node* n2)
{
if (n1->prev != NULL)
{
Multiply2(n1->prev, n2);
}
if (resultp2 == NULL)
{
resultp2->data = 0;
result = resultp = resultp2;
}
int m = n1->data * n2->data + resultp2->data;
int carryon = (int)(m / pow(10, digitsPerNode));
resultp2->data = m % (int)pow(10, digitsPerNode);
if (carryon > 0)
{
if (resultp2->prev == NULL)
{
resultp2->prev->data = carryon;
}
else
{
resultp2->prev->data += carryon;
}
}
resultp2 = resultp2->prev;
}
/* int* buffer;
int lenBuffer = 0;
void multiplyHelper(int v, node* , int o);
void addToBuffer(int v, int i);
node* multiply(node* num1, node* num2)
{
if (num1 == NULL || num2 == NULL) return NULL;
int length1 = getSize(num1);
int length2 = getSize(num2);
if (length1 > length2) return multiply(num2, num1);
// initialize buffer
lenBuffer = length1 + length2;
buffer = new int[lenBuffer];
memset(buffer, 0, sizeof(int) * lenBuffer);
// multiply
int offset = 0;
node* anode = num1;
while (anode && anode->data!= -1)
{
multiplyHelper(anode->data, num2, offset);
anode = anode->prev;
offset++;
}
// transfer buffer to a linked list
node* h;
int pos = 0;
while (pos < lenBuffer && buffer[pos] == 0) pos++;
if (pos < lenBuffer)
{
node* temp;
temp->data = buffer[pos++];
h = temp;
anode = h;
while (pos < lenBuffer)
{
node* temp;
temp->data = buffer[pos++];
anode->prev = temp;
anode = anode->prev;
}
}
delete buffer;
lenBuffer = 0;
buffer = NULL;
cout << h->data << endl;
return h;
}
// multiply a single digit with a number
// called by multiply()
void multiplyHelper(int value, node* head, int offset)
{
// assert(value >= 0 && value <= 9 && head != NULL);
if (value == 0) return;
node* anode = head;
int pos = 0;
while (anode != NULL)
{
int temp = value * anode->data;
int ones = temp % 10;
if (ones != 0) addToBuffer(ones, offset + pos + 1);
int tens = temp / 10;
if (tens != 0) addToBuffer(tens, offset + pos);
anode = anode->prev;
cout << anode->data;
pos++;
}
}
// add a single digit to the buffer at place of index
// called by multiplyHelper()
void addToBuffer(int value, int index)
{
// assert(value >= 0 && value <= 9);
while (value > 0 && index >= 0)
{
int temp = buffer[index] + value;
buffer[index] = temp % 10;
value = temp / 10;
index--;
}
}*/
// Driver program to test above functions
int main(int argc, char *argv[])
{
char filename[50];
string name= argv[1];
string dig;
name.erase(0,9);//Parse input to only get input file.
ifstream file;
int digits;
for(int i = 0; i < name.length(); i++){
if(name.at(i) == ';'){
// dig = name.substr(0,name.length()-i);
name = name.substr(0,name.length()-i);
}
}
//cout << dig << endl;
//file.open("input.txt");
file.open(name.c_str());
digits = 2;
///////
///////////////////////////////////////////////////////////////////////
int words = 0;
int numbers = 0;
while(!file.eof()) //Goes through whole file until no more entries to input
{
string word;
getline(file,word); //Inputs next element as a string
// word << file;
//cout << word << '\n';
int x = 0;
node *head1 = NULL, *head2 = NULL, *result = NULL;
int counter = 0;
int t1index = 0; //keep tracks of nodes to multiply
int t2index = 0;
char operatorX;
LinkedList tempList1;
LinkedList tempList2;
while(x<word.length()) //Loops through each string input
{
//if(x<word.length()&&isalpha(word.at(x))) //Checks that x is in bounds and that char at position x is a letter
if(x<word.length()&&isdigit(word.at(x))) //Checks that x is in bounds and that char at position x is a number/digit
{
int start = x;
while(x<word.length()&&isdigit(word.at(x))) //Loops past the number portion
{
x++;
}
string temp = word.substr(start, x).c_str();
// cout << temp << '\n';
for(int i = 0; i < temp.length();i++){
tempList1.addValue(atoi(temp.substr(i, 1).c_str()));
// push(&head1, atoi(temp.substr(i, 1).c_str()));
counter++;
t1index++;
}
//search for the operator
while(x<word.length()){
if(x<word.length()&& (!isspace(word.at(x)) && !isdigit(word.at(x))))
{
while(x<word.length()&&(!isspace(word.at(x)) && !isdigit(word.at(x)))) //Loops past the letter portion
{
// cout << (word.at(x))<< '\n';
operatorX = word.at(x);
x++;
}
//search second value
while(x<word.length()){ //second value find
//start
if(x<word.length()&&isdigit(word.at(x))) //Checks that x is in bounds and that char at position x is a number/digit
{
int start = x;
while(x<word.length()&&isdigit(word.at(x))) //Loops past the number portion
{
x++;
}
string temp = word.substr(start, x).c_str();
for(int i = 0; i < temp.length();i++){
tempList2.addValue(atoi(temp.substr(i, 1).c_str()));
// push(&head2, atoi(temp.substr(i, 1).c_str()));
// cout << atoi(temp.substr(i, 1).c_str());
counter++;
}
//////START READING NUMBERS BACKWARDS
LinkedList finalList;
node* tempA = tempList1.tail;
node* tempB = tempList2.tail;
// multiply(tempA, tempB);
//ADDITION
while(tempA != NULL){
if(tempA->data != -1){
push(&head1,tempA->data);
// cout << tempA->data;
}
tempA = tempA->prev;
}
while(tempB != NULL){
if(tempB->data != -1){
push(&head2, tempB->data);
// cout << tempB->data;
}
tempB = tempB->prev;
}
// multiply(head1, head2);
// result = multiply(head1, head2);
// tempList1.PrintReverse();
addList(head1, head2, &result);
printList(head1);
cout << operatorX;
printList(head2);
cout << "=";
printList(result);
cout << endl;
}
else{
x++;
}
//end
}
}
else{
x++;
}
}
}
else //If char at position x is neither number or letter skip over it
{
x++;
}
}
}
}
Since you're working in C++, use a template/overloaded operators. Cast your ints to a floating point type as necessary. See e.g.:
C++ Template problem adding two data types
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 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.