Stack - Push implementation - file

Can anyone please explain here what is the issue in the below code because of that it is not producing any errors as well as any output?
#include <stdio.h>
#include <stdlib.h>
typedef struct Stack{
int size;
int top;
int data;
int *arr;
} Stack;
void push( Stack*s , int data)
{
s->top++;
s->arr[s->top] = data;
}
int main()
{
struct Stack *s;
s->size = 100;
s->top = -1;
s->arr = (int* ) malloc (s->size* sizeof(int));
push( s, 180);
}

this is because you write struct Stack *s; which is just a wild pointer pointing to some space in memory with no reserved space, so you should do instead :
struct Stack *s = (struct Stack* ) malloc (sizeof(struct Stack));
to reserve space for your wild pointer.
even my compiler gave me this warning, so make sure to turn on all compiler warnings on yours.
Variable 's' is uninitialized when used here
this is the full code with only this small modification:
#include <stdio.h>
#include <stdlib.h>
typedef struct Stack{
int size;
int top;
int data;
int *arr;
} Stack;
void push( Stack*s , int data)
{
s->top++;
s->arr[s->top] = data;
}
int main()
{
//struct Stack *s = (struct Stack* ) malloc (sizeof(struct Stack));
struct Stack *s;
s->size = 100;
s->top = -1;
s->arr = (int* ) malloc (s->size* sizeof(int));
push( s, 180);
printf("stack top data = %d\n", s->arr[s->top]);
}
and this is the output:
stack top data = 180

Related

Adding item to a stack make it crash

I am trying to implement on my own (in order to understand it better) the Stack data structure in C language.
Here is what I've got so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stack{
//Data_Strucure: Stack of intgers
int *stack;
int size_of_stack;
int elem_in_stack;
};
struct stack *creat_stack(unsigned int);
int push(struct stack *, int);
int pop(struct stack *);
int empty(struct stack *);
int peek(struct stack *);
int main(int argc, char *argv[]){
int new_elem = 13;
struct stack *new_stack = creat_stack(5);
printf("%d %d\n", new_stack->size_of_stack, new_stack->elem_in_stack);
//Crashes from here
push(new_stack, new_elem);
printf("%d\n", new_stack->stack[new_stack->size_of_stack]);
}
struct stack *creat_stack(unsigned int size){
struct stack tmp;
struct stack *ret_stack = &tmp;
if((ret_stack->stack = malloc(sizeof(int) * size)) == NULL){
fprintf(stderr, "Unable to allocate memory for the Stack.\n");
exit(1);
}
ret_stack->size_of_stack = size;
ret_stack->elem_in_stack = 0;
return ret_stack;
}
int push(struct stack *stack, int nw_elem){
int pos = stack->size_of_stack - stack->elem_in_stack;
if(stack->size_of_stack == 0)
return 1;
stack->stack[pos] = nw_elem;
}
The compiler returns me no error. Though I don't understand why it crashes after push() is called.
Please, if possible, instead of solution code, can you just tell me where the error is? This way I can understand how it effect the whole program and try to solve it on my own (so next time won't happen again).
Thanks is advance for any of your usefull answers.
At least the function creat_stack is incorrect.
struct stack *creat_stack(unsigned int size){
struct stack tmp;
struct stack *ret_stack = &tmp;
//...
return ret_stack;
}
It returns a pointer to the local object tmp that will not be alive after exiting the function. So the returned pointer will be invalid and dereferencing such a pointer invokes undefined behavior.
Instead you could return the object itself from the function. That is the function declaration could look like
struct stack creat_stack(unsigned int size);
And in main you can write
struct stack new_stack = creat_stack(5);
Also the function push does not change the data member elem_in_stack And again it invokes undefined behavior because when elem_in_stack is equal to 0 then the function tries to write to memory outside the dynamically allocated array. That is in this case pos is equal to size_of_stack.
int push(struct stack *stack, int nw_elem){
int pos = stack->size_of_stack - stack->elem_in_stack;
if(stack->size_of_stack == 0)
return 1;
stack->stack[pos] = nw_elem;
}

I was trying to create a stack data type using array in pointer. But my program is giving segmentation fault

This is the code here. Even after debugging I'm not able to find the problem. The code was working fine if I'm not using the pointer.
#include <stdio.h>
#include <stdlib.h>
struct stack{
int size;
int top;
int *arr;
};
int isEmpty(struct stack *ptr){
if ((*ptr).top == -1){
return 1;
}
else{
return 0;
}
}
int main()
{
struct stack *s;
(*s).size = 80;
(*s).top = -1;
(*s).arr = (int *)malloc((*s).size * sizeof(int));
// Check if stack is empty
if(isEmpty(s)){
printf("The stack is empty");
}
else{
printf("The stack is not empty");
}
return 0;
}
You did not allocate any memory for your struct. You may decalre it on the stack: struct stack s; or allocate memory for it: struct stack *s = (struct stack *)malloc(sizeof(struct stack));.
When you have a pointer to a struct, please use the -> operator to access its members like so s->size.

Pointer passed in to function not reassigning

So I'm trying to implement a linked list stack that takes in char arguments and adds them to the link list with it's ascii code as the value of the nodes.
I pass in my nstack pointer into my push function and re-assign it to new_node in order to create a new top, but my push function doesn't seem to be reassigning my nstack node - it just prints the originally initialized nstack value. Why isn't nstack being reassigned?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list_node {
int element;
struct list_node * pnext;
};
void push(struct list_node *operators, int e);
int pop(struct list_node *operators);
int main(int argc, char *argv[]) {
int newvalue = (int)argv[1][0];
struct list_node * nstack = (struct list_node*)malloc(sizeof(struct list_node));
nstack->element = newvalue;
nstack->pnext = NULL;
int i;
for (i = 2; i < argc; i++) {
push(nstack, (int)argv[i][0]);
}
printf("top: %d\n", nstack->element);
}
void push(struct list_node *nstack, int e) {
struct list_node * new_node = (struct list_node*)malloc(sizeof(struct list_node));
new_node->pnext = nstack;
new_node->element = e;
nstack = new_node;
}
Because you are passing a copy of pointer (by value). You need something like this (pointer to pointer):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list_node {
int element;
struct list_node * pnext;
};
void push(struct list_node **operators, int e);
int pop(struct list_node *operators);
int main(int argc, char *argv[]) {
//int newvalue = (int)argv[1][0];
int newvalue = 1;
struct list_node * nstack = (struct list_node*)malloc(sizeof(struct list_node));
nstack->element = newvalue;
nstack->pnext = NULL;
int i;
for (i = 2; i < 7; i++) {
//push(nstack, (int)argv[i][0]);
push(&nstack, i);
}
printf("top: %d\n", nstack->element);
}
void push(struct list_node **nstack, int e) {
struct list_node * new_node = (struct list_node*)malloc(sizeof(struct list_node));
new_node->pnext = *nstack;
new_node->element = e;
*nstack = new_node;
}
To expand on Tarod's correct point. What the caller function is doing is taking a copy of your pointer value and putting it onto the stack or in a register (compiler dependent) that will then be used in your push function. However, within your push function you're actually changing the value in this register or stack location before returning. But when you return the caller function basically discards this information (its popped of the stack - or, again depending on the compiler, uses the register for something else). The only way around this is to pass the address of the pointer and deference this when you need to write to it as Tarod has shown.

Why do I need to use & to pass a pointer to a struct in this stack implementation [duplicate]

This question already has answers here:
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 7 years ago.
In the following program I need to pass an argument to a function using the &-operator although I expect it to be a pointer and the function is expecting a pointer. Why do I need to do this?
The program implements a simple stack using linked lists and incomplete types in C. Here are the three necessary files:
stack.h
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
struct Stack {
int number;
struct Stack *next;
};
/*
* We declare a pointer to a Stack structure thereby making use of incomplete
* types. Clients that pull in stack.h will be able to declare variables of type
* pstack which are pointers to Stack structures. */
typedef struct Stack *pstack;
bool is_empty(pstack *s);
void make_empty(pstack *s);
void push(pstack *s, int new_num);
int pop(pstack *s);
#endif /* STACK_H */
stack.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
bool is_empty(pstack *s)
{
return !s;
}
void make_empty(pstack *s)
{
if (!is_empty(s))
pop(s);
}
int pop(pstack *s)
{
struct Stack *tmp;
int i;
if (is_empty(s)) {
exit(EXIT_FAILURE);
}
tmp = *s;
i = (*s)->number;
*s = (*s)->next;
free(tmp);
return i;
}
void push(pstack *s, int new_num)
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;
}
stackclient.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main(void)
{
pstack s1;
int n;
push(&s1, 1);
push(&s1, 2);
n = pop(&s1);
printf("Popped %d from s1\n", n);
n = pop(&s1);
printf("Popped %d from s1\n", n);
exit(EXIT_SUCCESS);
}
Again, I thought that by using
typedef struct Stack *pstack;
and later on in main()
pstack s1;
I'm declaring a pointer to the linked list Stack and hence it would be fine to simply pass s1 to say push() by just using
push(s1, 1);
but I actually need to use
push (&s1, 1);
Why?
Your functions are all declared to take pstack* as an argument, which is actually a pointer to a pointer to a Stack struct. Just use pstack. You'll also need to replace the instances of (*s) with just s in the implementations of those functions.
Edit: As was pointed out in the comments, you actually write to (*s) in the function implementations and rely on this behavior for correctness, so you need to keep the argument as pstack*. Conceptually, this is because the stack variable (s1) is literally the top of the stack itself, and so must be modified by push and pop.
You need to use pstack *s ( pointer to pstack ) in void push(pstack *s, int new_num), according to your implementation code,
if to use pstack s( pstack ), the new_node will not be returned correctly.
Two possible ways to insert a Node in push():
if insert to head, it should be *s = new_node
if insert to tail, it could be s->next = new_node
Back to the code, if to use push(s1, 1); such as,
//If only use pstack s, the new_node can not be pushed.
void push(pstack s, int new_num) //it is a wrong implementation for demo
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = s;
s = new_node;// WRONG! here, the new_node cannot be kept by s
// two typical node insert ways:
// 1)if insert to head, it should be *s = new_node
// 2)if insert to tail, it could be s->next = new_node
//Now, Your code applied the #1 way, so need *s
}
So, it should be inputed pstack *s, and call with push (&s1, 1);
void push(pstack *s, int new_num)//it is the correct version the same as your post
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node) {
exit(EXIT_FAILURE);
}
new_node->number = new_num;
new_node->next = *s;
*s = new_node;//here, the new_node could be kept by *s
}

dynamically allocate arrays of pointers to structures in C

I have this structure here:
typedef struct _open {
int x;
struct _open *next;
} *NODE;
And on my main function I declared this pointer:
NODE open = initOpen(size);
Here's the initOpen function:
NODE initOpen(int size) {
return (NODE)malloc(sizeof(struct _open)*size);
}
I this correct? can I access my array in the main function like: open[0] to open[9] ?
First of all, the way you are doing dynamically allocated array is wrong.
I'm not sure if you actually want the thing you wrote, which is linked list, or the thing you said, which is dynamically allocated array.
Below is how you should do dynamically allocated array. Hope it helps.
By doing so, you can add as many ints into the array as you want, before you run out of memory. And you can access the array using array notation but with a pointer first: darray->array[0]
Your linked list, however, can not be accessed with this syntax.
#include <stdio.h>
#include <stdlib.h>
#define INITSIZE 8
typedef struct dyarr{
int num;
int max;
int *array;
}arr;
arr* makeArr();
void add( arr*, int );
int main( int argc, char const *argv[] ){
int t;
arr* darray = makeArr();
while( scanf( "%d", &t ) != EOF ){
add( darray, t );
}
int i;
for( i = 0; i<darray->num; i++ ){
printf( "%d\n", darray->array[i] );
}
getchar();
return 0;
}
arr* makeArr(){
arr* A = malloc( sizeof( arr ) );
A->max = MAXSIZE;
A->num = 0;
A->array = malloc( sizeof( int )*A->max );
return A;
}
void add( arr* a, int i ){
if( a->num == a->max ){
a->max *= 2;
a->array = realloc( a->array, a->max );
}
a->array[a->num++] = i;
}
First of all, you should respect some conventions:
typedef struct node {
int x;
struct node *next;
} *nodePtr;
Second, what is the usage of the parameter size ?
According to me the right way to allocate a new nodePtr is:
nodePtr initNodePtr() {
return (nodePtr)malloc(sizeof(struct node));
}
Also dont forget to release memory after usage:
nodePtr node = initNodePtr();
...
...
free(node); //should be wrapped in a function to respect design.
To Create an array of structure, you should do the following:
typedef struct {
int x;
node* next;
} node;
int main() {
node* nodeArray = (node*)malloc(sizeof(node)*50); // 50 = size of your array
...
// do whatever you want
...
free(nodeArray);
}
Not tested, let me know if errors.

Resources