简体   繁体   English

c 中关于使用堆栈的括号平衡的程序不起作用

[英]Program in c regarding balance of parenthesis using stack not working

I wrote this program in c to check whether the parenthesis is balanced or not using the concept of stack.我在c中写了这个程序,使用堆栈的概念检查括号是否平衡。

#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.我已经隔离了我的pushpop function 没有被调用的问题,并且无论输入如何,堆栈都是空的。 any idea how to fix the code?知道如何修复代码吗?

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:如果想要(, [, {无法区分,则不需要O(length)空间O(1)计数器当前在字符串的 position 上有多少个括号/大括号/括号就可以了。你可以做更多的存储arr队列;也就是说,查找大括号类型中的不匹配。我编写了自己的快速括号检查器,并发现:

I would say there are 4 exception conditions to a passing valid input.我想说传递有效输入有 4 个异常条件。 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> .使用#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");

What one expects is different for every character.每个角色的期望都不同。 Instead of a series of ifs , I would use a switch statement.而不是一系列ifs ,我会使用switch语句。 Something like,就像是,

expect = 0;
switch(str[i]) {
case '\0':
    if(!empty()) /* unclosed */
    /* end of string */;
case '(': expect = ')'; break;
case '[': expect = ']'; break;
case '{': expect = '}'; break;
case ')': case ']': case '}':
    if(empty()) /* underflow */;
    if(pop() != str[i]) /* pop returns top now; mismatch */;
default: ; /* sic, everything else ignored */
}
if(expect) push(expect); /* overflow is contained in there */

There are two problems.有两个问题。

  • First one is the scan should be %s not %d.第一个是扫描应该是 %s 而不是 %d。
  • second one you pop if(str[i] == arr[Top]) which is always false, so the stack will remain full.第二个你弹出 if(str[i] == arr[Top]) 总是假的,所以堆栈将保持满。

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

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... function 调用从堆栈中推送/弹出值的替代方法是使用变量的 32 位(或 64 位)来跟踪 3 对不同的括号/括号...

2 bits can represent 4 values. 2 位可以表示 4 个值。 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. 0b00 没有用,因为它无法与 null(数据)区分开来,但可以利用 0b01、0b10 和 0b11 来表示三对兴趣中的每一对。

In the code below, an unsigned int is the stack.在下面的代码中, unsigned int是堆栈。 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.弹出首先测试堆栈的两个 LSB 与字符 stream 作为右括号的内容,然后右移堆栈。

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.这在我的 32 位编译器上仅限于 16 个并发嵌套级别,但在 64 位编译器上可以 go 到 32 级。 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 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...总而言之,一个有趣的项目......

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

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