【问题标题】:How to validate brackets in equation string in PHP如何在PHP中验证方程式字符串中的括号
【发布时间】:2013-03-31 10:33:18
【问题描述】:

如果有人擅长 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]”的验证问题!我不知道该怎么做:(

【问题讨论】:

  • 你允许嵌套括号吗?例如((1 + 3) / (2 - 5)) + 5... 如果是这样,最好使用适当的词法分析器
  • 我认为你的检查条件不对。应该是if ($counter1 != 0 || $counter2 != 0){ return false; }。您从两个计数器 0 开始,当您完成验证括号是否有效时,它们都应该是 0。这是对@MarkBaker 评论的补充:-)
  • ircmaxell 对stackoverflow.com/questions/12692727/… 的回答是一个很好的数学公式词法分析器(如果你也需要解析器)的起点

标签: php string validation math


【解决方案1】:

我想到的第一个想法是使用堆栈。 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 智能简约。此外,堆栈机器正是用于检查字符串是否属于由上下文无关语法定义的语言。
  • 好方法。我会将( / [ 本身推入堆栈并在弹出时检查) / ]
  • $len = mb_strlen($string); $stack = array();
【解决方案2】:

验证此类语法规则的常用方法是使用Context-free grammar - 请参阅examples,您会发现您正在尝试执行的操作作为示例 :-) 您可以应用此类规则正如 Mark Ba​​ker 所指出的,使用词法分析器的语法。
在您的代码中,您只需要确保左括号的数量与右括号的数量相匹配,这就是缺陷。同样正如我在评论中指出的那样,您的最后一个条件应该是

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

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

【讨论】:

  • 您好,您有一些链接可以查看如何在 php 中应用此 Context-free-grammar 吗?对这个问题进行同样的验证
  • @EmilioGort 你可以在网上find some resources
【解决方案3】:

我写了以下认识。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    • 2016-03-07
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 2016-12-09
    • 2016-11-20
    相关资源
    最近更新 更多