简体   繁体   English

递归检查C中方程的括号平衡

[英]Recursively check parenthesis balance of an equation in C

I am trying to write a program in C that recursively checks the balance of an equations parenthesis. 我试图用C编写一个程序,该程序递归检查方程式括号的平衡。 Ie for every open there is a closing. 即,每次打开都有一个关闭。

This is what I currently have, but I can't get it to ignore characters and spaces. 这是我目前拥有的,但是我无法忽略字符和空格。

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

#define MAX_SIZE 100

struct Stack{
    int top;
    char arr[MAX_SIZE];
} st;

void init(){
    st.top = -1;
}

bool isEmpty(){
    if(st.top == -1){
        return true;
    }else{
        return false;
    }
}

bool isFull(){
    if(st.top == MAX_SIZE-1){
        return true;
    }else{
        return false;
    }
}

void push(char item){
    if(isFull()){
            printf("Stack is full");
            exit(0);
    }else{
        st.top++;
        st.arr[st.top] = item;
    }
}

void pop(){
    if(isEmpty()){
        printf("Stack is empty");
        exit(0);
    }else{
        st.top--;
    }
}

char gettop(){
    return st.arr[st.top];
}

bool ArePair(char opening,char closing)
{
        if(opening == '(' && closing == ')') return true;
        else if(opening == '{' && closing == '}') return true;
        else if(opening == '[' && closing == ']') return true;
        return false;
}

void main()
{
    char in_expr[MAX_SIZE],a,temp;
    int length=0,i,j,count;

    init();
    printf("Enter an expression to check:");
    scanf("%s", in_expr);
    length = strlen(in_expr);

    for(i=0;i<length;i++){
         if (in_expr[i] !=  '(' && in_expr[i] != ')' && in_expr[i] != '{' && in_expr[i] != '}' && in_expr[i] != '[' && in_expr[i] !=  ']') {
                i++;
        }
        else if(in_expr[i] == '(' || in_expr[i] == '{' || in_expr[i] == '['){
                push(in_expr[i]);
                a = in_expr[i];
                printf("%c",a);
        }
        else if(in_expr[i] == ')' || in_expr[i] == '}' || in_expr[i] == ']'){
//                       a = st.arr[st.top];
                a = in_expr[i];
                printf("%c", a);
        }
        if(isEmpty() || !ArePair(gettop(),in_expr[i])){
          printf("\nInvalid expression - Not Balanced!\n");
                exit(0);
        }
        else{
                pop();
            }
        i++;
//        }
    }
    if(isEmpty()){
        printf("\nValid expression - Perfectly Balanced!\n");
    }else{
        printf("\nInvalid expression - Not Balanced!\n");
    }
}

Any help is greatly appreciated and if you need more details, don't hesitate to ask! 非常感谢您的帮助,如果您需要更多详细信息,请随时询问! If this is a duplicate I apologize, I am still searching for another solution through other posts here. 如果这很抱歉,我仍在通过此处的其他帖子搜索其他解决方案。

A few bugs: 一些错误:

Don't do i++ except in the for clause. 除了for子句,不要执行i++ You're [potentially] skipping past chars that you want to see. 您[潜在地]跳过了想要查看的字符。

Also, don't check for isEmpty or ArePair unless the current char is a closer. 另外, 除非当前字符更近,否则不要检查isEmptyArePair


Here's a corrected version [please pardon the gratuitous style cleanup]. 这是一个更正的版本[请原谅免费的样式清理]。 Note that there may be other bugs, but I think this will get you closer: 请注意,可能还有其他错误,但是我认为这将使您更加接近:

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

#define MAX_SIZE 100

struct Stack {
    int top;
    char arr[MAX_SIZE];
} st;

void
init()
{
    st.top = -1;
}

bool
isEmpty()
{
    if (st.top == -1) {
        return true;
    }
    else {
        return false;
    }
}

bool
isFull()
{
    if (st.top == MAX_SIZE - 1) {
        return true;
    }
    else {
        return false;
    }
}

void
push(char item)
{
    if (isFull()) {
        printf("Stack is full");
        exit(0);
    }
    else {
        st.top++;
        st.arr[st.top] = item;
    }
}

void
pop()
{
    if (isEmpty()) {
        printf("Stack is empty");
        exit(0);
    }
    else {
        st.top--;
    }
}

char
gettop()
{
    return st.arr[st.top];
}

bool
ArePair(char opening, char closing)
{
    if (opening == '(' && closing == ')')
        return true;
    else if (opening == '{' && closing == '}')
        return true;
    else if (opening == '[' && closing == ']')
        return true;
    return false;
}

void
main()
{
    char in_expr[MAX_SIZE],
     a,
     temp;
    int length = 0,
        i,
        j,
        count;

    init();
#if 0
    printf("Enter an expression to check:");
    scanf("%s", in_expr);
#else
    strcpy(in_expr,"( ( a + b ) * (c + d) ) * ( ( w + x ) * (y + z) )");
    //strcpy(in_expr,"( ( a + b ) * (c + d) ) * ( ( w + x ) * y + z) )");
#endif
    length = strlen(in_expr);

    for (i = 0; i < length; i++) {
        int chr = in_expr[i];
        printf("input: '%c'\n",chr);

        if (chr != '(' && chr != ')' && chr != '{' && chr != '}' && chr != '[' && chr != ']') {
            //i++;
            continue;
        }

        if (chr == '(' || chr == '{' || chr == '[') {
            push(chr);
            a = chr;
            printf("%c", a);
            continue;
        }

        if (chr == ')' || chr == '}' || chr == ']') {
            a = chr;
            printf("%c", a);
        }

        if (isEmpty() || !ArePair(gettop(), chr)) {
            printf("\nInvalid expression - Not Balanced!\n");
            exit(0);
        }
        else {
            pop();
        }
        //i++;
    }
    if (isEmpty()) {
        printf("\nValid expression - Perfectly Balanced!\n");
    }
    else {
        printf("\nInvalid expression - Not Balanced!\n");
    }
}

Here's a version that uses a switch statement that may be easier to read: 这是使用switch语句的版本,可能更易于阅读:

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

#define MAX_SIZE 100

struct Stack {
    int top;
    char arr[MAX_SIZE];
} st;

void
init()
{
    st.top = -1;
}

bool
isEmpty()
{
    if (st.top == -1) {
        return true;
    }
    else {
        return false;
    }
}

bool
isFull()
{
    if (st.top == MAX_SIZE - 1) {
        return true;
    }
    else {
        return false;
    }
}

void
push(char item)
{
    if (isFull()) {
        printf("Stack is full");
        exit(0);
    }
    else {
        st.top++;
        st.arr[st.top] = item;
    }
}

void
pop()
{
    if (isEmpty()) {
        printf("Stack is empty");
        exit(0);
    }
    else {
        st.top--;
    }
}

char
gettop()
{
    return st.arr[st.top];
}

bool
ArePair(char opening, char closing)
{
    if (opening == '(' && closing == ')')
        return true;
    else if (opening == '{' && closing == '}')
        return true;
    else if (opening == '[' && closing == ']')
        return true;
    return false;
}

void
main()
{
    char in_expr[MAX_SIZE],
     a,
     temp;
    int length = 0,
        i,
        j,
        count;

    init();
#if 0
    printf("Enter an expression to check:");
    scanf("%s", in_expr);
#else
    strcpy(in_expr,"( ( a + b ) * (c + d) ) * ( ( w + x ) * (y + z) )");
    //strcpy(in_expr,"( ( a + b ) * (c + d) ) * ( ( w + x ) * y + z) )");
#endif
    length = strlen(in_expr);

    for (i = 0; i < length; i++) {
        int chr = in_expr[i];
        printf("input: '%c'\n",chr);

        switch (chr) {
        case '(':
        case '{':
        case '[':
            push(chr);
            a = chr;
            printf("%c", a);
            break;
        }

        case ')':
        case '}':
        case ']':
            a = chr;
            printf("%c", a);
            if (isEmpty() || !ArePair(gettop(), chr)) {
                printf("\nInvalid expression - Not Balanced!\n");
                exit(0);
            }

            pop();
            break;
        }
    }

    if (isEmpty()) {
        printf("\nValid expression - Perfectly Balanced!\n");
    }
    else {
        printf("\nInvalid expression - Not Balanced!\n");
    }
}

Here's a version that adds a self test function that allows multiple unit tests. 这是一个添加了自测功能的版本,该功能允许进行多个单元测试。 It's what I've done when I've written expression parsers in the past. 这是我过去编写表达式解析器时所做的事情。

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

#define MAX_SIZE 100

struct Stack {
    int top;
    char arr[MAX_SIZE];
} st;

void
init()
{
    st.top = -1;
}

bool
isEmpty()
{
    if (st.top == -1) {
        return true;
    }
    else {
        return false;
    }
}

bool
isFull()
{
    if (st.top == MAX_SIZE - 1) {
        return true;
    }
    else {
        return false;
    }
}

void
push(char item)
{
    if (isFull()) {
        printf("Stack is full");
        exit(0);
    }
    else {
        st.top++;
        st.arr[st.top] = item;
    }
}

void
pop()
{
    if (isEmpty()) {
        printf("Stack is empty");
        exit(0);
    }
    else {
        st.top--;
    }
}

char
gettop()
{
    return st.arr[st.top];
}

bool
ArePair(char opening, char closing)
{
    if (opening == '(' && closing == ')')
        return true;
    else if (opening == '{' && closing == '}')
        return true;
    else if (opening == '[' && closing == ']')
        return true;
    return false;
}

// RETURNS: 1=balanced, 0=unbalanced
int
test_expr(const char *in_expr)
{
    int i;
    int length;

    //printf("\ntest_expr: '%s'\n",in_expr);

    init();
    length = strlen(in_expr);

    for (i = 0; i < length; i++) {
        int chr = in_expr[i];
        //printf("input: '%c'\n",chr);

        switch (chr) {
        case '(':
        case '{':
        case '[':
            push(chr);
            //printf("%c", chr);
            break;

        case ')':
        case '}':
        case ']':
            //printf("%c", chr);
            if (isEmpty() || !ArePair(gettop(), chr)) {
                printf("Invalid expression - Not Balanced!\n");
                return 0;
                exit(0);
            }

            pop();
            break;
        }
    }

    if (isEmpty()) {
        printf("Valid expression - Perfectly Balanced!\n");
        return 1;
    }
    else {
        printf("Invalid expression - Not Balanced!\n");
        return 0;
    }
}

void
testone(int expected,const char *expr)
{
    int isvalid;

    printf("\ntestone: '%s'\n",expr);
    isvalid = test_expr(expr);
    printf("%s\n", (isvalid == expected) ? "PASS" : "FAIL");
}

void
testall(void)
{

    testone(1,"( ( a + b ) * (c + d) ) * ( ( w + x ) * (y + z) )");
    testone(0," ( a + b ) * (c + d) ) * ( ( w + x ) * (y + z) )");
    testone(0,"( ( a + b ) * (c + d) ) * ( ( w + x ) * y + z) )");
    testone(0,"( ( a + b ) * (c + d) ) * ( ( w + x ) * (y + z) ");
    testone(0,"( ( a + b ) * (c + d) ) * ( ( w + x ) * (y + z )");
    testone(0,"( ( a + b ) * (c + d) ] * ( ( w + x ) * (y + z) )");
}

int
main(void)
{

#if 0
    char in_expr[MAX_SIZE];
    printf("Enter an expression to check:");
    scanf("%s", in_expr);
    test_expr(in_expr);
#else
    testall();
#endif

    return 0;
}

You can take a simpler approach with an incremental state that stores the pending blocks, for example a char array with the opening characters. 您可以采用具有存储待处理块的增量状态的更简单方法,例如,带有开头字符的char数组。

Here is the code: 这是代码:

#include <stdio.h>

#define MAX_EXPR  256
#define MAX_LEVEL  32

enum { EXPR_BALANCED, EXPR_TOO_DEEP, EXPR_PAREN_MISMATCH, EXPR_UNCLOSED_PAREN };

int check_balance(const char *expr) {
    char state[MAX_LEVEL];
    const char *p;
    int level = 0;
    state[level++] = 0;  // force mismatch on state[0]
    for (p = expr; *p; p++) {
        switch (*p) {
          case '(':
          case '{':
          case '[':
            if (level >= MAX_LEVEL)
                return EXPR_TOO_DEEP;
            state[level++] = *p;
            break;
          case ')':
            if (state[--level] != '(')
                return EXPR_PAREN_MISMATCH;
            break;
          case '}':
            if (state[--level] != '{')
                return EXPR_PAREN_MISMATCH;
            break;
          case ']':
            if (state[--level] != '[')
                return EXPR_PAREN_MISMATCH;
            break;
        }
    }
    if (level != 1)
        return EXPR_UNCLOSED_PAREN;

    return EXPR_BALANCED;
}

int main() {
    char expr[MAX_EXPR];

    printf("Enter expressions to check, one per line: ");
    while (fgets(expr, sizeof expr, stdin) {
         switch (check_balance(expr)) {
           case EXPR_TOO_DEEP:
             printf("too many nesting levels\n");
             break;
           case EXPR_PAREN_MISMATCH:
             printf("closing character mismatch\n");
             break;
           case EXPR_UNCLOSED_PAREN:
             printf("closing character missing\n");
             break;
           case EXPR_BALANCED:
             printf("expression is balanced\n");
             break;
         }
    }
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM