when I'm trying to push elements to a stack I get segmentation fault, but if I open address for stack(i marked them with "!!!") and it's symbols it accepts it. But this time in each push, it creates new address and doesn't increase top value.
typedef struct
{
struct table **symbols; // array of the stack
int top; //index of the top element
int size; //maximum size of the stack
}stack;
void push(stack *stck,struct table *element)
{
if(stck->top == stck->size)
{
printf("stack is full");
return;
}
stck = malloc(sizeof(stack)); !!!
stck->symbols = (struct table **)malloc(50 * sizeof(struct table*)); !!!
printf("top : %d\n",stck->top);
stck->top = stck->top++;
printf("%d"&stck->top);
stck->symbols[stck->top] = element;
printf("top : %d\n",stck->top);
}
You have to construct your stack before you can push anything onto it. Eg. create function stack_new that will allocate memory for your stack and initialize its members:
stack * stack_new (size_t size)
{
stack * stck = malloc(sizeof(stack));
stck->top = -1;
stck->size = size
stck->symbols = (struct table **)malloc(size * sizeof(struct table*));
return stck;
}
Now, once you properly constructed your stack with above function, you may pass it to push function.
You are passing one stack in a variable called stck, but then allocating a new structure and assigning it to the same pointer. So the stack you pass in is never modified. I don't think you need the first malloc call.
Before you ever call push, you are going to want to malloc space for the stack.
With the !!! lines, you are allocating new memory with each push, which is wrong.
Without the !!! lines, you are never allocating the memory
If you pass a single pointer stack *stck and then malloc inside the function, it will not reflect once you get out the function.
Also, why do you need to allocate memory for table for 50 pointers each time you want to push?
Do it like below:
struct table
{
//members go here
};
typedef struct
{
struct table **symbols;
int top;
int size;
}stack;
struct table *get_elem(void)
{
//logic for getting elements go here
}
void stack_push(stack *stck, struct table *element)
{
if(stck->top==stck->size)
{
printf("Stack Full\n");
return;
}
stck->top++;
stck->symbols[stck->top] = element;
return;
}
void stack_func()
{
struct table *elem = NULL;
stack *stck = (stack *)malloc(sizeof(stack));
if(NULL==stck)
{
return;
}
stck->top = -1;
stck->symbols = (struct table **)malloc(50 * sizeof(struct table *));
if(NULL == stck->symbols)
{
free(stck);
return;
}
stck->size = 49;
elem = get_elem();
//do check here for correctness of elem returned from get_elem
stack_push(stck, elem);
return;
}
Hope this helps! : )
Related
In this code I pass struct stack * sp as call by value ,if it pass by value approach then how it gets update the value in functions and if I miss something then help this to find out?
#include<stdio.h>
#include<conio.h>
struct stack{
int size ;
int top;
int * arr;
};//creating structures
void traversal(struct stack *sp){
for(int i=0;i<=sp->top;i++){
printf("%d\n",sp->arr[i]);
}
}
int isEmpty(struct stack* ptr){
if(ptr->top == -1){
return 1;
}
else{
return 0;
}
}
int isFull(struct stack* ptr){
if(ptr->top == ptr->size - 1){
return 1;
}
else{
return 0;
}
}
void push(struct stack* ptr, int val){
if(isFull(ptr)){
printf("Stack Overflow! Cannot push %d to the stack\n", val);
}
else{
ptr->top=ptr->top+1;//how it gets update when i pass by value
ptr->arr[ptr->top] = val;
}
}
int pop(struct stack* ptr){
if(isEmpty(ptr)){
printf("Stack Underflow! Cannot pop from the stack\n");
return -1;
}
else{
int val = ptr->arr[ptr->top];
ptr->top=ptr->top-1;//ptr pass by value how it gets update
return val;
}
}
int main(){
**struct stack *sp** = (struct stack *) malloc(sizeof(struct stack));//local pointer variable
sp->size = 10;
sp->top = -1;
sp->arr = (int *) malloc(sp->size * sizeof(int));
printf("Stack has been created successfully\n");
push(sp,10);//pass by value in push
push(sp,200);//pass by value in push
traversal(sp);
printf("the %d element from stack is popped\n",pop(sp));
printf("the %d element from stack is popped\n",pop(sp));
traversal(sp);
return 0;
}
Now in this code push and pop modify the top and array as I say I passed as a call by value as you see but they are also get modified in the above code but how?
Your code seems to contain some errors so let me address those first:
in the main() function you have declared this **struct stack *sp** = (struct stack *) malloc(sizeof(struct stack)). this is wrong and will bring up a error. You seem to want to pass sp by value, the correct way to declare sp would be to do struct stack *sp = (struct stack *) malloc(sizeof(struct stack)).
You seem to be mainly confused on how the struct that sp points to is being modified by the functions that you have made to implement a stack, lets go through main() and see what happends.
main():
int main(){
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));//local pointer variable
sp->size = 10;
sp->top = -1;
sp->arr = (int *) malloc(sp->size * sizeof(int));
printf("Stack has been created successfully\n");
push(sp,10);//pass by value in push
push(sp,200);//pass by value in push
traversal(sp);
printf("the %d element from stack is popped\n",pop(sp));
printf("the %d element from stack is popped\n",pop(sp));
traversal(sp);
return 0;
}
So i will break down how this works:
First of all in main() we have a pointer to a struct of type struct stack:
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));
This struct has some memory allocated for it and, sp stores the address of this struct.
Next in main() you store 10 in the member called size in the struct that sp points to:
sp->size = 10;
You also store -1 in the member called top in the struct that sp points to:
sp->top = -1;
Lastly you allocate some memory for the stack in this line, in this case you allocate 40 bytes for 10 ints:
sp->arr = (int *) malloc(sp->size * sizeof(int));
Now moving to the function calls:
you wrote push(sp,10)
lets break this down further and take a look at push()
push():
void push(struct stack* ptr, int val){
if(isFull(ptr)){
printf("Stack Overflow! Cannot push %d to the stack\n", val);
}
else{
ptr->top=ptr->top+1;//how it gets update when i pass by value
ptr->arr[ptr->top] = val;
}
}
push() takes 2 parameters, one is a pointer to a struct, the second is a integer value.
push(sp,10)
Now you pass sp to the first parameter struct stack* ptr, remember sp holds the address of a struct that you allocated memory for in main().
you are now giving this address to struct stack* ptr which is a local pointer to the push() function. After push() ends, struct stack* ptr will get destroyed.
With this in mind you are passing sp by value since you are not actually passing sp itself (address of sp), you are passing the address that sp is pointing to/holding into a copy which would be struct stack* ptr.
And now since you pass the address of the struct that sp is holding/pointing too, this address can be modified.
I'm doing an exercise, and want support about it. The problem is this: I have two structures (1 for the nodes of the stack, 1 for the stack). In the node structure, there is a void* data field.
I've tried to push a value on the stack but, because of void* data instead of simple data, I failed.
This is the code about the structures and the push() function.
struct upo_stack_node_s
{
void *data;
struct upo_stack_node_s *next;
};
typedef struct upo_stack_node_s upo_stack_node_t;
struct upo_stack_s
{
upo_stack_node_t *top;
size_t size;
};
/*Function for create the stack*/
upo_stack_t upo_stack_create()
{
upo_stack_t stack = malloc(sizeof(struct upo_stack_s));
if (stack == NULL)
{
fprintf(stderr, "Unable to create a stack!\n");
abort();
}
stack->top = NULL;
stack->size = 0;
return stack;
}
/*Push() function:*/
void upo_stack_push(upo_stack_t stack, void *data)
{
/* TO STUDENTS:
* Remove the following two lines and put here your implementation
*/
upo_stack_node_t *node = malloc(sizeof(struct upo_stack_node_s));
node->data = data; /*<-- Here's the problem */
node->next = stack->top;
stack->top = node;
++stack->size;
}
/*Top() function*/
void* upo_stack_top(const upo_stack_t stack)
{
/* TO STUDENTS:
* Remove the following two lines and put here your implementation
*/
return (void *)(stack->top); //<---
}
/*Function for testing (there are other functions in the code)*/
void test_top()
{
int value1 = 1;
int value2 = 2;
upo_stack_t stack;
stack = upo_stack_create();
upo_stack_push(stack, &value1); //<----
upo_stack_push(stack, &value2); //<----
assert( upo_stack_top(stack) != NULL );
assert( *((int*) upo_stack_top(stack)) == value2 ); <-- Here's the error
upo_stack_pop(stack, 0);
assert( upo_stack_top(stack) != NULL );
assert( *((int*) upo_stack_top(stack)) == value1 );
upo_stack_pop(stack, 0);
assert( upo_stack_top(stack) == NULL );
upo_stack_destroy(stack, 0);
}
You always have to pass a void pointer. That means if you want to pass a simple value, like 1, what you need to do is, is to allocate an integer value, and pass the pointer to it (as a void pointer).
Thus something like:
int x = 4;
upo_stack_push(upo_stack, &x);
Of course you have to make sure the int variable x does not go out of scope, otherwise the pointer will point to freed memory, which results in nasty memory problems.
Update
It is assumed above, that the void pointer you pass is stored already in memory for the scope of the stack. In case, you want the stack itself to copy the data, you have also to malloc space for that, thus not only mallocing the node, but also mallocing and copy the data type passed. Also to know the size of the data (since it is a void pointer, which is unaware of its type), you have to add an int size parameter to the push function.
For an integer value to be stored, pass it as a pointer, with size: sizeof(int). Than for copying the data structure, use memcpy. This only works for simple types and structures without pointers. If you have to copy structures with pointers (thus you need so called deep-copying), than it is more tricky.
i have a problem inside my program, i've implemented a simple stack in C
the problem is that when i try to reallocate the stack array for the second time, the program triggers a brekapoint just inside the realloc function, i don't know what could be wrong since i'm using a buffer to check whether realloc fails or not. probably, this code is where i use the realloc function:
struct stack {
void** data;
int top;
int initial_size;
};
static void stack_resize(struct stack* instance, int capacity)
{
if (instance->initial_size == instance->top)
{
int new_sz = capacity * sizeof *instance->data;
// THIS REALLOC crashes
void** buffer = realloc(instance->data, new_sz); // realloc the stack array
printf("reallocating memory\n");
if (buffer) {
instance->data = buffer;
instance->initial_size = new_sz;
}
}
}
the following function instead, is where the stack_resize() gets called
void stack_push(struct stack* instance, void* data)
{
if (instance->top >= instance->initial_size)
{
// shrink the array
stack_resize(instance, instance->initial_size);
}
instance->data[++instance->top] = data;
printf("pushing onto the stack!\n");
}
This is the constructor where i initialize all the data.
struct stack* stack_new(int initial_size)
{
struct stack* new_stack = (struct stack*)malloc(sizeof(struct stack));
if (!new_stack) {
fprintf(stderr, "no memory available from the operative system\n");
return NULL;
}
memset(new_stack, 0, sizeof(struct stack));
new_stack->data = (void**)malloc(sizeof(void*) * initial_size);
if (!new_stack->data) {
fprintf(stderr, "could not allocate memory for the buffer\n");
return NULL;
}
printf("created a stack with %d slot(s)\n", initial_size);
new_stack->top = -1;
new_stack->initial_size = initial_size;
return new_stack;
}
and this is the entry point of the program:
int main(int argc, char** argv)
{
struct stack* new_stack = stack_new(2);
for (int i = 0; i < 55; i++)
{
stack_push(new_stack, (void*)i);
}
getchar();
return 0;
}
Any help would be much appreciated! thanks to all.
Crash is seen because you are assigning new_sz to instance->initial_size.
since new_sz holds actual size of array in bytes, which is capacity*sizeof(void *)
int new_sz = capacity * sizeof *instance->data;
instance->initial_size = new_sz;
your stack top and initial_size will mismatch.
if (instance->top >= instance->initial_size)
Your top will always less then initial_size and you will not allocate new memory.
In order to your program to work you need to make the following changes.
int new_sz = (capacity+1) * sizeof(void *);
instance->initial_size = capacity+1;//instead of new_size
I have been doing excercises from a book. And I am stuck on the meaning of this qustion. Assuming that you store integer values on the stac and that using a static array to store data provide a createStack() deleteStack(stack) methods.
My interpretation is
typedef struct {
int values;
char data[50];
} StackData;
typedef struct n {
StackData d; // store some data in node
struct n *successor; // store successor of node
// as typedef is not yet completed
// name StackNode cannot be used
} SatckNode;
typedef struct {
StackNode *head;
StackNode *current;
} Stacklist;
I know these arent the methods. But i want to know if I am going about it the right way
If you're using a static array for the values, then you don't technically need createStack() and deleteStack() functions, because you can just create a struct stack or whatever on the stack (pun intended) and you're done.
If you do want to, though, (and you might legitimately want to, e.g. to avoid having to explicitly initialize top, or to hide the implementation behind an opaque type, or to be able to return one from a function without copying a potentially large array) this'll do it:
#include <stdio.h>
#include <stdlib.h>
#define STACKSIZE 50
typedef struct stack * Stack;
struct stack {
size_t top;
int values[STACKSIZE];
};
Stack createStack(void)
{
Stack new_stack = malloc(sizeof *new_stack);
if ( !new_stack ) {
perror("couldn't allocate memory");
exit(EXIT_FAILURE);
}
new_stack->top = 0;
return new_stack;
}
void deleteStack(Stack stack)
{
free(stack);
}
void push(Stack stack, const int n)
{
if ( stack->top < STACKSIZE ) {
stack->values[stack->top++] = n;
}
else {
fprintf(stderr, "Stack full - exiting.\n");
exit(EXIT_FAILURE);
}
}
int pop(Stack stack)
{
if ( stack->top > 0 ) {
return stack->values[--stack->top];
}
else {
fprintf(stderr, "Stack empty - exiting.\n");
exit(EXIT_FAILURE);
}
}
int main(void)
{
Stack mystack = createStack();
push(mystack, 3);
push(mystack, 1);
push(mystack, 4);
push(mystack, 1);
push(mystack, 5);
for ( size_t i = 0; i < 5; ++i ) {
printf("Popped %d from stack.\n", pop(mystack));
}
deleteStack(mystack);
return 0;
}
Right now you seem to want a stack with values in a static array, but then you start defining structs for nodes and lists, as if you want a linked list implementation. The two implementations are obviously pretty different.
I think you're on the right way - just a couple of comments.
In Stacklist, I don't get why you have pointers to two of the nodes in the stack.
Usually, stacks only keep a reference to the item on the top of the stack.
In addition, they either keep a counter of how big is the stack, or a pointer to the node on the bottom of the stack (which is what you probably mean by head, and reference the head node by current?).
And don't forget to initialize everything whenever you create any of those structures :P usually ends up in endless hours of headache.
Keep up the good work.
I am currently working on stacks right now. I am supposed to use the following structures and function prototypes:
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
Here is my actual code for create_stack() and push():
stack* create_stack()
{
stack *stack;
stack = malloc(sizeof(stack));
stack->size = 0;
stack->stack = NULL;
return stack;
}
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack();
newStack->stack->data = val;
newStack->stack = s->stack;
s = newStack;
}
I am getting a segmentation fault when I try to store char val into newStack->stack->data. How does this not work? What do I need to do to make this stack on top???
The push function is wrong.
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack(); /* new stack created, why not work on the existing one ? */
newStack->stack->data = val; /* you're writing to a NULL pointer */
newStack->stack = s->stack;
s = newStack; /* this will not be visible from outside the function */
}
First of all, you are trying to recreate a new stack for each call of this function, which is certainly not what is intended.
If you try to modify the value of s, it will not be visible from outside the function, and you will still have your original stack.
Then, you are accessing the stack->data member even though stack has no space allocated to it yet (because you set it to NULL). You actually set it right after, which is why it crashes, most probably.
You probably want to do something like this:
void push(stack* s, char val)
{
node * n;
/* go to the end of the "stack" */
n = s->stack;
while (n != NULL) {
n = n->next;
}
/* allocate memory for a new node */
n = malloc(sizeof(node));
/* initialize node */
n->data = val;
n->next = NULL;
/* increment stack size */
s->size++;
}
And as mentionned before, this is merely a singly-linked list which is not the best fit for a stack, because as it exists now, you have to follow the node pointers to reach the last element, which makes push and pop operations O(N).
A faster implementation would look like this:
void push(stack* s, char val)
{
node * first_node, * new_node;
first_node = s->stack;
/* allocate memory for a new node */
new_node = malloc(sizeof(node));
/* initialize node */
new_node->data = val;
new_node->next = first_node;
/* increment stack size */
s->stack = new_node;
s->size++;
}
The top of the stack is always the first node, and the performance is O(1).
Follow your code....
stack *newStack = create_stack(); // in push()
newStack = malloc(sizeof(stack)); // in create_stack()
newStack->stack = NULL; // in create_stack()
newStack->stack->data = val; // in push()... this is where you crash.
Because newStack->stack is a NULL pointer. Your create_stack() function sets it to NULL, and you then dereference it. You have to allocate a struct node somewhere.
This code also has some readability issues which might be contributing to the problem. You are naming variables the same names as their types, which is very confusing. Consider using some other naming pattern like stack_t for types and stack for variable names.