Home > Net >  Using C to determine if a string contains any imbalanced brackets
Using C to determine if a string contains any imbalanced brackets

Time:03-07

I am completing some course work and stuck at this final hurdle! I need to identify if a string contains any bracket imbalances, but I can only use C. I have read that this is a very popular interview question used by some organisations. I have a solution, but I know it is not correct, the answer requires using the stack to push and pop variables. Does anyone have any advice? I appologies for my naivety.

Here is my solution:

int balanced(char line [LINE_LENGTH])
{
    int bracketCount = 0;
        
    for (int counter = 0 ; counter < strlen(line) ; counter  )
    {
        if (line[counter] == '[' || line[counter] == ']' || line[counter] == '(' || line[counter] == ')' || line[counter] == '{' || line[counter] == '}')
        { 
            bracketCount  ;
        }
    }
    return bracketCount;
}

CodePudding user response:

Here is one approach to find out if a string of brackets is balanced or not.

#include <stdio.h>
#include <string.h>
#define log(...) fprintf(stderr, __VA_ARGS__)

static inline int is_opening_bracket (int ich) {
    switch (ich) {
    case '{':    case '(':    case '[':
        return 1;
    default:
        return 0;
    }
}

static inline int is_closing_bracket (int ich) {
    switch (ich) {
    case '}':    case ')':    case ']':
        return 1;
    default:
        return 0;
    }
}

/**
 * Opening Brackets : [ { (
 * Closing Brackets : ] } )
 * Balanced : No overlapping of brackets & every open has a matching close
 * Example :    {[({})]} - balanced
 *              {[(}{)]} - unbalanced
 * Function returns on first detection of any error
 */
int check_bracket_balance (const char* brkts, const int slen)
{
    if (!brkts || !(*brkts) || slen < 0) return -1;

    char matchBkt[256] = {0}; // makes matching easier
    matchBkt[ (unsigned) '}'] = '{';
    matchBkt[ (unsigned) ']'] = '[';
    matchBkt[ (unsigned) ')'] = '(';

    char bStack [slen   1]; // array stack emulation
    int sTop = -1;
    for (int bi = 0; bi < slen;   bi) {
        int ich = (unsigned) brkts[bi];
        if (is_opening_bracket(ich))
            bStack[  sTop] = ich;       // push on to stack
        else if (is_closing_bracket(ich)) {           // a closing bracket
            if (sTop < 0)               // Stack was empty
                return 1;               // closing bracket before an open
            if (bStack[sTop] == matchBkt[ich])  // is stack top a matching bracket
                --sTop;                 // pop matching bracket from stack
            else
                return 2; // bracket mismatch
        } else // invalid character
            return -2;  // define enums like eInvBracketChar for easier code-read
    }
    if (sTop >= 0) return 3;  // brackets incomplete = mismatch

    return 0; // balanced
}


#define MAX_STRINGS 7
int main ()
{
    log("\n");
    char* strings[MAX_STRINGS] = {"{([])}",
        "{}()[]",
        "{})([]",
        "{([)]}",
        "{{(([[",
        "",
        "{}<>{}"
    };
    for (int si =0; si < MAX_STRINGS;   si) {
        log ("\n%s", strings[si]);
        int error = check_bracket_balance (strings[si], strlen (strings[si]));
        if (error) // handle negative / positive errors separately?
            log ("\tERROR[%d]: Brackets not Balanced", error);
        else
            log ("\tBrackets Balanced");
    }

    log("\n");
    return 0;
}

CodePudding user response:

Your solution is incorrect: you increment bracketCount for both types of brackets, so the function just returns the total number of brackets, it does not check for proper balancing.

You could improve your approach by incrementing bracketCount for opening brackets and decrementing it on closing brackets: this would detect missing brackets but not imbalance nor mismatched brackets.

You could use different counters for {, [ and ( and keep track of bracket types separately, but you still would not detect nesting errors as in "([)]"

To implement a proper checker, you need to store the opening brackets in a stack where you can check for each closing bracket that it matches the currently open one.

Here is a simple implementation using an array of char as a stack:

int balanced(const char *line) {
    char brackets[LINE_LENGTH];
    char *bp = brackets   LINE_LENGTH;

    *--bp = '\0';
    for (size_t i = 0; line[i] != '\0'; i  ) {
        char cc;
        switch (line[i]) {
          case '[':
            cc = ']';
            break;
          case '(':
            cc = ')';
            break;
          case '{':
            cc = '}';
            break;
          case ']':
          case ')':
          case '}':
            if (*bp == '\0') {
                /* stack is empty: unexpected closing bracket */
                printf("offset %zu: no opening bracket for '%c'\n",
                       i, line[i]);
                return 0;
            }
            if (*bp != line[i]) {
                /* nesting error: closing bracket does not match the expected type */
                printf("offset %zu: bad bracket type for '%c', expected '%c'\n",
                       i, line[i], *bp);
                return 0;
            }
            bp  ;
            continue;
          default:
            continue;
        }
        if (bp == brackets) {
            /* stack overflow */
            printf("too many open brackets\n");
            return -1;
        }
        *--bp = cc;  /* push the expected closing bracket */
    }
    if (*bp) {
        /* some opening brackets have not been closed */
        printf("missing brackets: %s\n", bp);
        return 0;
    }
    return 1;    
}
  •  Tags:  
  • c
  • Related