Program in c regarding balance of parenthesis using stack not working

Viewed 90

I wrote this program in c to check whether the parenthesis is balanced or not using the concept of stack.

#include<stdio.h>
#include<string.h>
#define MAX 100

int top = -1;
int arr[MAX];


void push(int x)
{
    if (top == (MAX - 1))
    {
        printf("error:stack overflow n");
        return;
    }
    top++;
    arr[top] = x;
}
void pop()
{
    top--;
}
int empty()
{
    
    if (top == -1)
    {
        printf("The stack is empty \n ");
        return 1;
    }
    else{
        return 0;
    }
}

int main()
{
    char str[30];int len;int i;int temp;
    printf("Enter he expression \n ");
    scanf("%d",str);
    len=strlen(str);

    for(i=0;i<len;i++)
    {

        if (str[i] == '(' || str[i] == '{' || str[i] == '[')
        {
            push(str[i]);
        }

        if (str[i] == ')' || str[i] == '}' || str[i] == ']')
        {
            temp=empty();
            if((empty())==1)
            {
                printf("Unbalanced\n ");
                return;
            }
            else if(str[i]==arr[top])
            {
                pop();
            }
        }
    }

   if((empty())==1)
   {
    printf("Balanced\n");
    
   }
   else {
    printf("unbalanced\n");
   }
    
    
    return 0;
}

however whatever the input i give the result i am getting is

Enter he expression
 {{{]])
empty happend
Balanced

i have isolated the problem where my push and pop function are not being called,and the stack is empty regardless of the input. any idea how to fix the code?

3 Answers

If one wanted (, [, { to be indistinguishable, one doesn't need O(length) space. An O(1) counter of how many parentheses/braces/brackets are currently at the position of the string would do. You can do more storing the arr queue; that is, find mismatches in the types of braces. I wrote my own quick parentheses checker, and discovered:

I would say there are 4 exception conditions to a passing valid input. In addition to a passing test, I would make sure to engineer a test for all four failing tests,

  • stack overflow: there are too many nesting levels for the fixed-size stack;
  • underflow: there are too many closing braces;
  • mismatch: one type of brace opened, but another closed; this is entirely missing from the original code;
  • unclosed: there are braces left in your stack but the input has ended.

One may want to automate this process, but the input has to be abstracted. Using #include <assert.h>.

assert(check("([{}({}[])]())") != 0);
assert(check("(") == 0);
assert(check("]") == 0);
...
printf("Enter he expression \n ");
if(!fgets(str, sizeof str, stdin)) return perror("input"), EXIT_FAILURE;
printf("%s\n", check(str) ? "Balanced" : "unbalanced");

I used the queue as what one expects; this is different for every character. Instead of a series of ifs, I used a switch statement. I changed the prototype for pop() to return the former top element and push() to return a boolean that it was successful (that is, not a stack overflow.) With this, for every byte, I wrote,

expect = 0;
switch(str[i]) {
case '\0':
    if(!empty()) raise unclosed;
    return;
case '(': expect = ')'; break;
case '[': expect = ']'; break;
case '{': expect = '}'; break;
case ')': case ']': case '}':
    if(empty()) raise underflow;
    if(pop() != str[i]) raise mismatch;
default: ; /* sic, everything else ignored */
}
if(expect && !push(expect)) raise overflow;

Where raise is dependent on the specificity one requires. Immediately report? With #include <stdbool.h>, raise -> return false; return -> return true. If one wanted be more specific, maybe return an exception value, enum { okay, unclosed, underflow, mismatch, overflow }. Or use goto to have more information about the context.

There are two problems.

  • First one is the scan should be %s not %d.
  • second one you pop if(str[i] == arr[Top]) which is always false, so the stack will remain full.

The code below should work fine.

#include <stdio.h>
#include <string.h>
#define MAX 100

int top = -1;
int arr[MAX];

void push(int x)
{
    if (top == (MAX - 1))
    {
        printf("error:stack overflow n");
        return;
    }
    top++;
    arr[top] = x;
}
void pop()
{
    top--;
}
int empty()
{
    if (top == -1)
    {
        printf("The stack is empty \n ");
        return 1;
    }
    return 0;   
}

int main()
{
    char str[30];
    int len;
    int i;
    int temp;
    printf("Enter he expression \n ");
    scanf("%s", str);
    len = strlen(str);
    for (i = 0; i < len; i++)
    {
        if (str[i] == '(' || str[i] == '{' || str[i] == '[')
        {
            push(str[i]);
            continue;
        }
        if (str[i] == ')' || str[i] == '}' || str[i] == ']')
        {
            if (empty())
            {
                printf("Unbalanceddd\n ");
                return;
            }
            pop();
        }
    }

    if (empty())
    {
        printf("Balanced\n");
    }
    else
    {
        printf("unbalanced\n");
    }
    return 0;
}

Edit:

The code above is just fixing the error of stack. The one below will check for each pair of the three.

#include <stdio.h>
#include <string.h>
#define STACK_MAX 100

int stack[STACK_MAX];
int top = -1;
void push(int x);
int pop();
int peek();
int isEmpty();

int main()
{
    char str[STACK_MAX * 2];
    printf("Enter he expression \n ");
    scanf("%s", str);
    int len = strlen(str);

    for (int i = 0; i < len; i++)
    {
        if (str[i] == '(' || str[i] == '{' || str[i] == '[')
        {
            push(str[i]);
            continue;
        }
        if (str[i] == ')' || str[i] == '}' || str[i] == ']')
        {
            if (isEmpty())
            {
                printf("unbalanced\n");
                return 0;
            }
            const char left = peek();
            const char peek[3];
            sprintf(peek, "%c%c", left, str[i]);
            if (!(strcmp(peek, "()") == 0 || strcmp(peek, "[]") == 0 || strcmp(peek, "{}") == 0))
                break;
            pop();
        }
    }

    if (isEmpty())
    {
        printf("Balanced\n");
    }
    else
    {
        printf("unbalanced\n");
    }
    return 0;
}
// --------------------------------------
// Stack Implementation
// --------------------------------------
void push(int x)
{
    if (top + 1 == STACK_MAX)
    {
        printf("error:stack overflow \n");
        return;
    }
    stack[++top] = x;
}

int pop()
{
    if (top == -1)
    {
        printf("error: stack is empty \n");
        return -1;
    }
    return stack[top--];
}
int peek()
{
    if (top == -1)
    {
        printf("error: stack is empty\n");
        return -1;
    }
    return stack[top];
}
int isEmpty()
{
    return top == -1;
}

A fun project!

An alternative to function calls to push/pop values off a stack is to use 32 (or 64) bits of a variable to track the 3 different pairs of parentheses/brackets...

2 bits can represent 4 values. 0b00 is not useful as it cannot be distinguished from null (data), but 0b01, 0b10 & 0b11 can be harnessed to represent the each of the three pairs of interest.

In the code below, an unsigned int is the stack. Pushing two bits onto the stack involves a left shift and and OR. Popping is first testing the stack's two LSB's against what the character stream holds as a closing bracket, then right shifting the stack.

This is limited to 16 concurrent levels of nesting on my 32 bit compiler, but could go to 32 levels on a 64 bit compiler. Practically speaking, this should serve the majority of instances.

The code does detect/prevent stack over-/under-flow and bails out when detected.

#include <stdio.h>
#include <limits.h> // to determine 32 bit v. 64 bit

#if UINT_MAX = 0xffffffff // not sure this is right...???
typedef uint32_t stk_t;
#define FULL 0xC0000000 // b31 & b30 set
#else
typedef uint64_t stk_t;
#define FULL 0xC000000000000000 // b63 & b62 set
#endif

int balChk( char *str ) {
    stk_t stk = 0;
    char *sel = "(){}[]";

    int ret = 0;
    for( char *cp = str; !ret && *cp; cp++ ) {
        for( char *bp = sel; *bp && *bp != *cp; bp++ ) {} // loop
        if( !*bp ) continue; // not interesting character
        if( (bp-sel)%2 == 0 ) { // 0,2,4 means push
            if( stk & FULL ) {
                printf( "Stack full - " );
                ret = -1;
            }
            // pushes encoded matching close ')', '}' or ']'
            stk = stk<<2 | ((bp-sel)+2)>>1; // use [2,4,6]/2 = 1,2,3
        }
        else // 1,3,5 means pop
        {
            // have stk item AND two LSBs match ([1,3,5]+1)/2 = 1,2,3
            // compare encoded close with "top of stack" (ie: 2 LSBs )
            if( !stk || (stk&3) != (bp-sel+1)>>1 ) {
                printf( !stk ? "Stack empty - " : "Unmatched '%c' - ", *cp );
                ret = -1;
            }
            stk >>= 2;
        }
    }
    return ret + stk; // 0 means good
}

int main() { // test a few variations
    char *strs[] = {
        "()", "{}", "[]", "((()))", "(([()]))",
        "(((([ (((([ (((([", // 15
        "(((([ (((([ (((([ [", // 16
        "(((([ (((([ (((([ [{", // 17 too many for my 32bit compiler
        "(((([ (((([ (((([ []{", // 16-1+1
        "{ ({()}) ((())) []        }",
        "{ ({()}) ((())) [] missing!",
        "{ ({()}) ((())) []          }",
        "{ ({()}) ((())) [] too many }}",
    };

    for( int i = 0; i < sizeof strs/sizeof strs[0]; i++ )
        printf( "'%s' - %s\n", strs[i], balChk( strs[i] ) ? "Bad" : "Good" );

    return 0;
}

Output

'()' - Good
'{}' - Good
'[]' - Good
'((()))' - Good
'(([()]))' - Good
'(((([ (((([ (((([' - Bad // but 15 passed
'(((([ (((([ (((([ [' - Bad // but 16 passed
Stack full - '(((([ (((([ (((([ [{' - Bad // 17 popped the stack
'(((([ (((([ (((([ []{' - Bad // 16 - 1 + 1 passed
'{ ({()}) ((())) []        }' - Good
'{ ({()}) ((())) [] missing!' - Bad
'{ ({()}) ((())) []          }' - Good
Stack empty - '{ ({()}) ((())) [] too many }}' - Bad // Excessive popping

All-in-all, a fun project...

Related