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

时间:2018-05-07 02:35:15

标签: c recursion stack

我正在尝试用C语言编写一个递归检查方程式括号的平衡的程序。即每次开放都有收盘。

这就是我现在所拥有的,但我无法忽略字符和空格。

#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");
    }
}

非常感谢任何帮助,如果您需要更多详细信息,请不要犹豫!如果这是重复我道歉,我仍在通过其他帖子搜索另一个解决方案。

2 个答案:

答案 0 :(得分:2)

一些错误:

i++子句外,不要for。你[可能]跳过你想要看到的过去的字符。

另外,请不要检查isEmptyArePair ,除非当前的char更接近。

这是一个更正版本[请原谅无偿风格的清理]。请注意,可能还有其他错误,但我认为这会让您更接近:

#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");
    }
}

这是一个使用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");
    }
}

这是一个添加自检功能的版本,允许多个单元测试。这就是我在过去编写表达式解析器时所做的事情。

#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;
}

答案 1 :(得分:0)

您可以采用更简单的方法,使用存储挂起块的增量状态,例如带有开头字符的char数组。

以下是代码:

#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;
}