I'm trying to create a doubly linked list where each list has a first node, last node, and num_elements. However, for some reason, when I try to test the code in a UseList.cpp file, I can't get the num_elements to set to zero as default.
Let me show you what I mean:
In List.h:
template <class L>
class List
{
private:
Node<L> *first;
Node<L> *last;
int num_elements;
public:
// constructors and destructors
List();
[...]
}
[...]
template <class L>
List<L>::List() {
first = NULL;
last = NULL;
num_elements = 0;
}
[...]
This is the show method lower down in list.h:
template <class L>
// Print out the data in each node separated by a space.
void List<L>::show() {
cout << num_elements << endl;
Node<L> *current_node = first;
while (current_node != NULL) {
cout << current_node->data << " ";
current_node = current_node->next;
}
cout << endl;
}
Note that there is a cout statement there to print the num_elements.
This is the relevant part of UseList.cpp:
int main (int argc, char *argv[]) {
cout << "-----------------------------------------" << endl;
cout << "----------------LIST ONE-----------------" << endl;
cout << "-----------------------------------------" << endl;
List<int> *list1;
srand(time(NULL));
list1->show();
[...]
When show is called, it prints out "1" and gives me a segmentation fault. Why is num_elements defaulting to "1" instead of "0"?
When I do a cout in List<L>::List() {, nothing is printed... (this implies that the constructor never runs?)
Thanks for the help!
You are declaring a pointer to a List<int> and not initializing it to anything.
You have created a pointer to a List<int> object, but no object. So, currently, your program will segmentation fault because the pointer is "dangling". When you try to dereference it with ->, you are accessing memory that isn't yours, and it fails. To fix this, simply allocate a new List object:
List<int> *list1 = new List<int>();
Don't forget to free it later:
delete list1;
Your other option is to just not use dynamic memory. You shouldn't use it if you don't have to.
List<int> list1;
list1.show()
List<int> *list1;
Declares list1 to be a pointer.
List<int> *list1 = new List<int>();
Would actually create an instance of List
Related
I'm writing a linked list, and using my main function to test it. Here's my code:
#include <iostream>
using namespace std;
class LinkedList {
int value;
LinkedList* next;
public:
LinkedList(int valueIn, LinkedList* nextIn) {
value = valueIn;
next = nextIn;
}
LinkedList(int valueIn) {
value = valueIn;
}
int getValue() {
return value;
}
void addNode(LinkedList* node) {
next = node;
}
LinkedList& getNext() {
return *next;
}
};
int main() {
cout << "starting..." << std::endl;
LinkedList list1(1);
LinkedList list2(2, &list1);
cout << list1.getValue() << " --> " << list1.getNext().getValue() << std::endl;
return 0;
}
I expect the output to be 1 --> 2, but I get 1 -->. As far as I understand, getNext() should return a reference to another list (list2 in this case), but something seems to be going wrong. My debugging efforts show me that list2 does have the correct value 2 when it's initialized, but when it's referenced for the final output, it doesn't seem to have anything for value. I can't for the life of me figure out why this is. Could someone help me to understand?
You are insertin list1(which is actually a node) to the end of list2, not the other way around, yet you call getNext() on list1. You should change the code in main to the below:
int main() {
std::cout << "starting..." << std::endl;
LinkedList list1(1);
LinkedList list2(2, &list1);
std::cout << list2.getValue() << " --> " << list2.getNext().getValue() << std::endl;
return 0;
}
Please note that there are a couple of other things which would be better to change:
Create a list class and a Node class woud make things clearer
Initializing the pointer to be NULL(or nullptr from C++11) in the LinkedList(int valueIn) constructor
Return the pointer to the node in getNext() rather than copy the node
You are not getting a blank value. Actually your program is crashing when you are trying to call list1.getNext().getValue() as getNext() is returning reference to a NULL.
You are doing the opposite of what you want to do.
Your list2 is pointing to list1 and list1 is pointing to NULL.
You should change your code with this:
LinkedList list2(2);
LinkedList list1(1, &list2);
cout << list1.getValue() << " --> " << list1.getNext().getValue() << std::endl;
I have started learning c++ (coming from java background) and barely reached pointers and got stuck. When I debug this program it says, program received segmentation fault (SIGSEGV signal) at line
*previous = head;
in the following code.
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *link;
};
int main()
{
cout << "Starting main program \n";
Node head;
head.data = 0;
head.link = NULL;
cout << "After declaring head and initializing values \n";
//Declaring a pointer variable which points to an entity of type struct.
Node *previous;
*previous=head;
cout << "After declaring previous pointer \n";
bool done = false;
int i = 1;
cout << "First while loop\n";
while(!done)
{
cout << i << ": Iteration";
Node temp;
temp.data=i;
temp.link=NULL;
if(i > 2)
{
done = true;
continue;
}
*previous->link=temp;
++i;
*previous = temp;
}
done = false;
cout << "Declaring temp pointer before printing \n";
Node *temp;
*temp = head;
cout << "Second while loop\n";
while (!done)
{
cout << i << ": Iteration";
if(temp == NULL)
{
done = true;
continue;
}
cout << temp->data << "->";
*temp = *temp->link;
}
cout << "NULL";
}
Why is the pointer initialization incorrect ?
First problem:
Node *previous;
*previous=head;
First line declares that previous will hold the address of a Node. It is not initialized, so whatever value happens to be on the stack will be picked up as the bit pattern it holds.
Unfortunately, the 2nd line then dereferences the pointer (which points to garbage) and attempts to copy head into random memory (hence your crash).
In this case you probably want previous to point to head, which is taking head's address and assigning it:
Node* previous = &head; // initialize at the point of declaration
However, you must also be very wary of pointers to variables declared on the stack, because the addresses will soon become invalid when the function returns or the scope exits.
(Usually data structures with pointers are using values allocated on the heap, so the objects outlive the function that declares them.)
Which brings us to the second problem:
while(!done)
{
cout << i << ": Iteration";
Node temp;
Already there's a problem. temp is declared inside the loop on the stack. Each loop iteration, the variable will automatically be destroyed. Therefore it cannot participate in your linked list without corrupting it.
You want your list nodes to be created with new, and when you update previous's next pointer, you want to assign an address TO it, not copy an object THROUGH it.
Something like this:
while(!done)
{
cout << i << ": Iteration";
Node * temp = new Node();
temp->data = i;
temp->link = nullptr; // better than NULL
if(i > 2)
{
break;
}
previous->link = temp;
++i;
previous = temp;
}
The head object should probably also be heap allocated. Of course, now you have to deal with cleaning up the memory by calling delete on all the nodes.
There were some bugs in the code but major ones were :-
you were not allocating memory for the new nodes that you were adding during runtime
you were creating instances of structure but instead you were required to create an pointer pointing to the structure ( instances will be created during runtime ( using new operator )
I have added the comments to the code explaining what exactly are the changes that I have done.
Here is the fix :-
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *link;
};
int main()
{
cout << "Starting main program \n";
// Allocating memory for the new instance of Node and making "head" pointing to it
Node *head = new Node;
head->data = 0;
head->link = NULL;
cout << "After declaring head and initializing values \n";
//Declaring a pointer variable which points to an entity of type struct.
Node *previous;
// As head and previous both are pointers thus can be assigned as it is
previous = head;
cout << "After declaring previous pointer \n";
bool done = false;
int i = 1;
cout << "First while loop\n";
while(!done)
{
cout << i << ": Iteration";
// Allocating memory for the new instance of Node and making temp pointing to it
Node *temp = new Node;
// As temp is a pointer thus using member access ("- >") operator to access the members
temp->data=i;
temp->link=NULL;
if(i > 2)
{
done = true;
continue;
}
previous->link = temp;
++i;
previous = temp;
}
done = false;
cout << "Declaring temp pointer before printing \n";
Node *temp;
temp = head;
cout << "Second while loop\n";
while (!done)
{
cout << i << ": Iteration";
if(temp == NULL)
{
done = true;
continue;
}
cout << temp->data << "->";
temp = temp->link;
}
cout << "NULL";
}
I'm implementing a stack using GList (doubly) but when I assign my stack with the last element using g_list_last(*stack*) the program doesn't print my stack at all
Pointing to the first element using g_list_first(*stack*) works and I can traverse with stack->next pointer
Here's my test program:
#include <iostream>
#include <cstdlib>
#include <glib.h>
using namespace std;
int main()
{
cout << "Enter the no of random data to push: ";
int number = 0;
cin >> number;
GList *stack = nullptr;
for (int i = 0; i < number; i++) {
int data = random() % 10;
stack = g_list_append(stack, GINT_TO_POINTER(data));
cout << "Push: " << data << endl;
}
cout << "Printing the stack forward:\n";
stack = g_list_first(stack);
while (stack != nullptr) {
cout << GPOINTER_TO_INT(stack->data);
cout << "->";
stack = stack->next;
}
cout << "nullptr" << endl;
cout << "Printing the stack backward:\n";
stack = g_list_last(stack);
while (stack != NULL) {
cout << GPOINTER_TO_INT(stack->data);
cout << "->";
stack = stack->prev;
}
cout << "nullptr" << endl;
return 0;
}
Do I have to manually assign the prev link while appending?
First of all, I would not recommend using GLib in a C++ code base; GLib is a C library, full of idiomatic C code and functionality. I'd suggest using the C++ standard library, instead.
GList is a doubly linked list where each element is composed by three pointers:
typedef struct _GList GList;
struct _GList
{
void *data; // untyped pointer data
GList *prev; // pointer to the previous element in the list
GList *next; // pointer to the next element in the list
}
For convenience, all the GList functions accept a NULL as a valid list; in the case of g_list_append(), passing a NULL list as the first argument means that it will allocate a new GList element for the data you're passing and place it at the start of the list.
In your code you're taking the head of the list after populating it, and calling g_list_first(), which is a no-op on the head of the list; then you proceed to consume it by iterating over it, until you hit the end of the list, where you assign nullptr to the stack variable. Since nullptr/NULL is a valid empty GList, you're now calling g_list_last() on a valid, but empty list, which will return NULL, and thus prevent you from iterating backwards. Additionally, you're now leaking the memory allocated to the list.
The solution is to never iterate a GList with the same variable that holds the head of the list:
cout << "Printing the stack forward:\n";
GList *iter = g_list_first(stack);
while (iter != nullptr) {
cout << GPOINTER_TO_INT(iter->data);
cout << "->";
iter = iter->next;
}
cout << "nullptr" << endl;
The code above will consume the iter variable, instead of the stack. Which means that the code below:
cout << "Printing the stack backward:\n";
iter = g_list_last(stack);
while (iter != NULL) {
cout << GPOINTER_TO_INT(iter->data);
cout << "->";
iter = iter->prev;
}
cout << "nullptr" << endl;
will work appropriately, and walk the stack backwards, as the stack variable still points to the head of the list, and you're now consuming a temporary iterator.
Remember to call g_list_free() on the list to release any resources allocated for it—and g_list_free_full() in case you're allocating the contents of the data pointer as well.
I have a problem with the following linked list code, but i'm not sure what it is. Could someone point me in the right direction? I'm using this code in some larger code where i update records, but it never reaches the "creating new record" section. It is as if the main code is updating the head pointer instead thus always resulting in a favourable comparison.
Thanks in advance. I've been racking my brains out trying to figure out what the problem is.
struct l_list *find_name(const char *name)
{
struct l_list *tmp=0;
if(records==0) { // First record
head=new l_list;
head->name=name;
head->next=0;
tail=head;
records++;
return head;
}
else {
tmp=head;
while(tmp!=0)
{
if(!std::strcmp(tmp->name,name))
{
cout << "Returning existing record with value: " << tmp->number << " name:" << tmp->name << endl;
return tmp;
}
tmp=tmp->next;
}
// No first and no existing records
cout << "Creating new record" << endl;
tail->next=new l_list;
tail=tail->next;
tail->name=name;
tail->next=0;
records++;
return tail;
}
I'm calling this from main with:
struct records *tmp=find_name("Max");
then :
tmp=find_name("Eva");
Once i get the struct i update it like so:
tmp->number=1;
Or even updating the name:
tmp->name="Peter";
So by passing a string to the function it will either create a new record and return it or give an existing record and return that. Problems might not be apparent in the output, but when you put it in a for(;;) loop in main it will
mess up.
The struct is as follows:
struct records {
const char *name;
struct records *next;
}
The relevant program code is:
struct record {
const char *name;
struct record *next;
};
struct record *head;
struct record *tail;
struct record *find_name(const char *name)
{
struct record *tmp=0;
if(record_count==0) { // First record
cout << "Creating first record" << endl;
head=new record;
head->name=name;
head->next=0;
tail=head;
record_count++;
return head;
} else {
tmp=head;
while(tmp!=0) {
if(!std::strcmp(tmp->name,name)) {
cout << "Returning existing record with value: " << "name: " << name << "tmp->name: " << tmp->name << endl;
return tmp;}
tmp=tmp->next;
}
// No first and no existing records
cout << "Creating new record" << endl;
tail->next=new record;
tail=tail->next;
tail->name=name;
tail->next=0;
record_count++;
return tail;
}
}
int main(int argc, const char *argv[])
{
struct record *tmp=0;
if(something is true) {
//Return or create a new user
tmp=find_name("Peter");
} else {
tmp=find_name("Unknown"); // Hold 1 unknown person in database
}
}
I know it's not compilable as-is but i had to extract it from a larger part.
Since you have not told us what the records structure is, there is no way for anyone to give a correct answer. You have made it even more impossible by not giving an example of code that will cause your function to behave incorrectly.
If the name element is a char * pointer then you could easily get this behaviour. For example:
The calling code puts a name into a buffer, and calls find_name.
find_name stores the address of the buffer into the name element of a records object. name therefore points to whatever the buffer happens to contain, now and in the future.
The calling code puts a new name into the same buffer. This automatically means that the name element now points to that new name, since it is pointing to the buffer.
The calling code calls find_name again.
find_name compares the contents of the buffer to the string pointed to by the name element of the first records object. Since the name element contains the address of the buffer passed by the caller (from step 2), this means that it is comparing the buffer to itself. So the result is always "equal".
But it may be that name is not a pointer at all, in which case this entire answer is irrelevant.
First of all do not use the following code formatting
if(record_count==0) { // First record
cout << "Creating first record" << endl;
//...
} else {
tmp=head;
//...
It is difficult to read such a code. It is just a bad style of programming.
The function itself can look the following way
struct l_list * find_name( const char *name )
{
struct l_list *tmp = head;
wjile ( tmp != nullptr && std::strcmp( tmp->name, name ) != 0 ) tmp = tmp->next;
if ( tmp == nullptr )
{
cout << "Creating new record" << endl;
tmp = new l_list;
tmp->name = name;
tmp->next = nullptr;
if ( tail == nullptr )
{
head = tail = tmp;
}
else
{
tail = tail->next = tmp;
}
records++;
}
return tmp;
}
Take into account that the nodes can contain pointers to strings either with the static storage duration as for example string literals or allocated in the heap.
I am having troubles with my code. the calling linkedlist does not seem to get "updated" with the values or they are not saved or something. Could use some help, Thanks.
template <class T>
void LinkedList<T>::insert_front(const T& x)
{
LinkedList* p = this;
LinkedList* tmp = new LinkedList(x,p);
p = tmp;
cout<<p->m_data<<endl;
cout<<tmp->m_data<<endl;
The calling function is
//TEST : Inserting 10 numbers to a
cout << endl << "TEST : Inserting 10 numbers to A" << endl;
for (int k=0; k<10; k++){
A.insert_front(k+1);
}
cout << A << endl;
cout << "Size of a = " << A.size() << endl;
I get an output of 1122334455667788991010
which is the tmp data value and the p data value each call
The values go to the code, and they are the right values, just when I go to print A nothing is shown just an empty list. Thanks, I'm new here but love the community.
Your design of the linked list and of the method are wrong.
In the method you defined local variable p and assigned to it tmp. After exiting the method this local variable will be destroyed. So nothing was occured with the list itself. Neither its data member was changed. Also there is a memory leak.
template <class T>
void LinkedList<T>::insert_front(const T& x)
{
LinkedList* p = this;
LinkedList* tmp = new LinkedList(x,p);
p = tmp;
cout<<p->m_data<<endl;
cout<<tmp->m_data<<endl;
You should split you class into two classes. The first one will define the node of the list and the second one will control operations withy the list and contain the head of the list as its data member.