Search code examples
cstack

Why can't I allocate memory to more than 3 elements in C Stack?


Dynamic memory allocation not working like I want it to, any ideas why ?

I tried to allocate memory to Stack (stucture member).

But no matter what length I tried to provide, it only pushes value upto 3 elements, I can't get it.

Is the problem with Push() , calloc() or sizeof()?

#include <stdio.h>
#include <stdlib.h>

typedef enum {
    FALSE,
    TRUE
} Boolean;

typedef struct a {
    int *stack, sp;
} Stack;

int IsEmpty(Stack *s)
{
    if (s->sp == -1)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

int IsFull(Stack *s)
{
    if (s->sp == sizeof(s->stack) / sizeof(int))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

void Push(Stack *s)
{
    int num;
    if (IsFull(s))
    {
        printf("Stack Overflow\n");
    }
    else
    {
        s->sp++;
        printf("Enter the Element:");
        scanf("%d", &num);
        s->stack[s->sp] = num;
    }
}

void Pop(Stack *s)
{
    if (IsEmpty(s))
    {
        printf("Stack Underflow\n");
    }
    else
    {
        s->sp--;
    }
}

void Peek(Stack *s)
{
    printf("The Element at the peak is %d", s->stack[s->sp]);
}

void Display(Stack *s)
{
    if (s->sp < 1)
    {
        printf("Stack is empty\n");
    }
    else
    {
        for (int i = 0; i <= s->sp; i++)
        {
            printf("The element at the index %d is %d\n", i, s->stack[i]);
        }
    }
}

int Option()
{
    int opt;
    printf("\nSelect Option\n\n1.Push\n2.Pop\n3.Peek\n4.Display\n5.Exit\n");
    scanf("%d", &opt);
    return opt;
}

void EmptyStack(Stack *s)
{
    int ln;
    s->sp = -1;
    printf("Enter the length of stack : ");
    scanf("%d", &ln);
    s->stack = (int *)calloc(ln, sizeof(int));
    if (s == NULL)
    {
        printf("Insufficient Memory");
        exit(0);
    }
    else
    {
        printf("Memory Allocated Successfully");
    }
}

void main()
{
    int opt;
    Stack s;
    EmptyStack(&s);
    while (1)
    {
        opt = Option();
        switch (opt)
        {
        case 1:
            Push(&s);
            break;
        case 2:
            Pop(&s);
            break;
        case 3:
            Peek(&s);
            break;
        case 4:
            Display(&s);
            break;
        case 5:
            exit(1);
        default:
            printf("Invalid Choice\n");
            break;
        }
    }
}

Any help to figure this out is appreciated, thank you!


Solution

  • You cannot use sizeof(s->stack) to compute the length of the array allocated by calloc() to which s->stack points. You must store the length in the Stack structure when you allocate the array.

    typedef struct a {
        int *stack;
        int sp, len;
    } Stack;
    

    Also note that the test for IsFull is inconsistent with your usage of the sp index. You should check that sp is below s->len - 1.

    Here is a modified version:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Stack {
        int *stack;
        int sp, len;
    } Stack;
    
    int IsEmpty(const Stack *s) {
        return (s->sp <= -1);
    }
    
    int IsFull(const Stack *s) {
        return (s->sp >= s->len - 1);
    }
    
    void Push(Stack *s) {
        int num;
        if (IsFull(s)) {
            printf("Stack Overflow\n");
        } else {
            printf("Enter the Element:");
            if (scanf("%d", &num) == 1) {
                s->sp++;
                s->stack[s->sp] = num;
            } else {
                printf("invalid input\n");
                scanf("%*[^\n]");  // consume the offending input
            }
        }
    }
    
    void Pop(Stack *s) {
        if (IsEmpty(s)) {
            printf("Stack Underflow\n");
            return 0;
        } else {
            return s->stack[s->sp--];
        }
    }
    
    void Peek(const Stack *s) {
        if (IsEmpty(s)) {
            printf("Stack is empty\n");
        } else {
            printf("The Element at the peak is %d\n", s->stack[s->sp]);
        }
    }
    
    void Display(const Stack *s) {
        if (IsEmpty(s)) {
            printf("Stack is empty\n");
        } else {
            for (int i = 0; i <= s->sp; i++) {
                printf("The element at the index %d is %d\n", i, s->stack[i]);
            }
        }
    }
    
    int Option(void) {
        int opt;
        printf("\nSelect Option\n\n"
               "1.Push\n"
               "2.Pop\n"
               "3.Peek\n"
               "4.Display\n"
               "5.Exit\n");
        if (scanf("%d", &opt) == 1) {
            return opt;
        } else {
            printf("Invalid input\n");
            scanf("%*[^\n]");  // consume the offending input
            return -1;
        }
    }
    
    void InitStack(Stack *s) {
        int len;
        printf("Enter the length of stack : ");
        if (scanf("%d", &len) != 1 || len <= 0) {
            printf("invalid input\n");
            scanf("%*[^\n]");  // consume the offending input
            exit(1);
        }
        s->sp = -1;
        s->len = len;
        s->stack = calloc(len, sizeof(*s->stack));
        if (s->stack == NULL) {
            printf("Insufficient Memory\n");
            exit(1);
        } else {
            printf("Memory allocated successfully\n");
        }
    }
    
    void FreeStack(Stack *s) {
        free(s->stack);
        s->len = 0;
        s->sp = -1;
    }
    
    int main(void) {
        Stack s;
        InitStack(&s);
        while (1) {
            switch (Option()) {
            case 1:
                Push(&s);
                break;
            case 2:
                Pop(&s);
                break;
            case 3:
                Peek(&s);
                break;
            case 4:
                Display(&s);
                break;
            case 5:
                FreeStack(&s);
                return 0;
            default:
                printf("Invalid choice\n");
                break;
            }
        }
    }