设置三个计数器初值设为零,分别记录小括号、中括号、大括号。开始进行第一次扫描,从左向右依次扫描每个字符,遇到左括号计数器加一,遇到右括号计数器减一,出现计数器小于零时,报错退出。扫描结束后,若三个计数器有一个不为零说明括号不匹配,报错结束检查。
第一步扫描结束,如果正确说明三种括号本身匹配正确。现在可能出现的错误只可能是不同括号出现交叉,比如 {(}{)},({[)]}。
计数器清零,现在从左向右依次扫描每个字符,直到遇到右括号,计数器加一,然后逆向扫描右括号之前的字符。遇到右括号计数器加一,遇到左括号计数器减一,直到遇到与开始处同类型的左括号,而且此类型计数器为零,如果此时其他两种括号计数器有不为零的,一定是存在交叉错误,报错结束扫描。否则计数器清零,继续向右扫描找到下一个右括号,重复上述操作直到扫描完整个字符串。
对于嵌套括号的处理做了优化,扫描速度倍增。
#define _using_goto_in_bracketsmatchingcheck_ 1
/*
参数:szsrc 为待检测字符串。
返回值:括号匹配正确 返回1值,否则返回0值。
*/
int bracketsmatchingcheck(const char *szsrc)
{
const char *ptr = szsrc;
const char *ptrlaststart;
const char *ptrlastend;
const char *ptrnowend = NULL;
char c;
char ch;
long parenthesis = 0; /* ()计数器 */
long brackets = 0; /* []计数器 */
long braces = 0; /* {}计数器 */
if (szsrc == NULL)
return 1;
while((int)(c = *ptr++)) /* 第一次扫描 */
{
scanfir:
if (c == '(')
{
++parenthesis;
#ifdef _using_goto_in_bracketsmatchingcheck_
if ((int)(c = *ptr++))
goto scanfir;
break;
#endif
}
else if (c == ')')
{
if (parenthesis == 0)
return 0;
--parenthesis;
#ifdef _using_goto_in_bracketsmatchingcheck_
if ((int)(c = *ptr++))
goto scanfir;
break;
#endif
}
else if (c == '[')
{
++brackets;
#ifdef _using_goto_in_bracketsmatchingcheck_
if ((int)(c = *ptr++))
goto scanfir;
break;
#endif
}
else if (c == ']')
{
if (brackets == 0)
return 0;
--brackets;
#ifdef _using_goto_in_bracketsmatchingcheck_
if ((int)(c = *ptr++))
goto scanfir;
break;
#endif
}
else if (c == '{')
{
++braces;
#ifdef _using_goto_in_bracketsmatchingcheck_
if ((int)(c = *ptr++))
goto scanfir;
break;
#endif
}
else if (c == '}')
{
if (braces == 0)
return 0;
--braces;
}
}
if (parenthesis != 0 || brackets != 0 || braces != 0) /* 括号不匹配,退出 */
return 0;
ptr = szsrc;
while((int)(ch = *ptr)) /* 第二次扫描 */
{
scansec:
if (ch == ']')
{
const char *ptr1 = ptr - 1;
ptrlastend = ptrnowend;
ptrnowend = ptr;
parenthesis = 0;
brackets = 1;
braces = 0;
while(1)
{
if ((c = *ptr1) == ')')
{
++parenthesis;
--ptr1;
continue;
}
else if (c == '(')
{
if (parenthesis == 0)
return 0;
--parenthesis;
--ptr1;
continue;
}
else if (c == '[')
{
if ((--brackets) == 0)
{
if (parenthesis == 0 && braces == 0)
{
#ifdef _using_goto_in_bracketsmatchingcheck_
if ((int)(ch = *(++ptr)))
{
ptrlaststart = ptr1;
goto scansec;
}
return 1;
#else
ptrlaststart = ptr1;
break;
#endif
}
return 0;
}
--ptr1;
continue;
}
else if (c == ']')
{
if (ptr1 == ptrlastend)
{
(ptr1 = ptrlaststart)--;
continue;
}
++brackets;
--ptr1;
continue;
}
else if (c == '}')
{
if (ptr1 == ptrlastend)
{
(ptr1 = ptrlaststart)--;
continue;
}
++braces;
--ptr1;
continue;
}
else if (c == '{')
{
--braces;
--ptr1;
}
}
}
else if (ch == '}')
{
const char *ptr1 = ptr - 1;
ptrlastend = ptrnowend;
ptrnowend = ptr;
parenthesis = 0;
brackets = 0;
braces = 1;
while(1)
{
if ((c = *ptr1) == ')')
{
++parenthesis;
--ptr1;
continue;
}
else if (c == '(')
{
if (parenthesis == 0)
return 0;
--parenthesis;
--ptr1;
continue;
}
else if (c == '{')
{
if ((--braces) == 0)
{
if (parenthesis == 0 && brackets == 0)
{
#ifdef _using_goto_in_bracketsmatchingcheck_
if ((int)(ch = *(++ptr)))
{
ptrlaststart = ptr1;
goto scansec;
}
return 1;
#else
ptrlaststart = ptr1;
break;
#endif
}
return 0;
}
--ptr1;
continue;
}
else if (c == '}')
{
if (ptr1 == ptrlastend)
{
(ptr1 = ptrlaststart)--;
continue;
}
++braces;
--ptr1;
continue;
}
else if (c == ']')
{
if (ptr1 == ptrlastend)
{
(ptr1 = ptrlaststart)--;
continue;
}
++brackets;
--ptr1;
continue;
}
else if (c == '[')
{
--brackets;
--ptr1;
}
}
}
++ptr;
}
return 1;
}