I had to implement a Linked HashTable for a project. Now I have to come up with an excercise and a solution to it using my hashtable. Everything works just fine, except I get random Segfault errors.
By Random I mean: It is the same line of code that causes it, but always at different times, calls.
I tested my code in Atom, Codeblocks and in Visual Studio Code. Both Atom and CB threw SegFault error, but VS Code ran it just fine without a problem.
NOTE: THIS IS NOT THE FULL/REAL CODE. It's part of a header file that is included in the main.cpp file which is then compiled and ran.
The Code:
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
//List:
template<class T>
struct Node
{
string data;
Node *next;
};
class List
{
private:
Node *head, *tail;
int length;
friend class HashTable;
public:
List();
List(const List &L);
//~List() {delete this;};
List& operator =(List L);
int find(string);
void insert(string value);
void remove_head();
void remove_poz(int);
void remove_tail();
void clear();
void display();
};
List::List()
{
head = NULL;
tail = NULL;
length = 0;
}
template<>
string List<string>::findByIndex(int ind)
{
int i = 0;
Node<string>* temp = new Node<string>;
temp = head;
while (temp != NULL)
{
i++;
if (i == ind) return temp->data;
temp = temp->next;
}
delete temp;
return "-1";
}
template<class T>
void List<T>::remove_head()
{
Node<T>* temp = new Node<T>;
temp = head;
head = head->next;
delete temp;
length--;
}
template<class T>
void List<T>::remove_pos(int pos)
{
int i;
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
for (i = 1; i < pos; ++i)
{
prev = curr;
curr = curr->next;
}
if (curr)
{
prev->next = curr->next;
length--;
}
else cout << "Error" << endl;
}
template<class T>
void List<T>::remove_tail()
{
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
while (curr->next != NULL)
{
prev = curr;
curr = curr->next;
}
tail = prev;
prev->next = NULL;
delete curr;
length--;
}
//HashTable:
class HashTable
{
private:
List *table;
float load, stored;
int slots;
friend class List;
public:
HashTable();
HashTable(int);
~HashTable();
int hashFunc(string key);
int findTable(string);
int findList(string);
HashTable& operator =(const HashTable&);
void resize(); //I need this one
void insert(string);
void remove(string);
void clear(int);
void clear();
void display();
};
HashTable::HashTable()
{
stored = 0;
load = 0.00;
slots = 15;
table = new List[slots];
}
int HashTable::hashFunc(string key)
{
int g, h = 0;
unsigned int i;
for (i = 0; i < key.size(); ++i)
{
h = (h << 4) + (int)(key[i]);
g = h & 0xF0000000L;
if (g != 0)
{
h = h ^ (g >> 24);
}
h = h & ~g;
}
return h % slots;
}
template<class T>
void HashTable<T>::remove(T value)
{
int ind = hashFunc(value);
int findInd = table[ind].findByValue(value);
if (findInd == 0)
table[ind].remove_head();
else if (findInd < table[ind].length)
table[ind].remove_pos(findInd);
else table[ind].remove_tail();
if (table[ind].isEmpty()) occupied--;
stored--;
load = stored / slots;
}
The function that would cause the segfault:
(This would be called over and over again in a loop till I don't have more elements in my table)
string reakcio(HashTable<string>& HT, int tarolok)
{
const int anyagszam = rand() % 4 + 2; //Min 2, Max 5 anyag hasznalodik
int i = 0, j;
string anyagok[5];
string eredmeny;
for(j = 0; j < tarolok && i < anyagszam; ++j) //elemek kivetele
{
while(!HT.table[j].isEmpty())
{
anyagok[i++] = HT.table[j].findByIndex(1); //This line right here is the culprit :(
HT.remove(anyagok[i-1]);
}
}
const int siker = rand() % 4 + 0; //75% esely a sikerre
if (siker)
{
eredmeny = anyagok[0];
for(i = 1; i < anyagszam; ++i)
eredmeny += " + " + anyagok[i];
}
else
eredmeny = "Sikertelen reakcio";
return eredmeny;
}
(Note: only the functions that might be needed are shown here)
Every element of my hashtable, or of my lists is a 10 character long random string value.
srand(time(NULL)) is used before the function call in main.cpp
Any help or advice would be much appreciated, as I'm stuck at this and I really need to move on to the next portion of my exercise, but I can't without this.
The main.cpp file:
#include <iostream>
//#include "LinkedHash.h"
#include "functions.cpp"
int main()
{
HashTable<string> Anyagok;
int tarolok;
tarol(Anyagok); //Stores the data from file, no problem here, functions.cpp
tarolok = Anyagok.getSlots();
srand(time(NULL));
int i = 1;
while (Anyagok.getStored() > 5 )
cout<<reakcio(Anyagok, tarolok)<<" "<<i++<<endl;
return 0;
}
The LinkedHash.h contains the hashtable and the list, the functions.cpp contains the problematic function.
EDIT:
By suggestion I changed out the
Node<string>* temp = new Node<string>;
temp = head;
part to
Node<string>* temp = head;
Also removed the delete line.
But my problem is still the same :/
Everything works just fine, except I get random Segfault errors
Then nothing works at all.
A first review show little care to the cornercases in the list class. You need to define a correct behavior for
operation on empty lists
operation on first and last element
key not found during search
Notable errors found:
remove_head, remove_tail will segfault on empty list. head is NULL. head->next is invalid memory access. Similar errors are all over the implementation.
HashTable<T>::remove(T value) will always remove something. Even if the value argument is not in the hashtable. This is deeply flawed
findByIndex returning "-1" make no sense. "-1" is a valid input.
Node<T>* temp = new Node<T>;temp = head;. You just leaked memory. You need a pointer to manipulate node addresses. You should not instantiate Nodes to get a pointer. This is not an issue (ie not noticeable) for a small projet, but unacceptable for a real implementation.
Related
I write a code for insertion sort for integer data in linked list in c++, I referred to the algorithms on the Internet, and finally took the following code using array as a basic concept for my version.
however, the sorting always ignore my first element,(but all the other element is ordered well).
I have tried checking my loop statement, checking the pointer address while looping (because my key pointer loop at first time didn't go into the judge pointer loop), checking the shifting mechanism while comparing, but I cannot find my logic problem.
(I know someone would said I doesn't provide enough data for you to help me, but I have been checking these things for two days, including asking friends and searching the solutions existed on website. So I really hope someone can answer me without blame, thank you.)
array version(on the internet)
#include <iostream>
void InsertionSort(int *arr, int size){
for (int i = 1; i < size; i++) {
int key = arr[i];
int j = i - 1;
while (key < arr[j] && j >= 0) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}
linked list version(by my own)
Node class used in my version
class Node
{
public:
Node()
{
next = NULL;
pre = NULL;
}
Node(int n)
{
data = n;
next = NULL;
pre = NULL;
}
int getData() { return data; }
Node *getNext() { return next; }
Node *getPre() { return pre; }
void setData(int d) { data = d; }
void setNext(Node *n) { next = n; }
void setPre(Node *p) { pre = p; }
private:
int data;
Node *next, *pre;
};
class List
{
public:
List() { list = NULL; }
List(int n) { generate(n); }
void generate(int n)
{
int j;
list = NULL;
for(j = 0;j < n;j ++)
generate();
}
void generate()
{
Node *buf = new Node(rand());
buf->setNext(list); //list->NODE2.next->NODE1.next->NULL
if(list != NULL)
list->setPre(buf);
list = buf;
}
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;// judge is the value that is going to compare with key
int key;
for(keyptr = list->getNext(); keyptr != NULL;
keyptr = keyptr->getNext()){
//if we set list as 5,7,6 ; 6 is key
key = keyptr->getData();//store the key value for the setting after shifting
breakByCompare = 0;
for(judgeptr = keyptr->getPre() ; judgeptr->getPre()!= NULL;
judgeptr= judgeptr->getPre()){
//list: 5,7,6 ; 7 is judge
if(judgeptr->getData() > key){
// 7>6, so we shift 7 to the position which was for 6
judgeptr->getNext()->setData(judgeptr->getData());// list: 5,7,7 ;
cout << judgeptr->getData() << " , " << keyptr->getData() << endl;
}
else{
break;
}
}
judgeptr->getNext()->setData(key);// list: 5,6,7
}
}
void print()
{
Node *cur = list;
while(cur != NULL)
{
cout<<cur->getData()<<" ";
cur = cur->getNext();
}
cout<<endl;
}
private:
Node *list;
};
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#define SIZE 100
int main()
{
srand(time(NULL));
List *l = new List(10);
l->print();
l->insertionSort();
l->print();
}
One of the most important difference between a linked list and an array is that it is sometimes required to handle the first element as a special case.
Here is a fixed version of your sorting method :
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;
int key;
for(keyptr = list->getNext(); keyptr != NULL; keyptr = keyptr->getNext()){
key = keyptr->getData();
breakByCompare = 0;
// I replaced judgeptr->getPre() by judgeptr in the condition
// to allow the backward loop to go until the root
for(judgeptr = keyptr->getPre() ; judgeptr != NULL; judgeptr= judgeptr->getPre()){
if(judgeptr->getData() > key){
judgeptr->getNext()->setData(judgeptr->getData());
cout << judgeptr->getData() << " , " << key << endl;
}
else break;
}
// Here is the special case : we must support a null judgeptr
// and replace its next element by the list
if (judgeptr) judgeptr->getNext()->setData(key);
else list->setData(key);
}
}
I have to implement a HashTable with linked lists. It is almost done (still missing templates, will do in time), but I'm stuck at something.
Basically, I want to resize my hashtable when the load factor reaches a given value, say 50%. But I don't know how I should do it.
I have a basic idea:
Create a temporary HT with the new size
Hash every data in every list from the old HT to the temporary one
Delete the old HT
Return the temporary HT
I can't figure out an implementation for it though...
Here is what I have so far:
//List:
struct Node
{
string data;
Node *next;
};
class List
{
private:
Node *head, *tail;
int length;
friend class HashTable;
public:
List();
List(const List &L);
//~List() {delete this;};
List& operator =(List L);
int find(string);
void insert(string value);
void remove_head();
void remove_poz(int);
void remove_tail();
void clear();
void display();
};
List::List()
{
head = NULL;
tail = NULL;
length = 0;
}
List::List(const List& L)
{
Node** temp = &head;
const Node* source = L.head;
while(source)
{
*temp = new Node(*source);
temp = &(*temp)->next;
source = source->next;
}
}
List& List::operator =(List L)
{
swap(head, L.head);
return *this;
}
void List::insert(string value)
{
Node* temp = new Node;
temp->data = value;
temp->next = NULL;
if (!head)
head = temp;
if (tail)
tail->next = temp;
tail = temp;
length++;
}
void List::display()
{
Node *temp = new Node;
temp = head;
while (temp != NULL)
{
cout<<temp->data<<" ";
temp = temp->next;
}
delete temp;
}
//HashTable:
class HashTable
{
private:
List *table;
float load, stored;
int slots;
friend class List;
public:
HashTable();
HashTable(int);
~HashTable();
int hashFunc(string key);
int findTable(string);
int findList(string);
HashTable& operator =(const HashTable&);
void resize(); //I need this one
void insert(string);
void remove(string);
void clear(int);
void clear();
void display();
};
HashTable::HashTable()
{
stored = 0;
load = 0.00;
slots = 15;
table = new List[slots];
}
HashTable::HashTable(int size)
{
stored = 0;
load = 0.00;
slots = size;
table = new List[slots];
}
int HashTable::hashFunc(string key)
{
unsigned int i, ind = 0;
for (i = 0; i<key.length(); ++i)
ind = ind + key[i];
ind %= slots;
return ind;
}
HashTable& HashTable::operator =(const HashTable& T) //I suppose it is incorrect
{
int i;
HashTable temp(T.slots);
for (i = 0; i < slots; ++i)
{
temp.table[i] = T.table[i];
}
return temp;
}
void HashTable::insert(string value)
{
int ind = hashFunc(value);
table[ind].insert(value);
if (!table[ind].head->next) stored++;
load = stored / slots;
if (load > 0.50) resize();
}
(Note: only the functions that might be needed are shown here)
Any help, correction or suggestion would be much appreciated :)
UPDATE:
Managed to pull this one off:
void HashTable::resize()
{
int i;
int newSize = slots * 2;
int newLoad = stored / newSize;
HashTable HT(newSize);
Node* temp;
for (i = 0; i < slots; ++i)
{
temp = table[i].head;
while (temp != NULL)
{
HT.insert(temp->data);
temp = temp->next;
}
}
}
Now I have a new HashTable named HT, with double the size of the original one, and all elements have been inserted correctly.
But I don`t know how to proceed.
The easiest way to proceed is to add a swapContents() method to your HashTable class:
void HashTable::swapContents(HashTable & rhs)
{
std::swap(table, rhs.table);
std::swap(load, rhs.load);
std::swap(stored, rhs.stored);
std::swap(slots, rhs.slots);
// any other member-variables of the HashTable class would get swapped here too
}
... then call swapContents(HT) at the end of your resize() method, so that HT becomes the older/smaller HashTable (and gets discarded) while this becomes the newer/larger table.
This is my code for an implementation of a doubly linked list that inherits previous code from a single linked list, I am currently having trouble with a linker error and surfed the web for the past hour looking for an answer to my problem and found nothing so far to help me. This is my last resor can anyone help?
Specifically the error i get when i try to use g++ to link my .o files is:
DoublyList.o:DoublyList.cpp:(.text+0xf): undefined reference to
`LinkedList::LinkedList()'
collect2.exe: error: ld returned 1 exit status
I have found very similar questions asked but none of the answers helped me or at least I do not know how to implement them in my code specifically, any help will be apprectiated.
My LinkedList class
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
using namespace std;
struct node
{
float value;
node *next;
};
class LinkedList
{
private:
node *first;
public:
LinkedList();
virtual void insert(float val);
virtual void del(float val);
virtual void read();
virtual int search(float val);
};
#endif
My LinkedList class definition
#include <iostream>
#include "LinkedList.h"
using namespace std;
LinkedList::LinkedList()
{
this->first = NULL;
}
void LinkedList::insert(float val)
{
if(this->first==NULL or this->first->value >= val)
{
node* a_node = new node();
a_node->value = val;
this->first = a_node;
return;
}
node* n = new node();
n = this->first;
node* new_node = new node();
new_node->value = val;
while(n->next != NULL and n->next->value < new_node->value)
{
n = n->next;
}
new_node->next = n->next;
n->next = new_node;
}
void LinkedList::del(float val)
{
node* n = this->first;
node* prev = new node();
prev = n;//in case if it is the first value
int i = this->search(val);
if(this->first->value == val)
{
this->first = this->first->next;
return;
}
if(i != -1)
{
for(int j = 0; j < i; j++)
{
prev = n;
n = n->next;
}
}
//one last check
if(n->value == val)
{
prev->next = n->next;
}
}
void LinkedList::read()
{
node* n = this->first;
int i = 1;
while(n != NULL)
{
cout << i << ". " << n->value << endl;
n = n->next;
i++;
}
}
int LinkedList::search(float val)
{
int i = 0;
node* n = this->first;
while(n != NULL)
{
if(n->value == val)
return i;
else
{
n = n->next;
i++;
}
}
return -1;
}
My doublylist class
#ifndef DOUBLYLIST_H
#define DOUBLYLIST_H
#include "LinkedList.h"
class DoublyList: public LinkedList
{
public:
struct node
{
float value;
node * next;
node * prev;
};
node * first;
DoublyList();
void insert(float val);
void del(float val);
void read();
int search(float val);
};
#endif
My Doubly List definiton
#include <cstddef>
#include "DoublyList.h"
#include "LinkedList.h"
using namespace std;
//constructor
DoublyList::DoublyList()
{
first = NULL;
}
//Insert a node into the correct position in the doubly linked list
void DoublyList::insert(float val)
{
//if linked list is empty or val <= the first node
if(this->first == NULL or this->first->value >= val)
{
node * a_node = new node();
a_node->value = val;//set node's value
//begin replacing and assigning pointers
a_node->next = this->first;
a_node->prev = NULL;
this->first = a_node;
return;
}
node * n = new node();
n = this->first;
node * new_node = new node();
new_node->value = val;
node * prev_node = new node();
while(n->next != NULL and n->next->value < new_node->value)
{
prev_node = n;
n = n->next;
}
prev_node->next = new_node;
new_node->next = n->next;
new_node->prev = prev_node;
n->next = new_node;
}
void DoublyList::del(float val)
{
node * n = this->first;
int i = this->search(val);
//if first node
if(this->first->value == val)
{
this->first = this->first->next;
this->first->prev = NULL;
return;
}
//if value found
if(i != -1)
{
for(int j = 0; j < i; j++)
{
n = n->next;
}
//if a middle node
if(n->value == val and n->next != NULL)
{
n->prev->next = n->next;
return;
}
//if last node
if(n->prev != NULL)
{
n->prev->next = n->next;
}
}
return;//value not found so return
}
void DoublyList::read() { }
int DoublyList::search(float val) { }
Edit: Forgot to mention this error specifically happens aruond line 8 of DoublyList.cpp, this was from previous trials to link the .o files.
The command I used to call the linker is
g++ -g main2.cpp DoublyList.o
Where main2.cpp is the code that contains my main function to test the code.
Thanks to xskxzr the solution was to also link LinkedList.o along with all the rest of the .o files. If anyone ever has the same problem this is the answer.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Let me first start by saying I do not have access to debuggers and I'm using Nano as my editor
Currently, with my calculator, I am beating my head against a brick wall(segmentation fault). I've tried going through my pointers to discover what my problem is, but my lack of experience/knowledge has only gotten me so far. Let me explain what works so far in my program. Currently, I am able to store hexadecimal numbers in a linked list and add them together. The problem comes from my multiplication method.Somehow leftNode is becoming NULL midway through the multiplication method throwing a segmentation fault. I'm wondering at what point does leftNode become NULL?
Multiplication Method:
LList Calculator::multiply(LList& left, LList& right) {
LList prodSum;
listnode *leftNode = (left.next());
int zeros = 0;
for(;;) {
if(leftNode == NULL) break;
int lval = leftNode->data;
LList curList;
for(int i = 0; i < zeros; i++) {
curList.insertTail(0);
}
right.reset();
listnode *rightNode = (right.next());
int carry = 0;
while(rightNode != NULL) {
int rval = rightNode->data;
int product = lval * rval + carry;
carry = product / 16;
product %= 16;
curList.insertTail(product);
rightNode = (right.next());
}
while(carry) {
curList.insertTail(carry % 16);
carry /= 16;
}
prodSum = *add(prodSum, curList);
leftNode = (left.next()); // eventually causes a segmentation fault
leftNode->data << endl;
++zeros;
}
return prodSum;
}
Classes related to multiplication:
class listnode {
public:
element data;
listnode * next;
};
class LList {
private:
listnode * head;
listnode * tail;
listnode * view;
public:
LList();
~LList();
void read();
listnode* next();
void reset();
void print();
void insertTail(element val);
void clean();
element deleteHead();
};
class Calculator {
public:
Calculator();
//inline LList* add(LList& left, LList& right); works
inline LList multiply(LList& left, LList& right);
};
Calculator::Calculator() {
};
Other methods related to traversing nodes:
listnode* LList::next() {
listnode* temp = view;
if(temp != NULL)
view = view->next;
if(view == NULL) {
}
return temp;
};
void LList::reset() {
view = head;
}
LList::LList(){
head = NULL;
view = NULL;
};
void LList::insertTail(element val) {
listnode * temp;
temp = new listnode;
temp -> data = val;
temp -> next = NULL;
if(head == NULL) {
head = temp;
view = head;
}
else
tail -> next = temp;
tail = temp;
};
void LList::clean() {
while(head != NULL)
deleteHead();
};
element LList::deleteHead() {
listnode * temp;
temp = head;
head = head -> next;
delete temp;
return temp -> data;
};
LList::~LList(){
delete head;
};
it's me again.
One exception occurs after the line you marked: // eventually causes a segmentation fault, there seems to be a partially-formed line for sending leftNode->data to cout, but on the final iteration through left's nodes, leftNode = (left.next()); will set leftNode to NULL, so a dereference here might be causing the fault.
One other problem is that no copy constructor or assignment operator is defined for LList, so this line: prodSum = *add(prodSum, curList); will give prodSum a set of list nodes that will be deleted right after.
However, LList's destructor only seems to delete the head node, not the whole list, so there's a grab-bag of invalid and valid going on.
Also, multiply returns prodSum, so the lack of a copy constructor will make something similar happen.
I'm including a version of your code that seems to work. I had to make my own add function, just because I don't see it here.
I made the destructor delete all of the LList's nodes.
I marked the default copy constructor and assignment operator =delete because the default implementations do the wrong thing.
In order to pass LList objects around by value, I added a move constructor and a move assignment operator. These pass allocated nodes from one object to another, and only one object is allowed to keep one set of nodes, so you don't have to worry about double-destruction.
#include <iostream>
#include <string>
typedef int element;
class listnode {
public:
element data;
listnode * next;
};
class LList {
listnode *head, *tail, *view;
public:
LList() { head = view = tail = NULL; }
LList(LList&& src) : head(src.head), tail(src.tail), view(src.view) { src.head = src.tail = src.view = nullptr; }
LList(const LList&) = delete;
~LList() { clean(); }
LList& operator = (LList&& src) {
clean();
/* OK here */
head = src.head;
tail = src.tail;
view = src.view;
src.head = src.tail = src.view = nullptr;
return *this;
}
LList& operator = (const LList&) = delete;
listnode* next() {
listnode* temp = view;
if(temp) view = view->next;
return temp;
}
void reset() { view = head; }
void print();
void insertTail(element val) {
listnode* temp = new listnode;
temp->data = val;
temp->next = NULL;
if(!head) { view = head = temp; }
else { tail->next = temp; }
tail = temp;
}
void clean() { while(head) deleteHead(); }
element deleteHead() {
listnode* temp = head;
head = head->next;
const element data = temp->data;
delete temp;
return data;
}
};
LList add(LList& left, LList& right) {
LList sum;
int carry = 0;
left.reset();
right.reset();
for(;;) {
const listnode* leftNode = left.next();
const listnode* rightNode = right.next();
if(!leftNode && !rightNode) break;
if(leftNode) carry += leftNode->data;
if(rightNode) carry += rightNode->data;
sum.insertTail(carry % 16);
carry /= 16;
}
if(carry) sum.insertTail(carry);
return sum;
}
LList multiply(LList& left, LList& right) {
LList prodSum;
listnode *leftNode = left.next();
int zeros = 0;
for(;;) {
if(!leftNode) break;
int lval = leftNode->data;
LList curList;
for(int i = 0; i < zeros; i++) {
curList.insertTail(0);
}
right.reset();
listnode *rightNode = right.next();
int carry = 0;
while(rightNode) {
int rval = rightNode->data;
int product = lval * rval + carry;
carry = product / 16;
product %= 16;
curList.insertTail(product);
rightNode = right.next();
}
while(carry) {
curList.insertTail(carry % 16);
carry /= 16;
}
prodSum = add(prodSum, curList);
leftNode = left.next(); // eventually causes a segmentation fault
//std::cout << leftNode->data << std::endl;
++zeros;
}
return prodSum;
}
LList string_to_list(std::string hex_string) {
LList list;
for(size_t i=hex_string.length()-1; i+1; --i) {
char c = hex_string[i] | 0x20;
if (c >= '0' && c <= '9') list.insertTail(c - '0');
else if(c >= 'a' && c <= 'f') list.insertTail(c - 'a' + 10);
}
return list;
}
std::string list_to_string(LList& list) {
std::string hex_string;
list.reset();
for(;;) {
listnode* node = list.next();
if(!node) return hex_string;
static const char digits[] = "0123456789abcdef";
hex_string = digits[node->data] + hex_string;
}
}
int main() {
//LList list = string_to_list("1234aBcd");
//std::string s = list_to_string(list);
//std::cout << s << '\n';
LList left = string_to_list("111");
LList right = string_to_list("333");
LList prod = multiply(left, right);
std::cout << list_to_string(prod) << '\n';
}
i want to make a linked list ..
but the first node with a data and null link
if i input a string (123)
linked list be like this:
1/null - 2/point to the last one(1) - 3/point to the last one(2)
#include <iostream>
#include <string>
using namespace std;
struct link
{
int data;
link* next;
};
class LinkedList
{
private:
link* first;
public:
LinkedList(){}
void Add(string s)
{
for (int i = 0; i > s.length(); i++)
{
if (i == 0)
{
first->data = s[i];
first->next = NULL;
}
else
{
link* NewOne = new link;
NewOne->data = s[i];
NewOne->next = first;
first = NewOne;
}
}
}
void display()
{
cout << first->data;
}
};
int main()
{
LinkedList l1;
l1.Add("2734");
l1.display();
return 0;
}
what's the wrong in the code
You forget to allocate memory for first.
Following may help (using std::unique_ptr for free/correct memory management):
struct link{
char data;
std::unique_ptr<link> next;
};
class LinkedList {
private:
std::unique_ptr<link> first;
public:
void Set(const std::string& s){
for (auto c : s) {
std::unique_ptr<link> node = std::move(first);
first = std::make_unique<link>();
first->data = c;
first->next = std::move(node);
}
}
Live example
It also looks like you're storing characters in an int. Your output will be the ASCII value of the character rather than the raw int values.
I would recommend using unique pointers as Jarod42 has done. Having said that, this quick example below does not use them so you will need to call delete appropriately or use unique_ptr.
I added a last pointer to help traversal of the list as we make new links.
private:
Link * first;
Link *last;
int numLinks;
public:
LinkedList()
{
first = NULL;
last = NULL;
numLinks = 0;
}
Now for Add
void Add(string s)
{
for (int i = 0; i < s.length(); i++)
{
if (numLinks == 0)
{
first = new Link;
first->data = (s[i] - '0');
first->next = NULL;
last = first;
numLinks++;
}
else
{
Link * newLink = new Link;
newLink->data = (s[i] - '0');
newLink->next = NULL;
last->next = newLink;
last = newLink;
numLinks++;
}
}
}
The constructor does not initialize the first member. Subsequently, in Add():
for (int i = 0; i > s.length();i++){
if (i == 0){
first->data = s[i];
first->next = NULL;
}
This ends up dereferencing an uninitialized pointer, leading to undefined behavior.
There's also a problem with your display() too, but this is the main problem.