C++ Executable Freezes at Runtime - c++

I wrote a simple console program for the use of testing some key classes in a library I'm building. Now, the code builds correctly with no errors. But, after executing the code, I found that the application stops working after calling the Index method at a certain point in the code. I tried debugging a few different ways to get more information about the problem, but the information I gathered didn't help me at all. Maybe it will help someone else who knows what I'm not doing(or doing incorrectly).
Here's the contents of the Util namespace;
template<typename var>
class VectorNode
{
public:
VectorNode(var value, VectorNode<var>* next = NULL, VectorNode<var>* prev = NULL)
{
data = value;
t_next = next;
t_prev = prev;
}
~VectorNode()
{
if (t_next != NULL)
delete t_next;
}
virtual VectorNode<var>* Next(){ return t_next; } // get the next node in line
virtual void Next(VectorNode<var>* newNode){ t_next = newNode; } // set the next node in line
virtual VectorNode<var>* Prev(){ return t_prev; }// get the previous node in line
virtual void Prev(VectorNode<var>* newNode){ t_prev = newNode; } // set the previous node in line
virtual var Value(){ return data; } // get the node's value
private:
var data;
VectorNode<var>* t_next;
VectorNode<var>* t_prev;
};
template<typename var>
class Vector
{
public:
Vector()
{
tailNode = new VectorNode<var>(*(new var));
headNode = new VectorNode<var>(*(new var), tailNode);
tailNode->Prev(headNode);
size = new int;
*size = 0;
}
~Vector()
{
delete headNode;
delete size;
}
int Size(){ return *size; } // get the size of a vector
void Add(var toAdd, int index = 0) //
{
VectorNode<var>* lastNode;
if (index > (*size))
index = *size;
if (index < 1) // add to the end of the vector
{
lastNode = tailNode;
}
else
{
int i;
if (index <= (*size / 2)) // if the index is less than half the size, iterate forwards
{
lastNode = headNode;
for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
}
else // otherwise, iterate backwards
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev(); }
}
}
VectorNode<var>* temp = lastNode->Prev();
VectorNode<var>* newNode = new VectorNode<var>(toAdd, lastNode, temp);
lastNode->Prev(newNode);
temp->Next(newNode);
*size = *size + 1;
}
void Remove(int index) // remove an index
{
VectorNode<var>* toRemove;
VectorNode<var>* lastNode;
int i;
if ((index > *size) || (index < 1)) // if not in the domain...
index = *size;
if (index <= (*size / 2)) // iterate forwards
{
lastNode = headNode;
for (i = 1; i < index+2; i++){ lastNode = lastNode->Next(); }
}
else // iterate backwards
{
lastNode = tailNode;
for (i = *size; i > index; i--){ lastNode = lastNode->Prev(); }
}
toRemove = lastNode->Prev();
VectorNode<var>* temp = toRemove->Prev();
temp->Next(lastNode);
lastNode->Prev(temp);
delete toRemove;
*size = *size - 1;
}
var Index(int index) // get the value of a node
{
VectorNode<var>* lastNode;
int i;
if (index <= (*size / 2)) // iterate forwards
{
lastNode = headNode;
for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
}
else // iterate backwards
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();}
}
return lastNode->Value();
}
private:
int* size;
VectorNode<var>* tailNode; // the head and tail nodes are placeholders, to keep the list inside its boundaries
VectorNode<var>* headNode;
};
If you don't feel like reading that, I marked each method with a comment, explaining its overall purpose. Also, I tried adding a small explanation of some of my blocks of code.
And, here's the entry function, and inclusions;
#include "iostream"
#include "stdlib.h" // this has nothing in it that's being used
#include "testhead.h" // the location of the Util namespace
int main()
{
using namespace Util;
Vector<int>* x = new Vector<int>();
x->Add(42);
x->Add(24);
x->Add(12);
x->Add(21);
std::cout << "Listing Indices\n";
for (int i = 1; i <= x->Size(); i++)
{
std::cout << i << "\t" << x->Index(i) << "\n";
}
std::cout << "Size(pre-removal):\t" << x->Size() << "\n";
x->Remove(2);
std::cout << "Size(post-removal):\t" << x->Size() << "\n";
std::cout << "Listing Indices\n";
std::cout << 3 << "\t" << x->Index(3) << "\n";
for (int i = 1; i <= x->Size(); i++)
{
std::cout << i << "\t" << x->Index(i) << "\n";
}
system("Pause");
}
Okay, the results I got where this. Before using the Remove method, any index can be accessed from the Vector class freely. But, after using the remove method, no matter what index is removed, no index above one can be accessed. Except, in the case which we remove the first index, then no indices can be accessed. I tried stepping through the code, but it brought me up to this line of code in the index method;
else
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();} // error occurs after running this line
}
Now, since I was able to figure out the Remove method was causing the problem, I went back and got some output about that. I had it run the following line prior to finishing its execution, twice. Once before toRemove is deleted, and once again after it is deleted.
std::cout << (lastNode->Prev() == temp) << "\t" << (temp->Next() == lastNode) << "\n";
Before it is removed, it prints 1 twice, indicating the comparison was true. But, the second time I call either the Prev and Next method, and the program freezes. I know this is because I freed the place in memory, but the comparison shows that any references from other nodes to the node I removed were gone. Now, my specific question is why exactly this is being caused, and how can I fix it? I know a little bit about managing memory on the heap, and this doesn't exactly appear as though it would cause any issues with the program. So, I could use a short explanation as to why this happens if anyone would be kind enough to provide it.
If it's any assistance, I'm using the Code::Blocks IDE and the GNU GCC compiler. Also, please tell me if I'm doing something wrong related to the way I asked my quetsion. I don't visit Stack Overflow often, and I don't ask questions here. This is just the best place to have your questions answered that I am aware of.

The destructor of the VectorNode class deletes the object pointer to by the t_next pointer. Calling delete on the toRemove pointer means that the destructor of that VectorNode object gets called, and then the next one, and then the next one etc. etc.
So basically, when you delete toRemove, you delete toRemove and all the objects that come after this. This causes the tailNode's t_prev to point to memory that you have already freed, and you then try dereferencing those pointers in your Index function, and that's not a good thing.

When you delete a VectorNode that has its t_next member pointing to some other node, the destructor of VectorNode will delete that other node (which in turn might go on to delete further nodes).
When you remove a node from the middle of a list with Remove(), the t_next of this node will point to the further nodes of the list. When this node is deleted, the destructor will also delete all the nodes following it in the list. Continuing to use this half-deleted list it will result in all kinds of problems.
Other random observations:
Why is size a int* instead of a normal int or size_t? I can't see any reason why this should be a pointer.
new VectorNode<var>(*(new var)) should really be new VectorNode<var>(var()) to not unnecessarily leak memory.
The t_next != NULL test before delete is unnecessary
Are you planning to create classes deriving from VectorNode<>? If not, than there is no reason why the methods would need to be virtual.
Using 1-based indexing in Add() is unusual, one would expect zero-based indexing
Also I feel obliged to tell you that there are standard library containers like std::list<> and std::vector<> which implement this kind of structures.

Calling remove deletes a node, but deleting a node deletes all the nodes->next
~VectorNode()
{
if (t_next != NULL)
delete t_next;
}
so deleting element 2 of your 1 based vector kills all the other elements as you have experienced, and there is no longer an element 3 to investigate

Related

Sieve of Eratosthenes C++ using single linked list

Hi I have a problem with Sieve of Eratosthenes in C++. I have to do this using single linked list. My program is running and showing first declaration of list but I don't know how to delete non prime numbers properly. My function just isn't working for me. How should I change my delete function?
#include <iostream>
#include <cmath>
using namespace std;
struct List
{
int number;
List* next;
};
List* head = new List;
void l_add(int n)
{
List* temp = head;
for (int i = 2; i <= n; i++)
{
temp->next = new List();
temp->number = i;
temp = temp->next;
}
}
void l_print()
{
List* temp = head;
while (temp->next != 0)
{
cout << temp->number << " ";
temp = temp->next;
}
cout << endl;
}
void l_delete(int n)
{
List* temp = head;
for (int i = 2; i < sqrt(n); i++)
{
if (temp->number % i == 0)
{
head = temp->next;
delete temp;
temp = head;
}
while (temp->next != 0)
{
if (temp->next->number % i == 0)
{
temp->next = temp->next->next;
delete temp->next;
}
temp = temp->next;
}
}
}
int main()
{
int n;
cout << "Enter up to which number to find prime numbers using Sieve of Eratosthenes: " << endl;
cin >> n;
l_add(n);
l_print();
l_delete(n);
l_print();
return 0;
}
This would be a working version of the l_delete method:
void l_delete(int n)
{
List* temp = head;
for (int i = 2; i < sqrt(n); i++)
{
while (temp->next != 0)
{
if (temp->next->number % i == 0 && temp->next->number != i)
{
List* temp2 = temp->next->next;
delete temp->next;
temp->next = temp2;
}
if(temp->next == 0) break;
temp = temp->next;
}
temp = head;
if (temp->number % i == 0 && temp->number != i)
{
head = temp->next;
delete temp;
temp = head;
}
}
}
There were several problems with your deletion method.
Problems with algorithm logic: With your algorithm head should be checked last because otherwise if its deleted, the new head is not checked for primality, you immediately check new next, which is old ->next->next. Also you didn't check if number is equal to divider in which case it should not be deleted.
Problems with programming logic:
When you're deleting next node in the while loop, same as when deleting head, you need another temporary variable to store temp->next->next and then after deleting assign it to temp->next.
But the biggest problem here is that this is not Eratosthenes sieve at all, you are
just checking all numbers for divisibility with all others smaller than sqrt(n). It
is suboptimal compared to the Eratosthenes sieve. If you Google Eratosthenes sieve, you’ll find a lot of detailed tutorials and explanations.
I like what Bran is pitching, and I'm going to add a few tricks.
Comment: Global variables suck. They make things harder to trace when projects get bigger. I'd move head into main and pass it around as a parameter. I'm also ditching the sentry node because I find them more trouble than they are worth most of the time.
int main()
{
int n;
cout << "Enter up to which number to find prime numbers using Sieve of Eratosthenes: " << endl;
if (cin >> n)
{
// should be a bit more logic here to automatically handle ns of 1 or 2
List* head = nullptr; // not using a sentinel node
l_add(head, n); // passing in head rather than global variable free-for-all
l_delete(head);
l_print(head);
return 0;
}
else
{
cout << "invalid input." << endl;
return 1;
}
}
When adding to the linked list, you don't need any even numbers other than 2. So don't add them. Less time spent iterating the list. After that it's a matter of making sure nodes go in in the right order.
void l_add(List*& head, // passing in head. Easier to track
int n)
{
List** temp = &head; // head is a next pointer with a different name
// hiding it behind another pointer allows us to treat
// it like a next
// temp is now a pointer to next pointers. We can add directly to the
// last nodes's next pointer and also use it to access the current
// pointer if we need to
(*temp) = new List {2, nullptr}; // 2 is only even prime
temp = &(*temp)->next;
for (int i = 3; i <= n; i+=2) // start at 3 and only add odd numbers
{
(*temp) = new List {i, nullptr};
temp = &(*temp)->next; // Advance to next node
}
}
When we're iterating through the list looking to eliminate multiples we need two loops. One to keep track of the node we're eliminating multiples and another loop to do the hunting and eliminating. Note that I'm using the pointer-to-pointer trick again. This trick annihilates about half of the code needed to traverse and remove nodes.
void l_delete(List * head)
{
List* last = head->next; // track the last known prime node. skip node 2.
// note this will blow up if there is no node 2.
while (last) // for every node still in the list
{
List** current = &last->next; // similar to trick above.
// if we have a pointer to the next to be
// updated, we don't need to track the previous node
while ((*current)) // look at every node after the last prime
{
if ((*current)->number % last->number == 0) // if it's a multiple, remove it.
{
List * to_del = (*current); //save node to delete
(*current) = (*current)->next; // link previous node to next node.
// effectively automatically advances the node
delete to_del;
}
else // proceed to next node
{
current = &(*current)->next;
}
}
last = last->next; // advance to next prime number
}
}
Probably plenty of room in there for optimization, but I'm aiming more for readability because if I drop ten lines of cryptic gibberish nobody learns nuthin'.

Im losing elements in my dynamically allocated arrays

Im implementing a stack which allocates a new array when the current array is full. It uses a linked list to keep the addresses of these arrays. When the stack pop()s the only element in an array, it deletes the array, deletes the linked list node which contains this array's address, then reverts to the next node (which is now in the front) and uses the array address within the node as its new "current array"
This is not working and I cannot change the basic structural requirement. The array deletes successfully, the node deletes successfully but for some reason, the old array seems to contain no data anymore and the function generally just breaks. Is there anything you can spot in these function definitions which obviously is the problem?:
Here the members (minus function prototypes and full LL def):
class Stack
{
private:
int height;
class LL
{
...
}
LL stack_map;
string * current_stack;
public:
int top_element;
Constructor:
Stack::Stack(int size)
{
height = size;
top_element = 0;
current_stack = new string[height];
stack_map.push_front(current_stack);
}
Push function:
void Stack::push(string data)
{
if (top_element == height)
{
current_stack = new string[height];
stack_map.push_front(current_stack);
current_stack[0] = data;
top_element = 1;
}
else
{
current_stack[top_element] = data;
top_element++;
}
}
And pop functions
bool Stack::pop(string& result_box)
{
if (top_element == 0)
{
delete[] current_stack;
cout << "Array deleted" << endl;
stack_map.delete_front(current_stack);
cout << "number of nodes :" << stack_map.list_length() << endl;
top_element = height - 1;
cout << current_stack[top_element];
result_box = current_stack[top_element];
return true;
}
else
{
top_element--;
result_box = current_stack[top_element];
return true;
}
}
Lastly here is the push_front and delete_front functions called in these:
push:
void push_front(string * current_stack)
{
LLnode * new_node;
new_node = new LLnode;
new_node -> stack_address = current_stack;
if (header == nullptr)
{
header = new_node;
new_node -> fwdPtr = nullptr;
}
else
{
LLnode * temp;
temp = header;
header = new_node;
new_node -> fwdPtr = temp;
}
return;
}
delete:
void delete_front(string * current_stack)
{
LLnode * temp, * kill_box;
if (header == nullptr)
{
return;
}
else
{
kill_box = header;
temp = header -> fwdPtr;
delete kill_box;
header = temp;
current_stack = temp -> stack_address;
}
}
I know this is a horrendous amount of code, I just dont understand the problem enough to minimize it further. Im not receiving errors, but my testing is not able to retrieve any strings once the pop() function tries to move back to a previous node/array.
Any advice is appreciated.
Ultimately I found the bug. The function delete_front(), which is responsible for changing the string * current_stack pointer was passed by value and not by reference. Therefore, it was never pointing at anything but the already-deleted array.
This is why it appeared like I was "losing data", my pointer was always pointing at the deleted array instead of changing as node/arrays were deleted. I was so pleased when I found this. Maybe this can help someone in the future, it definitely will be a good reference for me.

Deallocating memory from a linked list

I'm trying to delete the n'th element, which is a random number from 1 to n.
My code does this fine (correct element is deleted and surrounding elemnts are connected) but when it comes to being efficient, it is crashing when I un-comment the line delete (nodeToRemove); and I'm not sure why. Does anyone have any insight?
Assuming my struct looks like :
struct Node {
int data; // The data being stored at the node
Node *next; // Pointer to the next node
};
//------------------------------------------------------------------------------
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
head = head->next;
}
else
{
for (int i = 1; i < random - 1; i++)
temp = temp->next;
nodeToRemove = temp->next;
temp->next = temp->next->next;
}
// delete (nodeToRemove); <----- uncommenting this leads to crash,
}//end deleteNthElement()
//------------------------------------------
int main()
{
Node *head = NULL;
Node *temp;
Node *listarray[n[i]];
int n[] = {1000, 5000, 9000, 105000, 400000, 500000, 505000, 800000, 995000, 1000000};
for (int j = 0; j < n[i]; j++)
listarray[j] = new (Node);
//start timer
begin = clock();
//fill it
for (int j = 0; j < n[i]; j++)
{
listarray[j]->data = (rand() % n[i] + 1);
insertNodeInOrder (head, temp, listarray[j]);
}
//delete it
for (int j = 0; j < n[i]; j++)
deleteNthElement (head, temp, (rand() % (n[i] - j) + 1));
//deallocate
for (int j = 0; j < n[i]; j++)
delete listarray[j];
delete *listarray;
//end timer
}
You're picking the wrong Node, you want:
...
nodeToRemove = temp;
...
At least, you have to check for the end of the list, that is, you need to avoid access to null pointers (i really hope you set next to 0 at the end of the list). If you add the allocation parts, I will extend my answer.
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
if(head != 0)
head = head->next;
} else {
for (int i = 1; i < random - 1; i++)
if(temp != 0)
temp = temp->next;
else throw 1; // no such index; throw something more verbose :)
if(temp == 0)
throw 1; // same situation as above
nodeToRemove = temp->next;
if(nodeToRemove == 0)
throw 1; // same situation as above
temp->next = temp->next->next;
}
if(nodeToRemove == 0)
throw 1; //no such index; ... as the above 3
delete nodeToRemove;
}//end deleteNthElement()
Some clean-up first:
Why pass in two pointers here? do you need the value of temp out? If so why not return it?
Also why the node * & temp? (I can see why it is done for head).
int random should probably be called something like index as it describes the functionality better (as far as the function is concerned, there is nothing random about it).
The same with temp.
I propose:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
//...
We don't need temp if we are removing the head. Also, we generally 0 index things, so we should reflect that too. Thus it becomes:
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
Now we get to the main bit. The loop is just there to step through to the parent node of the node to delete, so we can simplify it a little and add checks to make sure we can't 'fall off' the end of the list.
We then have to make sure there is a node to remove, (so another check). We don't need to check for a node beyond as assigning nullptr isn't a problem (I am assuming that an invalid pointer is set to nullptr here):
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
Incidentally, this fixes a probable off by one error. Which is probably your problem (did it crash every time? only when deleting the last element? next to last?
Now we just need to delete it.
Putting it all together:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
else
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
delete node_to_remove;
return;
}
And that should work fine. The checks will prevent us dereferencing null pointers which was (probably) what caused you to crash. Can't tell without full code.

Segmentation Fault C++

#include <iostream>
#include "Student.h"
#include "SortedList.h"
using namespace std;
#define BOUNDS 100
int main() {
SortedList *list = new SortedList(); // points to the sorted list object
Student *create[BOUNDS]; // array to hold 100 student objects
int num = 100000; // holds different ID numbers
// fills an array with 100 students of various ID numbers
for (int i = 0; i < BOUNDS; i++) {
create[i] = new Student(num);
num += 10;
}
// insert all students into the sorted list
for (int i = 0; i < BOUNDS; i++)
list->insert(create[i]);
// removes each student from the list
num = 100000;
for (int i = 0; i < BOUNDS; i++) {
list->remove(num);
num += 10;
}
delete list;
return 0;
}
I am getting a seg fault with the previous code. Any insight as to why this is or how to possibly fix it would be appreciated. The seg fault is definitely caused by the delete list; line
UPDATE 1: Here is my SortedList destructor
/*
* Destructs this sorted list object
*/
SortedList::~SortedList() {
freeList(head);
}
/*
* Traverses throught the linked list and deallocates each node
*/
void SortedList::freeList(Listnode *L) {
Listnode *tmp = L; //holds the node to be deleted
//traverses the list
while (tmp != NULL) {
Listnode *next = tmp->next; //holds the value of the next node
//delete previous node
delete tmp->student;
delete tmp->next;
delete tmp;
//sets the next node to the node to be deleted
tmp = next;
}
//delete header node
delete L;
}
Well, we can't see SortedList or Student, and I'd guess the problem is in one of those. I note that num never gets reset to its original value after the creation loop, which means that most of the remove calls are going to be passed an id that belongs to no Student; perhaps that case fails. Or perhaps there are simply bugs in the insert or remove methods -- or the constructor or destructor, for that matter. It's totally up in the air.
EDIT: As others have pointed out, that destructor uses a pointer after it's been deleted; that could be the only source of error, or there could easily be more in the code we haven't seen yet.
In freelist(), you delete tmp->next, then set tmp = tmp->next. Now tmp has an invalid pointer. You need to restructure your code so that you do not free a pointer before accessing its members.
Although I hate doing people's homework for them, here's my solution:
/*
* Traverses throught the linked list and deallocates each node
*/
void SortedList::freeList(Listnode *L) {
if(L == NULL) return;
freeList(L->next);
delete L->student;
delete L;
}
This use O(n) stack space for deletion, but I personally find it much clearer than a loop. Your solution can be tweaked to "just work" by removing the call to delete tmp->next.
// removes each student from the list
for (int i = 0; i < BOUNDS; i++) {
list->remove(num);
num += 10;
}
Looks interesting... how does this work exactly? If num is 100000 + BOUNDS*10 at this point in the code (since it is never changed after you add 10 to it for each student you create). Every remove call you make doesn't remove a student by their ID (since the id called is 100000 + BOUNDS*10 + i*10). Was the intent to remove them by ID, if so you should consider resetting num to 100000 before doing the remove loop.
To clarify how this could cause the seg-fault: if your remove function doesn't have proper bounds checking it could go out of the memory looking for the id to remove.
Updated with destructor question:
void SortedList::freeList(Listnode *L) {
Listnode *tmp = L; //holds the node to be deleted
//traverses the list
while (tmp != NULL) {
Listnode *next = tmp->next; //holds the value of the next node
//delete previous node
delete tmp->student;
delete tmp->next;
delete tmp;
//sets the next node to the node to be deleted
//**********
//Check here, you deleted next, but the assigned it to temp. Tmp isn't null, but
//it is however, no longer your memory (since you deleted it)
//**********
tmp = next;
}
//delete header node
delete L;
}

Why can't the Nodes be linked together?

EDIT: Is it possible to NOT use new? (do not dynamically allocating memory)
I think it is push that is wrong, but I don't know where, how, and why. here is the code:
struct Node {
string fileName;
Node *link;
};
int size(Node *&flist) {
int count = 0;
Node *tempPtr = flist;
while (tempPtr != 0) {
count += 1;
tempPtr->link = (tempPtr->link)->link;
}
return count;
}
Node* push(Node *&flist, string name) {
Node temp;
Node *tempPtr = &temp;
temp.fileName = name;
temp.link = flist;
cout << tempPtr->fileName << endl;
cout << (tempPtr->link)->fileName << endl;
return tempPtr;
}
int main( int argc, char *argv[] ) {
Node aNode;
Node *flist = &aNode;
flist->fileName = "a";
flist->link = NULL;
push(flist, "b");
int s = size(flist);
cout << "size: " << s << endl;
}
the output is
b
a
size: 0
Thank you.
In your size() function you are modifying the list in the loop. You don't want to modify tempPtr->link but rather just change tempPtr as you iterate. Changing tempPtr won't modify anything permanently. You should also avoid passing flist by reference here as there's no need to modify it. So:
int size(Node *flist) {
int count = 0;
Node *tempPtr = flist;
while (tempPtr != 0) {
count += 1;
tempPtr = tempPtr->link;
}
return count;
}
As for push(), the biggest problem is that you're allocating the new node as a local variable which means it'll be on the stack and will get destroyed when the function returns. To create a node that is more permanent you need to allocate it on the heap using the new operator. And again the '&' for flist is unnecessary:
Node* push(Node *flist, string name) {
Node *tempPtr = new Node;
tempPtr->fileName = name;
tempPtr->link = flist;
cout << tempPtr->fileName << endl;
cout << tempPtr->link->fileName << endl;
return tempPtr;
}
Note that the counterpart to new is delete. Since the new nodes are allocated on the heap they will not be destroyed automatically so you will need to manually delete them when you are done with the list. Your goal is to have one delete for every new, so if you new 5 nodes your code should delete 5 nodes when it cleans up. If you don't do this your program will run fine but it will have a small memory leak.
(Actually, when it exits all allocated memory is automatically freed. But it's a bad habit to allocate memory and never free it, in general, so you should pretend this automatic cleanup doesn't happen.)
Well, your size() function is a little overkill. You might try
int size(Node *flist) {
int count = 0;
Node *tempPtr = flist;
while (tempPtr) {
count += 1;
tempPtr=tempPtr->link;
}
return count;
}
I've removed an extraneous exit condition from the while statement that prevented calculation of the length of lists that have only one element.
The reason it's returning 0 in your version is that your while statement:
while ((tempPtr != 0) &&(tempPtr ->link != 0)) {
count += 1;
tempPtr->link = (tempPtr->link)->link;
}
never executes since your one node has a .link value of null (0). Try the modified version I provided above.
Oh, in the future, you might want to tag these sorts of posts as "homework." You'll get better responses.
You need to use new. Otherwise the variable temp is destroyed at the end of the push function. Later, if you try to access what that pointer pointed to, it will be GONE.