如何在PHP中验证方程字符串中的括号

时间:2013-03-31 10:33:18

标签: php string validation math

如果有一个善于PHP的人可以建议如何在表达式中验证括号,我会徘徊:

    ( 5 * 3 [ 6 ) - 6]

这是错误的表达方式。我需要一个功能来做到这一点。这是我到目前为止所尝试的:

<?php
function hasMatchedParenthesis($string) {

$counter1 = 0;
$counter2 = 0;

$length = strlen($string);

for ($i = 0;$i < $length; $i++) {
    $char = $string[$i];
    if( $char == '(' ) {
        $counter1 ++;
    } elseif( $char == ')' ) {
        $counter1 --;
    }

        for($j =0;$j < $length; $j++) {
            $char = $string[$j];
            if( $char == '[' ) {
                $counter2 ++;
        } elseif( $char == ']' ) {
                $counter2 --;
        }

        }


    if( $counter1 < 0 || $counter2 < 0) {
        return false;
    }

}

echo 'ok';;

}


hasMatchedParenthesis('[5] * 3 - ( 4 - 7 * [3-6])'); // this is ok!

hasMatchedParenthesis('( 5 * 3 [ 6 ) - 6]'); // this returns as TRUE, but it is not!

?>

请帮助我解决'[6)'问题的验证!我不知道怎么做:(

3 个答案:

答案 0 :(得分:9)

我想到的第一个想法是使用堆栈。 PHP提供了两个函数来将数组视为堆栈:array_pusharray_pop。我们可以使用它们创建一堆0(我们在一个开头(内)和1(我们在[内),并在每个结束括号时匹配我们插入的最后一个值:

function hasMatchedParenthesis($string) {
    $len = strlen($string);
    $stack = array;
    for ($i = 0; $i < $len; $i++) {
        switch ($string[$i]) {
            case '(': array_push($stack, 0); break;
            case ')': 
                if (array_pop($stack) !== 0)
                    return false;
            break;
            case '[': array_push($stack, 1); break;
            case ']': 
                if (array_pop($stack) !== 1)
                    return false;
            break;
            default: break;
        }
    }
    return (empty($stack));
}

请注意,您可以将其扩展为包括{}在内的任何其他字符对:

case '{': array_push($stack, 2); break;
case '}': 
    if (array_pop($stack) !== 2)
        return false;
break;

答案 1 :(得分:1)

验证此类语法规则的常用方法是使用Context-free grammar - 请参阅examples,您将找到您正在尝试做的事情作为示例:-)并且您可以申请马克贝克指出,使用词法分析器这样的语法规则 在您的代码中,您只需要确保左括号的数量与右括号的数量相匹配,这就是缺陷。正如我在评论中指出的那样,你的最后一个条件应该是

if ($counter1 != 0 || $counter2 != 0){
    return false;
}

在当前情况下,当任何计数器为true时,将返回>=0。尝试使用一个简单的案例hasMatchedParenthesis('[5] * 3 - ( 4 - 7 * [3-6');,即使它出错也会返回true

答案 2 :(得分:0)

我在实现后写了。

function check_brackets_balance($string, $bracket_map = false) {
    $bracket_map = $bracket_map ?: [ '[' => ']', '{' => '}', '(' => ')' ];
    $bracket_map_flipped = array_flip($bracket_map);
    $length = mb_strlen($string);
    $brackets_stack = [];
    for ($i = 0; $i < $length; $i++) {
        $current_char = $string[$i];
        if (isset($bracket_map[$current_char])) {
            $brackets_stack[] = $bracket_map[$current_char];
        } else if (isset($bracket_map_flipped[$current_char])) {
            $expected = array_pop($brackets_stack);
            if (($expected === NULL) || ($current_char != $expected)) {
                return false;
            }
        }
    }
    return empty($brackets_stack);
}

它也使用堆栈,但代码较少,并为您自己的括号集提供了额外的参数。

check_brackets_balance('[5] * 3 - ( 4 - 7 * [3-6])'); // true
check_brackets_balance('( 5 * 3 [ 6 ) - 6]')); // false