花括号匹配 c实现

花括号的匹配。从逻辑上看,分几种形式:

{ { { }}}
{ {} {} }
{} {} {}

以上3种都是匹配的。所以逻辑处理的时候要考虑这些情况。

简单说一下判断逻辑:

  1. 遇到 {的时候,检查一下之前是否有过 },如果有就要去消掉对应记录;如果} 数量大于 {了,说明必然匹配失败了,直接不需要检查后面的结束匹配验证;如果之前没有出现过},那就直接统计。
  2. 如果遇到} 就直接统计就好了,不用做什么处理,并且此后就不能继续统计{了,直到}的记录全被消掉才可以。

给出一个通用的实现方案:

// 通用实现方案,匹配花括号。(输入与匹配的逻辑分离。)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LEFT '{'
#define RIGHT '}'

int match(int a, int b)
{
    return a == b;
}

void check(char *str)
{
    int len = strlen(str);
    int ch;
    int f = 0, s = 0;
    int stopLeftcollect = 0;
    int earlyFail = 0;
    for (int i = 0; i < len; ++i)
    {
        ch = str[i];
        if (LEFT == ch)
        {
            if (s > 0)
            {
                if (s <= f)
                {
                    f = 1 + (f - s);
                    stopLeftcollect = 0;
                    s = 0;
                }
                else
                {
                    printf("======= current line braces match FAIL#\n");
                    earlyFail = 1;
                    break;
                }
            }
            else
            {
                if (!stopLeftcollect)
                {
                    f++;
                }
            }
        }
        else if (RIGHT == ch)
        {
            stopLeftcollect = 1;
            s++;
        }
    }

    if (!earlyFail)
    {

        if (f == s)
        {
            printf("======= #current line braces match ok\n");
        }
        else
        {
            printf("======= #current line braces match FAIL#\n");
        }
    }
}

int main(int argc, char *argv[])
{

    char str[1000];
    while (gets(str) != NULL)
    {
        printf("origin: %s\n", str);
        check(str);
    }

    return 0;
}

==== 通用的方案当然好,但是因为不知道用户的输入程度,直接申请了长度为1000的数组,这样容易造成内存的浪费。

那么,如果直接去一个字符一个字符的判断,就不用申请一个大的数组了。只是,这样也是有利有弊。弊端就是这样的处理逻辑无法通用,只能用于处理控制台输入的,输入与匹配的逻辑耦合在一起了。

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

#define LEFT '{'
#define RIGHT '}'

int match(int a, int b)
{
    return a == b;
}

void checkBraces()
{
    int ch;
    int f = 0, s = 0;
    int stopLeftcollect = 0;
    int earlyFail = 0;
    // 两种情况,一种: {a{b{c}d}e}
    // 这种的处理方式就很简单,就是遇到第一个 } 就停止对{ 进行计数,并开始对 } 进行计数,结束后比较二者数量即可。
    // 两种情况,二种: {s}{w}{k}
    // 这种需要在第二个 { 的时候就比较前一次 的 {,}的数量然后清空计数再次分别统计。
    while ((ch = getchar()) != EOF && ch != '\n')
    {
        if (LEFT == ch)
        {
            if (s > 0)
            {
                if (s <= f)
                {
                    f = 1 + (f - s);
                    stopLeftcollect = 0;
                    s = 0;
                }
                else
                {
                    printf("======= current line braces match FAIL#\n");
                    earlyFail = 1;
                    break;
                }
            }
            else
            {
                if (!stopLeftcollect)
                {
                    f++;
                }
            }
        }
        else if (RIGHT == ch)
        {
            stopLeftcollect = 1;
            s++;
        }

        // putchar(ch);
    }
    printf("EXIT WHILE $$$$$$.\n");
    if (!earlyFail)
    {

        if (f == s)
        {
            printf("======= #current line braces match ok\n");
        }
        else
        {
            printf("======= #current line braces match FAIL#\n");
        }
    }
    while (earlyFail && (ch = getchar()) != '\n')
    {
        ;
    }
    if (ch == '\n')
    {
        printf("NEXT LINES\n");
        checkBraces();
    }
    else
    {
        printf("who you are? %c\n", ch);
        // logic error.
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[])
{

    printf("check match of braces. INPUT:\n");
    checkBraces();
    return 0;
}

执行效果如下:

{}
origin: {}
======= #current line braces match ok
{}{}
origin: {}{}
======= #current line braces match ok
{{},{}cc{}}
origin: {{},{}cc{}}
======= #current line braces match ok
{}}
origin: {}}
======= #current line braces match FAIL#
{{x},{wq}}
origin: {{x},{wq}}
======= #current line braces match ok
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值