This question already has answers here:
How to change value of variable passed as argument?
(4 answers)
Closed 5 years ago.
The program has no problem in the push function as I can reach the members of the structure (e.g. key). If I call push(stack, 3) the key is 3 within the push function on the newElem pointer that has been allocated on the HEAP, but then when it is assigned to the stack, and used outside of push function (used in main), it no longer has a clue what values the members of the struct has at that current address. So it seems to me that the malloc doesn't really work and doesn't put the memory on the HEAP since It's not accessible anymore through the main function??
#include <stdio.h>
#include <stdlib.h>
typedef struct list_element_t {
int key;
struct list_element_t* next;
struct list_element_t* prev;
}ListElement;
ListElement* GetNewElement(int k) {
ListElement* newElem = (ListElement*) malloc(sizeof(ListElement));
newElem->key = k;
newElem->next = NULL;
newElem->prev = NULL;
return newElem;
}
void push(ListElement* S, int k) {
ListElement* newElem = GetNewElement(k);
//The key is always correct here
printf("%d\n", newElem->key);
if(S == NULL) {
S = newElem;
//S is not NULL here.
return;
}
newElem->next = S;
S->prev = newElem;
//Put our stack in the back of the list
S = newElem;
}
void display(ListElement* S) {
ListElement* temp = S;
while(temp != NULL) {
printf("%d\n", temp->key);
temp = temp->next;
}
}
int main(int argc, char **argv)
{
ListElement* stack = NULL;
push(stack, 3);
//stack is still NULL here????
//Causes segmentation Fault
printf("%d\n", stack->key);
//Never prints anything (stack is NULL)
display(stack);
return 0;
}
S in push function is local variable, so in this assigment
S = newElem;
you assign newElem to temporary object which is destroyed when push ends. If you want to modify content pointed by S you should pass this by pointer to pointer.
void push(ListElement** S, int k) {
ListElement* newElem = GetNewElement(k);
printf("%d\n", newElem->key);
if(*S == NULL) {
*S = newElem;
return;
}
newElem->next = *S;
(*S)->prev = newElem;
*S = newElem;
}
and in main function call push function as follows
ListElement* stack = NULL;
push(&stack, 3);
Related
I am implementing a stack using linked list in C, and I stumbled upon two issues:
I need the stack_pop function to return a valid value temp, that is the temporary node/cell, and therefore, I can't free it. So, 1) Do you think freeing each node for every pop function call is better than until the end using the stack_destroy() 2) How can I achieve both, free(temp) and return it at the same time in stack_pop?
How bad my implementation becomes not using exit(1) in both stack_push and stack_pop functions?
This is the implementation:
//// Stack
// Linked list
typedef struct {
int data;
Cell* next;
} Cell;
struct stack_l {
size_t count;
Cell *top;
};
typedef struct stack_l *Stack;
You've got stack_pop declared to return an int, but you're attempting to return a Cell * which doesn't make sense.
Copy the value in the popped cell to a local variable, free the popped cell, then return the value.
temp = stack->top;
stack->top = stack->top->next;
temp->next = NULL;
stack->count--;
int val = temp.data;
free(temp)
return val;
Also, it makes no sense to call exit in either stack_push or stack_pop as that ends the program.
I think it is a bit overcomplicated. You only need to remember the previous stack pointer. Nothing else
typedef struct stack
{
int data;
struct stack *prev;
}stack;
stack *push(stack **sp, int data)
{
stack *new = malloc(sizeof(*new));
if(new)
{
new -> prev = *sp;
new -> data = data;
*sp = new;
}
return new;
}
int isempty(stack *sp)
{
return !stack_pointer;
}
int pop(stack **sp)
{
stack *new;
int result = 0;
if(sp && *sp)
{
result = (*sp) -> data;
new = (*sp) -> prev;
free(*sp);
*sp = new;
}
return result;
}
int main(void)
{
stack *stack_pointer = NULL;
int result;
push(&stack_pointer, 1);
push(&stack_pointer, 2);
push(&stack_pointer, 3);
do
{
result = pop(&stack_pointer);
printf("%d\n", result);
}while(stack_pointer) ;
printf("Stack was empty so the loop has exited\n");
}
I'm trying to figure out why my stack struct is not popping the elements and considers the stack to be NULL (i get the else condition from the pop() executing both times)? I'm confused because the printf shows the elements are being added onto to the stack.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int element;
struct node *pnext;
} node_t;
void push(node_t *stack, int elem){
node_t *new = (node_t*) malloc(sizeof(node_t)); // allocate pointer to new node memory
if (new == NULL) perror("Out of memory");
new->pnext = stack;
new->element = elem;
stack = new; // moves the stack back to the top
printf("%d\n", stack->element);
}
int pop(node_t *stack) {
if (stack != NULL) {
node_t *pelem = stack;
int elem = stack->element;
stack = pelem->pnext; // move the stack down
free(pelem); // free the pointer to the popped element memory
return elem;
}
else {
printf("fail");
return 0; // or some other special value
}
}
int main(int argc, char *argv[]){
node_t *stack = NULL ; // start stack as null
push(stack, 3);
push(stack, 5);
int p1 = pop(stack);
int p2 = pop(stack);
printf("Popped elements: %d %d\n", p1, p2);
return 0 ;
}
As said in a remark when you exit push/pop the variable stack in main is unchanged, so it is like you did nothing, except a memory leak in push
To have the new stack in main after a push that function can return the new stack, but this is not possible for pop already returning the poped value, so to have the same solution for both just use give the address of the variable in parameter to the functions to allow to modify it, so a double pointer rather than a simple
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int element;
struct node *pnext;
} node_t;
void push(node_t ** stack, int elem){
node_t *new = (node_t*) malloc(sizeof(node_t)); // allocate pointer to new node memory
if (new == NULL) {
perror("Out of memory");
exit(-1);
}
new->pnext = *stack;
new->element = elem;
*stack = new; // moves the stack back to the top
printf("%d\n", (*stack)->element);
}
int pop(node_t ** stack) {
if (*stack != NULL) {
node_t *pelem = *stack;
int elem = (*stack)->element;
*stack = pelem->pnext; // move the stack down
free(pelem); // free the pointer to the popped element memory
return elem;
}
else {
printf("fail");
return 0; // or some other special value
}
}
int main(int argc, char *argv[]){
node_t *stack = NULL ; // start stack as null
push(&stack, 3);
push(&stack, 5);
int p1 = pop(&stack);
int p2 = pop(&stack);
printf("Popped elements: %d %d\n", p1, p2);
return 0 ;
}
Compilation and execution :
% gcc -Wall s.c
% ./a.out
3
5
Popped elements: 5 3
I'm reading in words from a dictionary and then adding them to linked lists in a hash table. This works fine when I try inserting the nodes for each word within the while loop.
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
return false;
}
// Set all next pointers to NULL in hash table
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
char word[LENGTH + 1];
while(fscanf(dict, "%s", word) != EOF)
{
// Get key from hash function
unsigned int key = hash(word);
node *pNode = getNode(word);
if (table[key] != NULL)
{
pNode->next = table[key];
}
table[key] = pNode;
words++;
}
fclose(dict);
return true;
}
I've tried refactoring this to a function insertNode with the exact same code but it doesn't work and the nodes seem to get lost and cause a memory leak. I assume it has something to do with how the arguments are passed into the function but as head is a pointer I would've thought it would work fine.
void insertNode(node *head, const char *key)
{
// Create node
node *pNode = getNode(key);
// Insert node into linked list
if (head != NULL)
{
// Make new node point to first item in linked list (a.k.a head)
pNode->next = head;
}
// Now point head to new node
head = pNode;
}
so the while loop within load would just call the function (which is defined before)
char word[LENGTH + 1];
while(fscanf(dict, "%s", word) != EOF)
{
// Get key from hash function
unsigned int key = hash(word);
// Add value to Hash table with head of linked list
insertNode(table[key], word);
words++;
}
As the 'head' variable is a pointer, you can just pass the value of 'head' by this pointer not the pointer itself, and in this case you try to override the local pointer inside the function.
Well look at this example to assign/change value to the pointer:
#include <stdio.h>
class A {
public:
int x;
};
// pass pointer by copy
void initialize(A* obj) {
obj = new A(); // obj not null here
obj->x = 2;
printf("x: %d\n", obj->x);
}
int main() {
A *a = nullptr;
initialize(a);
// a is still null here (pointer passed by copy)
printf("x: %d\n", a->x); // seg fault here, read on null
return 0;
}
The following code as you can see is incorrect. To fix this example you have to change the function prototype, and pass the pointer by pointer so it should lool like this:
#include <stdio.h>
class A {
public:
int x;
};
// pass pointer by pointer
void initialize(A** obj) {
*obj = new A(); // obj not null here
(*obj)->x = 2;
printf("x: %d\n", (*obj)->x);
}
int main() {
A *a = nullptr;
initialize(&a); // get the pointer address
// a is valid object here
printf("x: %d\n", a->x); // no error, x == 2
return 0;
}
So in your case it should be:
insertNode(&table[key], word);
and
void insertNode(node **head, const char *key)
{
// Create node
node *pNode = getNode(key);
// Insert node into linked list
if (*head != NULL)
{
// Make new node point to first item in linked list (a.k.a head)
pNode->next = *head;
}
// Now point head to new node
*head = pNode;
}
typedef struct student *std_ptr;
struct student
{
int number;
std_ptr next;
};
typedef std_ptr STACK;
create_stack(void)
{
STACK S;
S = (STACK) malloc( sizeof( struct student ) );
if(S == NULL) printf("out of space!");
return S;
}
void push(int x, STACK S)
{
std_ptr tmp;
tmp = (std_ptr) malloc(sizeof(struct student));
if(tmp == NULL) printf("out of space!");
else
{
tmp -> number = x;
tmp -> next = S -> next;
S -> next = tmp;
}
}
int main()
{
push(12058010,STACK S);
return 0;
}
Im trying to call function and I get error: expected expression before stack.I also tried to call the function like that
int main()
{
push(12058010,S);
return 0;
}
This time I get error: 'S' undeclared(first use in this function)
Thank you for your help!
Define the variable s by doing:
STACK s;
Initialise it:
s = create_stack();
Test whether the initialisation succeeded:
if (NULL == s)
{
return EXIT_FAILURE;
}
Use it by calling push() like this:
push(12058010, s);
All together this could look like this:
int main(void)
{
STACK s = create_stack(); /* This merges step 1 and 2. */
if (NULL == s)
{
return EXIT_FAILURE;
}
push(12058010, s);
return EXIT_SUCCES;
}
S is neither in the global scope nor in the scope of main().
I suspect you meant to write STACK S = create_stack(); as the first statement in main().
Don't forget to free the allocated memory as well.
I am currently in a University program studying Data Structures in C and I am having a lot of trouble right now. I want to make clear that what I am asking help for is not for marks, just practice challenge problems.
The goal is to implement a stack using Linked Lists. By looking through the lecture notes I think I have most of the functions down. I need to demonstrate Push() and Pop() will an append and a pretend. Using Cygwin, I compiled with no errors. but when I try to run it, I get a "Segmentation Fault". What does this mean and how do I fix it? if I remove "stack = initLListStack();", the error disappears. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Link{
int *value;
struct Link *next;
}Link;
typedef struct LList1{
int *size;
Link *head;
}LList1;
typedef struct LListStack{
LList1 *llist;
}LListStack ;
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
}
void removefront(LList1 *llist)
{
if(llist->head != NULL){
llist->head = llist->head->next;
llist->size--;
}
}
Link *FindLastLink(LList1 *llist, Link *link)
{
if(link = NULL){
return(NULL);
}
else if(link->next == NULL){
return(link);
}
else{
return(FindLastLink(llist, link->next));
}
}
Link *FindSecondLastLink(LList1 *llist, Link *link)
{
if(link = NULL){
return(NULL);
}
else if(link->next->next == NULL){
return(link);
}
else{
return(FindSecondLastLink(llist, link->next));
}
}
void removelast(LList1 *llist)
{
Link *secondlastlink = (Link *) malloc(sizeof(Link));
secondlastlink = FindSecondLastLink(llist, llist->head);
secondlastlink->next = NULL;
llist->size--;
}
void prepend(int *newValue, LList1 *templist)
{
Link *node = (Link *) malloc(sizeof(Link));
node->value = newValue;
node->next = templist->head;
templist->head = node;
templist->size++;
}
void append(int *newValue, LList1 *templist)
{
Link *node = (Link *) malloc(sizeof(Link));
Link *lastlink = (Link *) malloc(sizeof(Link));
lastlink = FindLastLink(templist, templist->head);
node->value = newValue;
lastlink->next = node;
node->next = NULL;
templist->size++;
}
void prepush(int *value, LListStack *stack)
{
prepend(value, stack->llist);
}
void apppush(int *value, LListStack *stack)
{
append(value, stack->llist);
}
int prepop(LListStack *stack, int *value)
{
int result ;
if ((!isEmpty(stack)))
{
removefront(stack->llist);
result = 1 ;
}
else {
result = 0 ;
}
return(result) ;
}
int isEmpty(LListStack *stack)
{
int empty;
if (stack->llist->head == NULL)
return( 1 ) ;
else
return( 0 ) ;
}
int apppop(LListStack *stack, int *value)
{
int result ;
if ((!isEmpty(stack)))
{
removelast(stack->llist);
result = 1 ;
}
else
result = 0 ;
return(result) ;
}
//*******MAIN**********//
int main()
{
LListStack *stack = (LListStack *) malloc (sizeof(LListStack));
stack = initLListStack(); //if I take this away, I can run the program
return(0);
}
I don't have that much in Main() yet because I'm just trying to get it to run first. Initializing the Stack seems to be the problem.
Thanks for your help guys!
The problem is in your initLListStack() function:
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
The result of malloc is an uninitialized block of memory large enough to hold an LListStack struct.
The very first thing you do with that memory is read its llist member. Since this is uninitialized, you invoke undefined behavior which, fortunately, causes a segfault. (The compiler would be within the specification to send embarrassing e-mails to our instructor when this happens.)
You need to initialize llist before you can use that member in stack. Something like:
LListStack *stack = malloc(sizeof(*stack));
stack->llist = malloc(sizeof(*stack->llist));
stack->llist->size = 0;
stack->llist->head = NULL;
return stack;
Note that I've also removed some unnecessary casts and parentheses, and changed the sizeof operator to calculate the memory you need based on the pointer you're storing into.
A segmentation fault error is usually caused by trying to dereference an uninitialized pointer. In your case, you have allocated memory for stack in your initLListStack method but you haven't initialized it -- in particular the llist field is not initialized to any particular value. You need to allocate an LList1 and set the llist field to the newly-allocated memory.
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0; // **this is probably where it crashes**
stack->llist->head = NULL;
return(stack);
}
You allocate stack ok, but you do not allocate stack->llist. So stack->llist is uninitialized and then you dereference it in stack->llist->size . Dereferencing an
uninitialized variable results in undefined behavior.
To fix this, allocate stack->list like this:
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist = (LListStack *) malloc(sizeof(LList1)) ; // ADD THIS LINE
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
}